@arktype/util
Advanced tools
Comparing version 0.3.0 to 0.5.0
@@ -1,9 +0,10 @@ | ||
/** Shallowly copy the properties and prototype of the object. | ||
/** Shallowly copy the properties of the object. */ | ||
export declare const shallowClone: <input extends object>(input: input) => input; | ||
/** Deeply copy the properties of the a non-subclassed Object, Array or Date. | ||
* | ||
* NOTE: this still cannot guarantee arrow functions attached to the object | ||
* are rebound in case they reference `this`. | ||
* @param input The object to clone | ||
* | ||
* See: https://x.com/colinhacks/status/1818422039210049985 | ||
* @returns A new deeply cloned version of the object, or the original object | ||
* if it has a prototype other than Object, Array Date, or null. | ||
*/ | ||
export declare const shallowClone: <input extends object>(input: input) => input; | ||
export declare const deepClone: <input>(input: input) => input; | ||
export declare const deepClone: <input extends object>(input: input) => input; |
@@ -1,27 +0,32 @@ | ||
/** Shallowly copy the properties and prototype of the object. | ||
import { getBuiltinNameOfConstructor } from "./objectKinds.js"; | ||
/** Shallowly copy the properties of the object. */ | ||
export const shallowClone = input => _clone(input, null); | ||
/** Deeply copy the properties of the a non-subclassed Object, Array or Date. | ||
* | ||
* NOTE: this still cannot guarantee arrow functions attached to the object | ||
* are rebound in case they reference `this`. | ||
* @param input The object to clone | ||
* | ||
* See: https://x.com/colinhacks/status/1818422039210049985 | ||
* @returns A new deeply cloned version of the object, or the original object | ||
* if it has a prototype other than Object, Array Date, or null. | ||
*/ | ||
export const shallowClone = (input) => { | ||
const cloned = Object.create(Object.getPrototypeOf(input), Object.getOwnPropertyDescriptors(input)); | ||
return cloned; | ||
}; | ||
export const deepClone = (input) => _deepClone(input, new Map()); | ||
const _deepClone = (input, seen) => { | ||
export const deepClone = (input) => _clone(input, new Map()); | ||
const _clone = (input, seen) => { | ||
if (typeof input !== "object" || input === null) | ||
return input; | ||
if (seen.has(input)) | ||
if (seen?.has(input)) | ||
return seen.get(input); | ||
const builtinConstructorName = getBuiltinNameOfConstructor(input.constructor); | ||
if (builtinConstructorName === "Date") | ||
return new Date(input.getTime()); | ||
// we don't try and clone other prototypes here since this we can't guarantee arrow functions attached to the object | ||
// are rebound in case they reference `this` (see https://x.com/colinhacks/status/1818422039210049985) | ||
if (builtinConstructorName && builtinConstructorName !== "Array") | ||
return input; | ||
const cloned = Array.isArray(input) ? | ||
// ensure arrays are copied with their original class attached so they | ||
// work with Array.isArray | ||
input.slice() | ||
: Object.create(Object.getPrototypeOf(input)); | ||
seen.set(input, cloned); | ||
const propertyDescriptors = Object.getOwnPropertyDescriptors(input); | ||
for (const key of Object.keys(propertyDescriptors)) { | ||
propertyDescriptors[key].value = _deepClone(propertyDescriptors[key].value, seen); | ||
if (seen) { | ||
seen.set(input, cloned); | ||
for (const k in propertyDescriptors) | ||
propertyDescriptors[k].value = _clone(propertyDescriptors[k].value, seen); | ||
} | ||
@@ -28,0 +33,0 @@ Object.defineProperties(cloned, propertyDescriptors); |
@@ -5,3 +5,2 @@ import type { describeDefaults, DescribeOptions } from "./describe.ts"; | ||
export type JsTypeOf = "object" | "function" | "number" | "bigint" | "boolean" | "string" | "symbol" | "undefined" | "null"; | ||
export declare const domainToJsTypesOf: (domain: Domain) => JsTypeOf[]; | ||
export declare const hasDomain: <data, domain extends Domain>(data: data, kind: domain) => data is data & inferDomain<domain>; | ||
@@ -8,0 +7,0 @@ type TypesByDomain = { |
@@ -1,4 +0,1 @@ | ||
export const domainToJsTypesOf = (domain) => domain === "null" ? ["object"] | ||
: domain === "object" ? ["object", "function"] | ||
: [domain]; | ||
export const hasDomain = (data, kind) => domainOf(data) === kind; | ||
@@ -5,0 +2,0 @@ export const domainOf = (data) => { |
@@ -19,4 +19,5 @@ import type { Primitive } from "./domain.ts"; | ||
} & u; | ||
/** Returns onTrue if the type is exactly `{}` and onFalse otherwise*/ | ||
export type ifEmptyObjectLiteral<t, onTrue = true, onFalse = false> = {} extends t ? keyof t extends never ? onTrue : onFalse : onFalse; | ||
export type leftIfEqual<l, r> = [l, r] extends [r, l] ? l : r; | ||
export type defer<t> = [t][t extends any ? 0 : never]; | ||
export type UnknownUnion = string | number | symbol | bigint | boolean | object | null | undefined; | ||
@@ -23,0 +24,0 @@ /** |
@@ -5,5 +5,7 @@ import type { array } from "./arrays.ts"; | ||
import type { Fn } from "./functions.ts"; | ||
import type { satisfy } from "./generics.ts"; | ||
import { type Key } from "./records.ts"; | ||
export type builtinConstructors = { | ||
export declare const ecmascriptConstructors: { | ||
Array: ArrayConstructor; | ||
Boolean: BooleanConstructor; | ||
Date: DateConstructor; | ||
@@ -13,17 +15,95 @@ Error: ErrorConstructor; | ||
Map: MapConstructor; | ||
Number: NumberConstructor; | ||
Promise: PromiseConstructor; | ||
RegExp: RegExpConstructor; | ||
Set: SetConstructor; | ||
String: StringConstructor; | ||
WeakMap: WeakMapConstructor; | ||
WeakSet: WeakSetConstructor; | ||
}; | ||
export type ecmascriptConstructors = typeof ecmascriptConstructors; | ||
export type EcmascriptObjects = satisfy<instantiateConstructors<keyof ecmascriptConstructors>, { | ||
Array: Array<unknown>; | ||
Boolean: Boolean; | ||
Date: Date; | ||
Error: Error; | ||
Function: Function; | ||
Map: Map<unknown, unknown>; | ||
Number: Number; | ||
RegExp: RegExp; | ||
Set: Set<unknown>; | ||
String: String; | ||
WeakMap: WeakMap<object, unknown>; | ||
WeakSet: WeakSet<object>; | ||
Promise: Promise<unknown>; | ||
}>; | ||
/** Node18 */ | ||
export declare const FileConstructor: typeof import("buffer").File; | ||
export type platformConstructors = { | ||
ArrayBuffer: ArrayBufferConstructor; | ||
Blob: typeof Blob; | ||
File: typeof File; | ||
FormData: typeof FormData; | ||
Headers: typeof Headers; | ||
Request: typeof Request; | ||
Response: typeof Response; | ||
URL: typeof URL; | ||
}; | ||
export declare const platformConstructors: platformConstructors; | ||
export type PlatformObjects = instantiateConstructors<keyof platformConstructors>; | ||
export declare const typedArrayConstructors: { | ||
Int8Array: Int8ArrayConstructor; | ||
Uint8Array: Uint8ArrayConstructor; | ||
Uint8ClampedArray: Uint8ClampedArrayConstructor; | ||
Int16Array: Int16ArrayConstructor; | ||
Uint16Array: Uint16ArrayConstructor; | ||
Int32Array: Int32ArrayConstructor; | ||
Uint32Array: Uint32ArrayConstructor; | ||
Float32Array: Float32ArrayConstructor; | ||
Float64Array: Float64ArrayConstructor; | ||
BigInt64Array: BigInt64ArrayConstructor; | ||
BigUint64Array: BigUint64ArrayConstructor; | ||
}; | ||
export type typedArrayConstructors = typeof typedArrayConstructors; | ||
export type TypedArrayObjects = instantiateConstructors<keyof typedArrayConstructors>; | ||
export declare const builtinConstructors: { | ||
String: StringConstructor; | ||
Number: NumberConstructor; | ||
Boolean: BooleanConstructor; | ||
Int8Array: Int8ArrayConstructor; | ||
Uint8Array: Uint8ArrayConstructor; | ||
Uint8ClampedArray: Uint8ClampedArrayConstructor; | ||
Int16Array: Int16ArrayConstructor; | ||
Uint16Array: Uint16ArrayConstructor; | ||
Int32Array: Int32ArrayConstructor; | ||
Uint32Array: Uint32ArrayConstructor; | ||
Float32Array: Float32ArrayConstructor; | ||
Float64Array: Float64ArrayConstructor; | ||
BigInt64Array: BigInt64ArrayConstructor; | ||
BigUint64Array: BigUint64ArrayConstructor; | ||
ArrayBuffer: ArrayBufferConstructor; | ||
Blob: typeof Blob; | ||
File: typeof File; | ||
FormData: typeof FormData; | ||
Headers: typeof Headers; | ||
Request: typeof Request; | ||
Response: typeof Response; | ||
URL: typeof URL; | ||
Array: ArrayConstructor; | ||
Date: DateConstructor; | ||
Error: ErrorConstructor; | ||
Function: FunctionConstructor; | ||
Map: MapConstructor; | ||
Promise: PromiseConstructor; | ||
RegExp: RegExpConstructor; | ||
Set: SetConstructor; | ||
WeakMap: WeakMapConstructor; | ||
WeakSet: WeakSetConstructor; | ||
Promise: PromiseConstructor; | ||
}; | ||
export declare const builtinConstructors: builtinConstructors; | ||
export type BuiltinObjectConstructors = typeof builtinConstructors; | ||
export type BuiltinObjectKind = keyof BuiltinObjectConstructors; | ||
export type BuiltinObjects = { | ||
[kind in BuiltinObjectKind]: InstanceType<BuiltinObjectConstructors[kind]>; | ||
export type builtinConstructors = typeof builtinConstructors; | ||
export type BuiltinObjectKind = keyof builtinConstructors; | ||
type instantiateConstructors<kind extends BuiltinObjectKind> = { | ||
[k in kind]: InstanceType<builtinConstructors[k]>; | ||
}; | ||
export type BuiltinObjects = instantiateConstructors<BuiltinObjectKind>; | ||
export type objectKindOf<data extends object> = object extends data ? keyof builtinConstructors | undefined : data extends Fn ? "Function" : instantiableObjectKind<data> extends never ? keyof builtinConstructors | undefined : instantiableObjectKind<data>; | ||
@@ -41,4 +121,61 @@ export type describeObject<o extends object, opts extends DescribeOptions = {}> = objectKindOf<o> extends string ? [ | ||
export declare const isArray: (data: unknown) => data is array; | ||
export declare const ecmascriptDescriptions: { | ||
readonly Array: "an array"; | ||
readonly Function: "a function"; | ||
readonly Date: "a Date"; | ||
readonly RegExp: "a RegExp"; | ||
readonly Error: "an Error"; | ||
readonly Map: "a Map"; | ||
readonly Set: "a Set"; | ||
readonly String: "a String object"; | ||
readonly Number: "a Number object"; | ||
readonly Boolean: "a Boolean object"; | ||
readonly Promise: "a Promise"; | ||
readonly WeakMap: "a WeakMap"; | ||
readonly WeakSet: "a WeakSet"; | ||
}; | ||
export declare const platformDescriptions: { | ||
ArrayBuffer: string; | ||
Blob: string; | ||
File: string; | ||
FormData: string; | ||
Headers: string; | ||
Request: string; | ||
Response: string; | ||
URL: string; | ||
}; | ||
export declare const typedArrayDescriptions: { | ||
readonly Int8Array: "an Int8Array"; | ||
readonly Uint8Array: "a Uint8Array"; | ||
readonly Uint8ClampedArray: "a Uint8ClampedArray"; | ||
readonly Int16Array: "an Int16Array"; | ||
readonly Uint16Array: "a Uint16Array"; | ||
readonly Int32Array: "an Int32Array"; | ||
readonly Uint32Array: "a Uint32Array"; | ||
readonly Float32Array: "a Float32Array"; | ||
readonly Float64Array: "a Float64Array"; | ||
readonly BigInt64Array: "a BigInt64Array"; | ||
readonly BigUint64Array: "a BigUint64Array"; | ||
}; | ||
/** Each defaultObjectKind's completion for the phrase "must be _____" */ | ||
export declare const objectKindDescriptions: { | ||
readonly Int8Array: "an Int8Array"; | ||
readonly Uint8Array: "a Uint8Array"; | ||
readonly Uint8ClampedArray: "a Uint8ClampedArray"; | ||
readonly Int16Array: "an Int16Array"; | ||
readonly Uint16Array: "a Uint16Array"; | ||
readonly Int32Array: "an Int32Array"; | ||
readonly Uint32Array: "a Uint32Array"; | ||
readonly Float32Array: "a Float32Array"; | ||
readonly Float64Array: "a Float64Array"; | ||
readonly BigInt64Array: "a BigInt64Array"; | ||
readonly BigUint64Array: "a BigUint64Array"; | ||
readonly ArrayBuffer: string; | ||
readonly Blob: string; | ||
readonly File: string; | ||
readonly FormData: string; | ||
readonly Headers: string; | ||
readonly Request: string; | ||
readonly Response: string; | ||
readonly URL: string; | ||
readonly Array: "an array"; | ||
@@ -59,3 +196,7 @@ readonly Function: "a function"; | ||
export type objectKindDescriptions = typeof objectKindDescriptions; | ||
export declare const getExactBuiltinConstructorName: (ctor: unknown) => BuiltinObjectKind | null; | ||
/** | ||
* this will only return an object kind if it's the root constructor | ||
* example TypeError would return null not 'Error' | ||
**/ | ||
export declare const getBuiltinNameOfConstructor: (ctor: Function) => BuiltinObjectKind | null; | ||
export type Constructor<instance = {}> = abstract new (...args: never[]) => instance; | ||
@@ -62,0 +203,0 @@ export type instanceOf<constructor> = constructor extends Constructor<infer instance> ? instance : never; |
import { domainOf } from "./domain.js"; | ||
import { isKeyOf } from "./records.js"; | ||
// Built-in object constructors based on a subset of: | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects | ||
export const builtinConstructors = { | ||
// ECMAScript Objects | ||
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects | ||
export const ecmascriptConstructors = { | ||
Array, | ||
Boolean, | ||
Date, | ||
@@ -11,11 +12,48 @@ Error, | ||
Map, | ||
Number, | ||
Promise, | ||
RegExp, | ||
Set, | ||
String, | ||
Number, | ||
Boolean, | ||
WeakMap, | ||
WeakSet, | ||
Promise | ||
WeakSet | ||
}; | ||
/** Node18 */ | ||
export const FileConstructor = globalThis.File ?? Blob; | ||
// Platform APIs | ||
// See https://developer.mozilla.org/en-US/docs/Web/API | ||
// Must be implemented in Node etc. as well as the browser to include here | ||
export const platformConstructors = { | ||
ArrayBuffer, | ||
Blob, | ||
File: FileConstructor, | ||
FormData, | ||
Headers, | ||
Request, | ||
Response, | ||
URL | ||
}; | ||
export const typedArrayConstructors = { | ||
Int8Array, | ||
Uint8Array, | ||
Uint8ClampedArray, | ||
Int16Array, | ||
Uint16Array, | ||
Int32Array, | ||
Uint32Array, | ||
Float32Array, | ||
Float64Array, | ||
BigInt64Array, | ||
BigUint64Array | ||
}; | ||
// Built-in object constructors based on a subset of: | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects | ||
export const builtinConstructors = { | ||
...ecmascriptConstructors, | ||
...platformConstructors, | ||
...typedArrayConstructors, | ||
String, | ||
Number, | ||
Boolean | ||
}; | ||
export const objectKindOf = (data) => { | ||
@@ -37,4 +75,3 @@ let prototype = Object.getPrototypeOf(data); | ||
export const isArray = (data) => Array.isArray(data); | ||
/** Each defaultObjectKind's completion for the phrase "must be _____" */ | ||
export const objectKindDescriptions = { | ||
export const ecmascriptDescriptions = { | ||
Array: "an array", | ||
@@ -54,5 +91,36 @@ Function: "a function", | ||
}; | ||
// this will only return an object kind if it's the root constructor | ||
// example TypeError would return undefined not 'Error' | ||
export const getExactBuiltinConstructorName = (ctor) => { | ||
export const platformDescriptions = { | ||
ArrayBuffer: "an ArrayBuffer instance", | ||
Blob: "a Blob instance", | ||
File: "a File instance", | ||
FormData: "a FormData instance", | ||
Headers: "a Headers instance", | ||
Request: "a Request instance", | ||
Response: "a Response instance", | ||
URL: "a URL instance" | ||
}; | ||
export const typedArrayDescriptions = { | ||
Int8Array: "an Int8Array", | ||
Uint8Array: "a Uint8Array", | ||
Uint8ClampedArray: "a Uint8ClampedArray", | ||
Int16Array: "an Int16Array", | ||
Uint16Array: "a Uint16Array", | ||
Int32Array: "an Int32Array", | ||
Uint32Array: "a Uint32Array", | ||
Float32Array: "a Float32Array", | ||
Float64Array: "a Float64Array", | ||
BigInt64Array: "a BigInt64Array", | ||
BigUint64Array: "a BigUint64Array" | ||
}; | ||
/** Each defaultObjectKind's completion for the phrase "must be _____" */ | ||
export const objectKindDescriptions = { | ||
...ecmascriptDescriptions, | ||
...platformDescriptions, | ||
...typedArrayDescriptions | ||
}; | ||
/** | ||
* this will only return an object kind if it's the root constructor | ||
* example TypeError would return null not 'Error' | ||
**/ | ||
export const getBuiltinNameOfConstructor = (ctor) => { | ||
const constructorName = Object(ctor).name ?? null; | ||
@@ -59,0 +127,0 @@ return (constructorName && |
@@ -1,6 +0,5 @@ | ||
export declare const arkUtilVersion = "0.3.0"; | ||
export declare const arkUtilVersion = "0.5.0"; | ||
export declare const initialRegistryContents: { | ||
version: string; | ||
filename: string; | ||
/** Node18 */ | ||
FileConstructor: typeof import("buffer").File; | ||
@@ -7,0 +6,0 @@ }; |
import { domainOf } from "./domain.js"; | ||
import { throwInternalError } from "./errors.js"; | ||
import { objectKindOf } from "./objectKinds.js"; | ||
import { FileConstructor, objectKindOf } from "./objectKinds.js"; | ||
// Eventually we can just import from package.json in the source itself | ||
@@ -8,8 +8,7 @@ // but for now, import assertions are too unstable and it wouldn't support | ||
// For now, we assert this matches the package.json version via a unit test. | ||
export const arkUtilVersion = "0.3.0"; | ||
export const arkUtilVersion = "0.5.0"; | ||
export const initialRegistryContents = { | ||
version: arkUtilVersion, | ||
filename: import.meta.filename, | ||
/** Node18 */ | ||
FileConstructor: globalThis.File ?? Blob | ||
FileConstructor | ||
}; | ||
@@ -16,0 +15,0 @@ export const registry = initialRegistryContents; |
{ | ||
"name": "@arktype/util", | ||
"version": "0.3.0", | ||
"version": "0.5.0", | ||
"author": { | ||
@@ -5,0 +5,0 @@ "name": "David Blass", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
89673
1932