From a33feb54348e6ec9251d858edb1b535c30c7f558 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Mon, 19 Dec 2022 18:44:53 -0500 Subject: [PATCH 01/10] refactor: Major simplification in providing implementation types --- src/Complex/all.ts | 9 ++++++++- src/Complex/type.ts | 12 ++---------- src/core/Dispatcher.ts | 6 ++++++ src/numbers/all.ts | 9 ++++++++- src/numbers/arithmetic.ts | 3 +-- src/numbers/type.ts | 6 ------ 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/Complex/all.ts b/src/Complex/all.ts index a386daa..9d417b8 100644 --- a/src/Complex/all.ts +++ b/src/Complex/all.ts @@ -1 +1,8 @@ -export * as Complex from './native.js' +import {ForType} from '../core/Dispatcher.js' +import * as Complex from './native.js' + +export {Complex} + +declare module "../core/Dispatcher" { + interface ImplementationTypes extends ForType<'Complex', typeof Complex> {} +} diff --git a/src/Complex/type.ts b/src/Complex/type.ts index 4e9704c..affbedc 100644 --- a/src/Complex/type.ts +++ b/src/Complex/type.ts @@ -1,4 +1,3 @@ -/// import {joinTypes, typeOfDependency, Dependency} from '../core/Dispatcher.js' export type Complex = {re: T; im: T;} @@ -18,13 +17,6 @@ export const Complex_type = { } } -export const complex_1 = (dep: Dependency<'zero', [T]>) => +export const complex_unary = (dep: Dependency<'zero', [T]>) => (t: T) => ({re: t, im: dep.zero(t)}) -export const complex_2 = (t: T, u: T) => ({re: t, im: u}) - -declare module "../core/Dispatcher" { - interface ImplementationTypes { - complex_1_Complex: typeof complex_1 - complex_2_Complex: typeof complex_2 - } -} +export const complex_binary = (t: T, u: T) => ({re: t, im: u}) diff --git a/src/core/Dispatcher.ts b/src/core/Dispatcher.ts index 4b3dfa6..bed8f0d 100644 --- a/src/core/Dispatcher.ts +++ b/src/core/Dispatcher.ts @@ -14,6 +14,12 @@ type Signature = Parameter[] export interface ImplementationTypes {} export type typeOfDependency = {typeOf: (x: unknown) => TypeName} +// Helper for collecting implementations +// (Really just suffixes the type name onto the keys of exports) +export type ForType = keyof Exports extends string + ? {[K in keyof Exports as `${K}_${T}`]: Exports[K]} + : never + //dummy implementation for now export function joinTypes(a: TypeName, b: TypeName) { if (a === b) return a diff --git a/src/numbers/all.ts b/src/numbers/all.ts index b71b4c3..5aea220 100644 --- a/src/numbers/all.ts +++ b/src/numbers/all.ts @@ -1 +1,8 @@ -export * as numbers from './native.js' +import {ForType} from '../core/Dispatcher.js' +import * as numbers from './native.js' + +export {numbers} + +declare module "../core/Dispatcher" { + interface ImplementationTypes extends ForType<'numbers', typeof numbers> {} +} diff --git a/src/numbers/arithmetic.ts b/src/numbers/arithmetic.ts index f1facf1..e78d9ec 100644 --- a/src/numbers/arithmetic.ts +++ b/src/numbers/arithmetic.ts @@ -1,6 +1,5 @@ -/// import {configDependency} from '../core/Config.js' -import {Dependency, ImplementationTypes} from '../core/Dispatcher.js' +import {Dependency} from '../core/Dispatcher.js' export const add = (a: number, b: number) => a + b export const unaryMinus = (a: number) => -a diff --git a/src/numbers/type.ts b/src/numbers/type.ts index 4e51f38..67dbd29 100644 --- a/src/numbers/type.ts +++ b/src/numbers/type.ts @@ -5,9 +5,3 @@ export const number_type = { } export const zero = (a: number) => 0 - -declare module "../core/Dispatcher" { - interface ImplementationTypes { - zero_numbers: typeof zero - } -} From 3fa216d1f4ce3814a09d241e65b193c4decffa5d Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Mon, 19 Dec 2022 23:50:24 +0000 Subject: [PATCH 02/10] refactor: Major simplification in providing implementation types (#2) This PR is an effort to address #1. It removes all boilerplate from individual implementation files, and moves it into a small, fixed section in the single `all.ts` module for each type that collects up all of the implementations relating to that type. Co-authored-by: Glen Whitney Reviewed-on: https://code.studioinfinity.org/glen/typocomath/pulls/2 --- src/Complex/all.ts | 9 ++++++++- src/Complex/type.ts | 12 ++---------- src/core/Dispatcher.ts | 6 ++++++ src/numbers/all.ts | 9 ++++++++- src/numbers/arithmetic.ts | 3 +-- src/numbers/type.ts | 6 ------ 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/Complex/all.ts b/src/Complex/all.ts index a386daa..9d417b8 100644 --- a/src/Complex/all.ts +++ b/src/Complex/all.ts @@ -1 +1,8 @@ -export * as Complex from './native.js' +import {ForType} from '../core/Dispatcher.js' +import * as Complex from './native.js' + +export {Complex} + +declare module "../core/Dispatcher" { + interface ImplementationTypes extends ForType<'Complex', typeof Complex> {} +} diff --git a/src/Complex/type.ts b/src/Complex/type.ts index 4e9704c..affbedc 100644 --- a/src/Complex/type.ts +++ b/src/Complex/type.ts @@ -1,4 +1,3 @@ -/// import {joinTypes, typeOfDependency, Dependency} from '../core/Dispatcher.js' export type Complex = {re: T; im: T;} @@ -18,13 +17,6 @@ export const Complex_type = { } } -export const complex_1 = (dep: Dependency<'zero', [T]>) => +export const complex_unary = (dep: Dependency<'zero', [T]>) => (t: T) => ({re: t, im: dep.zero(t)}) -export const complex_2 = (t: T, u: T) => ({re: t, im: u}) - -declare module "../core/Dispatcher" { - interface ImplementationTypes { - complex_1_Complex: typeof complex_1 - complex_2_Complex: typeof complex_2 - } -} +export const complex_binary = (t: T, u: T) => ({re: t, im: u}) diff --git a/src/core/Dispatcher.ts b/src/core/Dispatcher.ts index 4b3dfa6..bed8f0d 100644 --- a/src/core/Dispatcher.ts +++ b/src/core/Dispatcher.ts @@ -14,6 +14,12 @@ type Signature = Parameter[] export interface ImplementationTypes {} export type typeOfDependency = {typeOf: (x: unknown) => TypeName} +// Helper for collecting implementations +// (Really just suffixes the type name onto the keys of exports) +export type ForType = keyof Exports extends string + ? {[K in keyof Exports as `${K}_${T}`]: Exports[K]} + : never + //dummy implementation for now export function joinTypes(a: TypeName, b: TypeName) { if (a === b) return a diff --git a/src/numbers/all.ts b/src/numbers/all.ts index b71b4c3..5aea220 100644 --- a/src/numbers/all.ts +++ b/src/numbers/all.ts @@ -1 +1,8 @@ -export * as numbers from './native.js' +import {ForType} from '../core/Dispatcher.js' +import * as numbers from './native.js' + +export {numbers} + +declare module "../core/Dispatcher" { + interface ImplementationTypes extends ForType<'numbers', typeof numbers> {} +} diff --git a/src/numbers/arithmetic.ts b/src/numbers/arithmetic.ts index f1facf1..e78d9ec 100644 --- a/src/numbers/arithmetic.ts +++ b/src/numbers/arithmetic.ts @@ -1,6 +1,5 @@ -/// import {configDependency} from '../core/Config.js' -import {Dependency, ImplementationTypes} from '../core/Dispatcher.js' +import {Dependency} from '../core/Dispatcher.js' export const add = (a: number, b: number) => a + b export const unaryMinus = (a: number) => -a diff --git a/src/numbers/type.ts b/src/numbers/type.ts index 4e51f38..67dbd29 100644 --- a/src/numbers/type.ts +++ b/src/numbers/type.ts @@ -5,9 +5,3 @@ export const number_type = { } export const zero = (a: number) => 0 - -declare module "../core/Dispatcher" { - interface ImplementationTypes { - zero_numbers: typeof zero - } -} From cc1e66c0546352b2b164a92f8295cedaab4e5f62 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Sun, 22 Jan 2023 01:34:57 +0000 Subject: [PATCH 03/10] Declare implementations and dependencies via standard interfaces for operations (#8) Adds a new subdirectory `interfaces` where standard interfaces are defined. Additional interfaces for a given operation can be added with an `AliasOf` type operator. Provides type operators that give the return type, full function type, and the type of a dependency on, a given operator. Resolves #6. Co-authored-by: Glen Whitney Co-authored-by: Jos de Jong Reviewed-on: https://code.studioinfinity.org/glen/typocomath/pulls/8 --- .gitignore | 3 ++ README.md | 9 +++- src/Complex/all.ts | 8 ++- src/Complex/arithmetic.ts | 101 +++++++++++++++++++++++++++++++++++ src/Complex/predicate.ts | 9 ++++ src/Complex/relational.ts | 6 +++ src/Complex/type.ts | 65 +++++++++++++++++----- src/all.ts | 1 + src/core/Config.ts | 1 + src/core/Dispatcher.ts | 32 ++--------- src/generic/all.ts | 1 + src/generic/arithmetic.ts | 5 ++ src/generic/native.ts | 2 + src/generic/relational.ts | 5 ++ src/index.ts | 16 ++++++ src/interfaces/arithmetic.ts | 18 +++++++ src/interfaces/predicate.ts | 10 ++++ src/interfaces/relational.ts | 9 ++++ src/interfaces/type.ts | 75 ++++++++++++++++++++++++++ src/numbers/all.ts | 5 -- src/numbers/arithmetic.ts | 41 +++++++------- src/numbers/predicate.ts | 4 ++ src/numbers/relational.ts | 21 ++++++++ src/numbers/type.ts | 22 +++++++- 24 files changed, 397 insertions(+), 72 deletions(-) create mode 100644 src/Complex/arithmetic.ts create mode 100644 src/Complex/predicate.ts create mode 100644 src/Complex/relational.ts create mode 100644 src/generic/all.ts create mode 100644 src/generic/arithmetic.ts create mode 100644 src/generic/native.ts create mode 100644 src/generic/relational.ts create mode 100644 src/interfaces/arithmetic.ts create mode 100644 src/interfaces/predicate.ts create mode 100644 src/interfaces/relational.ts create mode 100644 src/interfaces/type.ts create mode 100644 src/numbers/predicate.ts create mode 100644 src/numbers/relational.ts diff --git a/.gitignore b/.gitignore index 0dc139f..d0c9d9e 100644 --- a/.gitignore +++ b/.gitignore @@ -129,6 +129,9 @@ dist # Stores VSCode versions used for testing VSCode extensions .vscode-test +# Webstorm +.idea + # yarn v2 .yarn/cache .yarn/unplugged diff --git a/README.md b/README.md index 34649c2..d15fcc4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ # typocomath -A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state. \ No newline at end of file +A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state. + +To build and run the prototype, run: + +``` +npx tsc +node obj +``` diff --git a/src/Complex/all.ts b/src/Complex/all.ts index 9d417b8..3ff6311 100644 --- a/src/Complex/all.ts +++ b/src/Complex/all.ts @@ -1,8 +1,6 @@ -import {ForType} from '../core/Dispatcher.js' import * as Complex from './native.js' +import * as complex from './arithmetic.js' + +export { complex } export {Complex} - -declare module "../core/Dispatcher" { - interface ImplementationTypes extends ForType<'Complex', typeof Complex> {} -} diff --git a/src/Complex/arithmetic.ts b/src/Complex/arithmetic.ts new file mode 100644 index 0000000..90c8eab --- /dev/null +++ b/src/Complex/arithmetic.ts @@ -0,0 +1,101 @@ +import {Complex} from './type.js' +import type { + Dependencies, Signature, Returns, RealType, AliasOf +} from '../interfaces/type.js' + +declare module "../interfaces/type" { + interface Signatures { + addReal: AliasOf<'add', (a: T, b: RealType) => T> + divideReal: AliasOf<'divide', (a: T, b: RealType) => T> + } +} + +export const add = + (dep: Dependencies<'add' | 'complex', T>): Signature<'add', Complex> => + (w, z) => dep.complex(dep.add(w.re, z.re), dep.add(w.im, z.im)) + +export const addReal = + (dep: Dependencies<'addReal' | 'complex', T>): + Signature<'addReal', Complex> => + (z, r) => dep.complex(dep.addReal(z.re, r), z.im) + +export const unaryMinus = + (dep: Dependencies<'unaryMinus' | 'complex', T>): + Signature<'unaryMinus', Complex> => + z => dep.complex(dep.unaryMinus(z.re), dep.unaryMinus(z.im)) + +export const conj = + (dep: Dependencies<'unaryMinus' | 'conj' | 'complex', T>): + Signature<'conj', Complex> => + z => dep.complex(dep.conj(z.re), dep.unaryMinus(z.im)) + +export const subtract = + (dep: Dependencies<'subtract' | 'complex', T>): + Signature<'subtract', Complex> => + (w, z) => dep.complex(dep.subtract(w.re, z.re), dep.subtract(w.im, z.im)) + +export const multiply = + (dep: Dependencies< + 'add' | 'subtract' | 'multiply' | 'conj' | 'complex', T>): + Signature<'multiply', Complex> => + (w, z) => { + const mult = dep.multiply + const realpart = dep.subtract( + mult( w.re, z.re), mult(dep.conj(w.im), z.im)) + const imagpart = dep.add( + mult(dep.conj(w.re), z.im), mult( w.im, z.re)) + return dep.complex(realpart, imagpart) + } + +export const absquare = + (dep: Dependencies<'absquare', T> + & Dependencies<'add', Returns<'absquare', T>>): + Signature<'absquare', Complex> => + z => dep.add(dep.absquare(z.re), dep.absquare(z.im)) + +export const divideReal = + (dep: Dependencies<'divideReal' | 'complex', T>): + Signature<'divideReal', Complex> => + (z, r) => dep.complex(dep.divideReal(z.re, r), dep.divideReal(z.im, r)) + +export const reciprocal = + (dep: Dependencies<'conj' | 'absquare' | 'divideReal', Complex>): + Signature<'reciprocal', Complex> => + z => dep.divideReal(dep.conj(z), dep.absquare(z)) + +export const divide = + (dep: Dependencies<'multiply' | 'reciprocal', Complex>): + Signature<'divide', Complex> => + (w, z) => dep.multiply(w, dep.reciprocal(z)) + +// The dependencies are slightly tricky here, because there are three types +// involved: Complex, T, and RealType, all of which might be different, +// and we have to get it straight which operations we need on each type, and +// in fact, we need `addReal` on both T and Complex, hence the dependency +// with a custom name, not generated via Dependencies<...> +export const sqrt = + (dep: Dependencies<'equal' | 'conservativeSqrt' | 'unaryMinus', RealType> + & Dependencies<'zero' | 'complex', T> + & Dependencies<'absquare' | 're' | 'divideReal', Complex> + & { + addTR: Signature<'addReal', T>, + addRR: Signature<'add', RealType>, + addCR: Signature<'addReal', Complex> + }): + Signature<'sqrt', Complex> => + z => { + const myabs = dep.conservativeSqrt(dep.absquare(z)) + const r = dep.re(z) + const negr = dep.unaryMinus(r) + if (dep.equal(myabs, negr)) { + // pure imaginary square root; z.im already zero + return dep.complex( + dep.zero(z.re), dep.addTR(z.im, dep.conservativeSqrt(negr))) + } + const num = dep.addCR(z, myabs) + const denomsq = dep.addRR(dep.addRR(myabs, myabs), dep.addRR(r, r)) + const denom = dep.conservativeSqrt(denomsq) + return dep.divideReal(num, denom) + } + +export const conservativeSqrt = sqrt diff --git a/src/Complex/predicate.ts b/src/Complex/predicate.ts new file mode 100644 index 0000000..ffcefaa --- /dev/null +++ b/src/Complex/predicate.ts @@ -0,0 +1,9 @@ +import {Complex} from './type.js' +import type {Dependencies, Signature} from '../interfaces/type.js' + +export const isReal = + (dep: Dependencies<'add' | 'equal' | 'isReal', T>): + Signature<'isReal', Complex> => + z => dep.isReal(z.re) && dep.equal(z.re, dep.add(z.re, z.im)) + +export const isSquare: Signature<'isSquare', Complex> = z => true // FIXME: not correct for Complex once we get there diff --git a/src/Complex/relational.ts b/src/Complex/relational.ts new file mode 100644 index 0000000..78550d7 --- /dev/null +++ b/src/Complex/relational.ts @@ -0,0 +1,6 @@ +import {Complex} from './type.js' +import {Dependencies, Signature} from '../interfaces/type.js' + +export const equal = + (dep: Dependencies<'equal', T>): Signature<'equal', Complex> => + (w, z) => dep.equal(w.re, z.re) && dep.equal(w.im, z.im) diff --git a/src/Complex/type.ts b/src/Complex/type.ts index affbedc..50a1314 100644 --- a/src/Complex/type.ts +++ b/src/Complex/type.ts @@ -1,22 +1,63 @@ -import {joinTypes, typeOfDependency, Dependency} from '../core/Dispatcher.js' +import {joinTypes, typeOfDependency} from '../core/Dispatcher.js' +import type { + ZeroType, OneType, NaNType, Dependencies, Signature, Returns +} from '../interfaces/type.js' -export type Complex = {re: T; im: T;} +export type Complex = { re: T; im: T; } export const Complex_type = { - test: (dep: {testT: (z: unknown) => z is T}) => + test: (dep: { testT: (z: unknown) => z is T }) => (z: unknown): z is Complex => - typeof z === 'object' && 're' in z && 'im' in z - && dep.testT(z.re) && dep.testT(z.im), + typeof z === 'object' && z != null && 're' in z && 'im' in z + && dep.testT(z['re']) && dep.testT(z['im']), infer: (dep: typeOfDependency) => (z: Complex) => joinTypes(dep.typeOf(z.re), dep.typeOf(z.im)), from: { - T: (dep: Dependency<'zero', [T]>) => (t: T) => - ({re: t, im: dep.zero(t)}), - Complex: (dep: {convert: (from: U) => T}) => - (z: Complex) => ({re: dep.convert(z.re), im: dep.convert(z.im)}) + T: (dep: Dependencies<'zero', T>) => (t: T) => + ({ re: t, im: dep.zero(t) }), + Complex: (dep: { convert: (from: U) => T }) => + (z: Complex) => ({ re: dep.convert(z.re), im: dep.convert(z.im) }) } } -export const complex_unary = (dep: Dependency<'zero', [T]>) => - (t: T) => ({re: t, im: dep.zero(t)}) -export const complex_binary = (t: T, u: T) => ({re: t, im: u}) +declare module "../interfaces/type" { + interface AssociatedTypes { + Complex: T extends Complex ? { + type: Complex + zero: Complex> + one: Complex | ZeroType> + nan: Complex> + real: RealType + } : never + } + + interface Signatures { + complex: ((re: T) => Complex) | ((re: T, im: T) => Complex) + } +} + +export const complex = + (dep: Dependencies<'zero', T>): Signature<'complex', T> => + (a, b) => ({re: a, im: b || dep.zero(a)}) + +export const zero = + (dep: Dependencies<'zero', T> + & Dependencies<'complex', Returns<'zero', T>>): + Signature<'zero', Complex> => + z => dep.complex(dep.zero(z.re), dep.zero(z.im)) + +export const one = + (dep: Dependencies<'one' | 'zero', T> + & Dependencies<'complex', Returns<'one' | 'zero', T>>): + Signature<'one', Complex> => + z => dep.complex(dep.one(z.re), dep.zero(z.im)) + +export const nan = + (dep: Dependencies<'nan', T> + & Dependencies<'complex', Returns<'nan', T>>): + Signature<'nan', Complex> => + z => dep.complex(dep.nan(z.re), dep.nan(z.im)) + +export const re = + (dep: Dependencies<'re', T>): Signature<'re', Complex> => + z => dep.re(z.re) diff --git a/src/all.ts b/src/all.ts index 192c7be..e2e83f1 100644 --- a/src/all.ts +++ b/src/all.ts @@ -1,2 +1,3 @@ export * from './numbers/all.js' export * from './Complex/all.js' +export * from './generic/all.js' diff --git a/src/core/Config.ts b/src/core/Config.ts index 3765328..c1eb24c 100644 --- a/src/core/Config.ts +++ b/src/core/Config.ts @@ -1,4 +1,5 @@ export type Config = { + epsilon: number predictable: boolean } diff --git a/src/core/Dispatcher.ts b/src/core/Dispatcher.ts index bed8f0d..def1bd3 100644 --- a/src/core/Dispatcher.ts +++ b/src/core/Dispatcher.ts @@ -10,44 +10,18 @@ type TypeName = string type Parameter = TypeName type Signature = Parameter[] +type DependenciesType = Record -export interface ImplementationTypes {} +// A "canned" dependency for a builtin function: export type typeOfDependency = {typeOf: (x: unknown) => TypeName} -// Helper for collecting implementations -// (Really just suffixes the type name onto the keys of exports) -export type ForType = keyof Exports extends string - ? {[K in keyof Exports as `${K}_${T}`]: Exports[K]} - : never - +// Utility needed in type definitions //dummy implementation for now export function joinTypes(a: TypeName, b: TypeName) { if (a === b) return a return 'any' } -/** - * Build up to Dependency type lookup - */ -type DependenciesType = Record - -type FinalShape = - FuncType extends (arg: DependenciesType) => Function - ? ReturnType : FuncType - -type BeginsWith = `${Name}${string}` - -type DependencyTypes = - {[K in keyof Ob]: K extends BeginsWith - ? FinalShape extends (...args: Params) => any - ? FinalShape - : never - : never} - -export type Dependency = - {[N in Name]: - DependencyTypes[keyof ImplementationTypes]} - // Now types used in the Dispatcher class itself type TypeSpecification = { diff --git a/src/generic/all.ts b/src/generic/all.ts new file mode 100644 index 0000000..78fa222 --- /dev/null +++ b/src/generic/all.ts @@ -0,0 +1 @@ +export * as generic from './native.js' diff --git a/src/generic/arithmetic.ts b/src/generic/arithmetic.ts new file mode 100644 index 0000000..78ad57d --- /dev/null +++ b/src/generic/arithmetic.ts @@ -0,0 +1,5 @@ +import type {Dependencies, Signature} from '../interfaces/type.js' + +export const square = + (dep: Dependencies<'multiply', T>): Signature<'square', T> => + z => dep.multiply(z, z) diff --git a/src/generic/native.ts b/src/generic/native.ts new file mode 100644 index 0000000..b8290ae --- /dev/null +++ b/src/generic/native.ts @@ -0,0 +1,2 @@ +export * from './arithmetic.js' +export * from './relational.js' diff --git a/src/generic/relational.ts b/src/generic/relational.ts new file mode 100644 index 0000000..714cb49 --- /dev/null +++ b/src/generic/relational.ts @@ -0,0 +1,5 @@ +import {Dependencies, Signature} from '../interfaces/type.js' + +export const unequal = + (dep: Dependencies<'equal', T>): Signature<'unequal', T> => + (x, y) => !dep.equal(x, y) diff --git a/src/index.ts b/src/index.ts index bb83486..297b271 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,3 +2,19 @@ import {Dispatcher} from './core/Dispatcher.js' import * as Specifications from './all.js' export default new Dispatcher(Specifications) + +import {Complex} from './Complex/type.js' +import {absquare as absquare_complex} from './Complex/arithmetic.js' + +const mockRealAdd = (a: number, b: number) => a+b +const mockComplexAbsquare = (z: Complex) => z.re*z.re + z.im*z.im + +const quatAbsquare = absquare_complex({ + add: mockRealAdd, + absquare: mockComplexAbsquare +}) + +const myabs = quatAbsquare({re: {re: 0, im: 1}, im: {re:2, im: 3}}) +const typeTest: typeof myabs = 7 // check myabs is just a number + +console.log('Result is', myabs) diff --git a/src/interfaces/arithmetic.ts b/src/interfaces/arithmetic.ts new file mode 100644 index 0000000..df2d765 --- /dev/null +++ b/src/interfaces/arithmetic.ts @@ -0,0 +1,18 @@ +import type {Complex} from '../Complex/type.js' +import type {RealType} from './type.js' + +declare module "./type" { + interface Signatures { + add: (a: T, b: T) => T + unaryMinus: (a: T) => T + conj: (a: T) => T + subtract: (a: T, b: T) => T + multiply: (a: T, b: T) => T + square: (a: T) => T + absquare: (a: T) => RealType + reciprocal: (a: T) => T + divide: (a: T, b: T) => T + conservativeSqrt: (a: T) => T + sqrt: (a: T)=> T extends Complex ? T : T | Complex + } +} diff --git a/src/interfaces/predicate.ts b/src/interfaces/predicate.ts new file mode 100644 index 0000000..93d3b4a --- /dev/null +++ b/src/interfaces/predicate.ts @@ -0,0 +1,10 @@ +// Warning: a module must have something besides just a "declare module" +// section; otherwise it is ignored. +export type UnaryPredicate = (a: T) => boolean + +declare module "./type" { + interface Signatures { + isReal: (a: T) => boolean + isSquare: (a: T) => boolean + } +} diff --git a/src/interfaces/relational.ts b/src/interfaces/relational.ts new file mode 100644 index 0000000..e2aa3a1 --- /dev/null +++ b/src/interfaces/relational.ts @@ -0,0 +1,9 @@ +// Warning: a module must have something besides just a "declare module" +// section; otherwise it is ignored. +export type BinaryPredicate = (a: T, b: T) => T +declare module "./type" { + interface Signatures { + equal: (a: T, b: T) => boolean + unequal: (a: T, b: T) => boolean + } +} diff --git a/src/interfaces/type.ts b/src/interfaces/type.ts new file mode 100644 index 0000000..9e6870d --- /dev/null +++ b/src/interfaces/type.ts @@ -0,0 +1,75 @@ +/***** + * Every typocomath type has some associated types; they need + * to be published in the following interface. The key is the + * name of the type, and within the subinterface for that key, + * the type of the 'type' property is the actual TypeScript type + * we are associating the other properties to. Note the interface + * is generic with one parameter, corresponding to the fact that + * typocomath currently only allows generic types with a single + * generic parameter. This way, AssociatedTypes can give the + * associated types for a generic type instantiated with SubType. + * That's not necessary for the 'undefined' type (or if you look in the + * `numbers` subdirectory, the 'number' type) or any concrete type, + * but that's OK, the generic parameter doesn't hurt in those cases. + ****/ + +export interface AssociatedTypes { + undefined: { + type: undefined + zero: undefined + one: undefined + nan: undefined + real: undefined + } +} + +type AssociatedTypeNames = keyof AssociatedTypes['undefined'] +type ALookup = { + [K in keyof AssociatedTypes]: + T extends AssociatedTypes[K]['type'] ? AssociatedTypes[K][Name] : never +}[keyof AssociatedTypes] + +// For everything to compile, zero and one must be subtypes of T: +export type ZeroType = ALookup & T +export type OneType = ALookup & T +// But I believe 'nan' really might not be, like I think we will have to use +// 'undefined' for the nan of 'bigint', as it has nothing at all like NaN, +// so don't force it: +export type NaNType = ALookup +export type RealType = ALookup + +/***** + * The global signature patterns for all operations need to be published in the + * following interface. Each key is the name of an operation (but note that + * the Dispatcher will automatically merge operations that have the same + * name when the first underscore `_` and everything thereafter is stripped). + * The type of each key should be an interface with two properties: 'params' + * whose type is the type of the parameter list for the operation, and + * 'returns' whose type is the return type of the operation on those + * parameters. These types are generic in a parameter type T which should + * be interpreted as the type that the operation is supposed to "primarily" + * operate on, although note that some of the parameters and/or return types + * may depend on T rather than be exactly T. + * So note that the example 're' below provides essentially the same + * information that e.g. + * `type ReOp = (t: T) => RealType` + * would, but in a way that is much easier to manipulate in TypeScript, + * and it records the name of the operation as 're' also by virtue of the + * key 're' in the interface. + ****/ +export interface Signatures { + zero: (a: T) => ZeroType + one: (a: T) => OneType + // nan needs to be able to operate on its own output for everything + // else to compile. That's why its parameter type is widened: + nan: (a: T | NaNType) => NaNType + re: (a: T) => RealType +} + +type SignatureKey = keyof Signatures + +export type Signature, T> = Signatures[Name] +export type Returns, T> = ReturnType[Name]> +export type Dependencies, T> = {[K in Name]: Signature} + +export type AliasOf = T & {aliasOf?: Name} diff --git a/src/numbers/all.ts b/src/numbers/all.ts index 5aea220..deb4a8e 100644 --- a/src/numbers/all.ts +++ b/src/numbers/all.ts @@ -1,8 +1,3 @@ -import {ForType} from '../core/Dispatcher.js' import * as numbers from './native.js' export {numbers} - -declare module "../core/Dispatcher" { - interface ImplementationTypes extends ForType<'numbers', typeof numbers> {} -} diff --git a/src/numbers/arithmetic.ts b/src/numbers/arithmetic.ts index e78d9ec..11da5c2 100644 --- a/src/numbers/arithmetic.ts +++ b/src/numbers/arithmetic.ts @@ -1,20 +1,25 @@ -import {configDependency} from '../core/Config.js' -import {Dependency} from '../core/Dispatcher.js' +import type {configDependency} from '../core/Config.js' +import type {Dependencies, Signature} from '../interfaces/type.js' + +export const add: Signature<'add', number> = (a, b) => a + b +export const unaryMinus: Signature<'unaryMinus', number> = a => -a +export const conj: Signature<'conj', number> = a => a +export const subtract: Signature<'subtract', number> = (a, b) => a - b +export const multiply: Signature<'multiply', number> = (a, b) => a * b +export const absquare: Signature<'absquare', number> = a => a * a +export const reciprocal: Signature<'reciprocal', number> = a => 1 / a +export const divide: Signature<'divide', number> = (a, b) => a / b + +const basicSqrt = a => isNaN(a) ? NaN : Math.sqrt(a) +export const conservativeSqrt: Signature<'conservativeSqrt', number> = basicSqrt -export const add = (a: number, b: number) => a + b -export const unaryMinus = (a: number) => -a -export const subtract = (a: number, b: number) => a - b -export const multiply = (a: number, b: number) => a * b -export const divide = (a: number, b: number) => a / b export const sqrt = - (dep: configDependency - & Dependency<'complex', [number, number]>) => { - if (dep.config.predictable || !dep.complex) { - return (a: number) => isNaN(a) ? NaN : Math.sqrt(a) - } - return (a: number) => { - if (isNaN(a)) return NaN - if (a >= 0) return Math.sqrt(a) - return dep.complex(0, Math.sqrt(unaryMinus(a))) - } - } + (dep: configDependency & Dependencies<'complex', number>): + Signature<'sqrt', number> => { + if (dep.config.predictable || !dep.complex) return basicSqrt + return a => { + if (isNaN(a)) return NaN + if (a >= 0) return Math.sqrt(a) + return dep.complex(0, Math.sqrt(unaryMinus(a))) + } + } diff --git a/src/numbers/predicate.ts b/src/numbers/predicate.ts new file mode 100644 index 0000000..03bd80f --- /dev/null +++ b/src/numbers/predicate.ts @@ -0,0 +1,4 @@ +import type {Signature} from '../interfaces/type.js' + +export const isReal: Signature<'isReal', number> = (a) => true +export const isSquare: Signature<'isSquare', number> = (a) => a >= 0 diff --git a/src/numbers/relational.ts b/src/numbers/relational.ts new file mode 100644 index 0000000..8f1ac92 --- /dev/null +++ b/src/numbers/relational.ts @@ -0,0 +1,21 @@ +import {configDependency} from '../core/Config.js' +import {Signature} from '../interfaces/type.js' + +const DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16 + +export const equal = + (dep: configDependency): Signature<'equal', number> => + (x, y) => { + const eps = dep.config.epsilon + if (eps === null || eps === undefined) return x === y + if (x === y) return true + if (isNaN(x) || isNaN(y)) return false + + if (isFinite(x) && isFinite(y)) { + const diff = Math.abs(x - y) + if (diff < DBL_EPSILON) return true + return diff <= Math.max(Math.abs(x), Math.abs(y)) * eps + } + + return false + } diff --git a/src/numbers/type.ts b/src/numbers/type.ts index 67dbd29..11e5d1c 100644 --- a/src/numbers/type.ts +++ b/src/numbers/type.ts @@ -1,7 +1,25 @@ +import type { Signature } from '../interfaces/type.js' + export const number_type = { before: ['Complex'], test: (n: unknown): n is number => typeof n === 'number', - from: {string: s => +s} + from: { string: (s: string) => +s } } -export const zero = (a: number) => 0 +declare module "../interfaces/type" { + interface AssociatedTypes { + numbers: { + type: number + zero: 0 + one: 1 + nan: typeof NaN + real: number + } + } +} + +// I don't like the redundancy of repeating 'zero'; any way to eliminate that? +export const zero: Signature<'zero', number> = (a) => 0 +export const one: Signature<'one', number> = (a) => 1 +export const nan: Signature<'nan', number> = (a) => NaN +export const re: Signature<'re', number> = (a) => a From f06943ba1a47a2738999a7d75f82c6f11c8334ee Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Fri, 18 Aug 2023 10:36:11 -0700 Subject: [PATCH 04/10] chore: Update to latest TypeScript and make sure instructions work --- README.md | 1 + package.json5 | 4 +++- pnpm-lock.yaml | 32 +++++++++++++++++++++++++------- src/generic/arithmetic.ts | 2 ++ tsconfig.json | 3 ++- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d15fcc4..73af828 100644 --- a/README.md +++ b/README.md @@ -6,5 +6,6 @@ To build and run the prototype, run: ``` npx tsc +echo '{"type": "module"}' > obj/package.json node obj ``` diff --git a/package.json5 b/package.json5 index 874d5e3..9cfd021 100644 --- a/package.json5 +++ b/package.json5 @@ -18,6 +18,8 @@ url: 'https://code.studioinfinity.org/glen/typocomath.git', }, devDependencies: { - typescript: '^4.9.3', + '@types/node': '^20.5.0', + 'source-map': '^0.7.4', + typescript: '^5.1.6', }, } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 095704b..682e112 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,15 +1,33 @@ -lockfileVersion: 5.4 +lockfileVersion: '6.0' -specifiers: - typescript: ^4.9.3 +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false devDependencies: - typescript: 4.9.3 + '@types/node': + specifier: ^20.5.0 + version: 20.5.0 + source-map: + specifier: ^0.7.4 + version: 0.7.4 + typescript: + specifier: ^5.1.6 + version: 5.1.6 packages: - /typescript/4.9.3: - resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} - engines: {node: '>=4.2.0'} + /@types/node@20.5.0: + resolution: {integrity: sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==} + dev: true + + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + + /typescript@5.1.6: + resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + engines: {node: '>=14.17'} hasBin: true dev: true diff --git a/src/generic/arithmetic.ts b/src/generic/arithmetic.ts index 78ad57d..6f4e949 100644 --- a/src/generic/arithmetic.ts +++ b/src/generic/arithmetic.ts @@ -3,3 +3,5 @@ import type {Dependencies, Signature} from '../interfaces/type.js' export const square = (dep: Dependencies<'multiply', T>): Signature<'square', T> => z => dep.multiply(z, z) + // z => dep.fooBar(z, z) // fails as desired + // z => dep.multiply(z, 'foo') // fails as desired diff --git a/tsconfig.json b/tsconfig.json index aae3a94..b45999b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "target": "ES2022", "rootDir": "./src", - "outDir": "./obj" + "outDir": "./obj", + "moduleResolution": "nodenext" } } From 76e144bc2a28d1c130b6c2a53a4ca6ec8c5e67a7 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 23 Aug 2023 03:20:10 +0000 Subject: [PATCH 05/10] feat: add build script (#13) This commit adds pnpm scripts for compiling and running the typocomath package, and a convenience script `pnpm go` that does both in succession. It also configure pnpm to use a shell emulator so that it should work on Windows as well. Finally, it changes the directory for object files from obj to build. Resolves #9. Reviewed-on: https://code.studioinfinity.org/glen/typocomath/pulls/13 Co-authored-by: Glen Whitney Co-committed-by: Glen Whitney --- .gitignore | 2 +- .npmrc | 1 + README.md | 11 +++++------ etc/package.json | 1 + package.json5 | 4 ++++ tsconfig.json | 2 +- 6 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .npmrc create mode 100644 etc/package.json diff --git a/.gitignore b/.gitignore index d0c9d9e..aeea740 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ *~ # Typescript # emitted code -obj +build # ---> Node # Logs diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..3bd3b7d --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +shell-emulator=true diff --git a/README.md b/README.md index 73af828..d626b30 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,9 @@ A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state. -To build and run the prototype, run: -``` -npx tsc -echo '{"type": "module"}' > obj/package.json -node obj -``` +Convenience scripts: + +* `pnpm build` -- compile the package +* `pnpm exec` -- run the compiled code produced by `pnpm build` +* `pnpm go` -- both of the above in sequence. diff --git a/etc/package.json b/etc/package.json new file mode 100644 index 0000000..6990891 --- /dev/null +++ b/etc/package.json @@ -0,0 +1 @@ +{"type": "module"} diff --git a/package.json5 b/package.json5 index 9cfd021..f233b62 100644 --- a/package.json5 +++ b/package.json5 @@ -5,7 +5,11 @@ main: 'index.ts', scripts: { test: 'echo "Error: no test specified" && exit 1', + build: 'tsc && cp etc/package.json build', + exec: 'node build', + go: 'pnpm --sequential "/build|exec/"', }, + packageManager: 'pnpm', keywords: [ 'math', 'algebra', diff --git a/tsconfig.json b/tsconfig.json index b45999b..13b7b6c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "ES2022", "rootDir": "./src", - "outDir": "./obj", + "outDir": "./build", "moduleResolution": "nodenext" } } From 327a9385edbdec572c2bb320530f5984c863ad35 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 23 Aug 2023 16:52:16 +0000 Subject: [PATCH 06/10] fix: Use intersection of matching types in AssociatedTypes<> lookup (#14) Resolves #11. Reviewed-on: https://code.studioinfinity.org/glen/typocomath/pulls/14 Co-authored-by: Glen Whitney Co-committed-by: Glen Whitney --- src/interfaces/type.ts | 10 +++++++--- src/numbers/type.ts | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/interfaces/type.ts b/src/interfaces/type.ts index 9e6870d..9fb1163 100644 --- a/src/interfaces/type.ts +++ b/src/interfaces/type.ts @@ -13,6 +13,10 @@ * but that's OK, the generic parameter doesn't hurt in those cases. ****/ +type ValueIntersectionByKeyUnion = { + [P in TKey]: (k: T[P])=>void +} [TKey] extends ((k: infer I)=>void) ? I : never + export interface AssociatedTypes { undefined: { type: undefined @@ -24,10 +28,10 @@ export interface AssociatedTypes { } type AssociatedTypeNames = keyof AssociatedTypes['undefined'] -type ALookup = { +type ALookup = ValueIntersectionByKeyUnion<{ [K in keyof AssociatedTypes]: - T extends AssociatedTypes[K]['type'] ? AssociatedTypes[K][Name] : never -}[keyof AssociatedTypes] + T extends AssociatedTypes[K]['type'] ? AssociatedTypes[K][Name] : unknown}, + keyof AssociatedTypes> // For everything to compile, zero and one must be subtypes of T: export type ZeroType = ALookup & T diff --git a/src/numbers/type.ts b/src/numbers/type.ts index 11e5d1c..48fb95e 100644 --- a/src/numbers/type.ts +++ b/src/numbers/type.ts @@ -8,7 +8,7 @@ export const number_type = { declare module "../interfaces/type" { interface AssociatedTypes { - numbers: { + number: { type: number zero: 0 one: 1 From 180e772dab3b01ca83609aab27232c4710e171e0 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Sat, 26 Aug 2023 02:15:59 +0000 Subject: [PATCH 07/10] fix: Add types first and distinguish them semantically. (#15) Rather than via some format on the name of the identifier, this commit changes the construction of Dispatcher to assume that functions are implementations and other objects are type specifiers. Also installs all types first, before any implementations. Resolves #3. Resolves #12. Reviewed-on: https://code.studioinfinity.org/glen/typocomath/pulls/15 Co-authored-by: Glen Whitney Co-committed-by: Glen Whitney --- src/Complex/type.ts | 1 + src/core/Dispatcher.ts | 24 +++++++++++++----------- src/numbers/type.ts | 1 + 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Complex/type.ts b/src/Complex/type.ts index 50a1314..10f76b6 100644 --- a/src/Complex/type.ts +++ b/src/Complex/type.ts @@ -6,6 +6,7 @@ import type { export type Complex = { re: T; im: T; } export const Complex_type = { + name: 'Complex', // just until we have reflection to tell us test: (dep: { testT: (z: unknown) => z is T }) => (z: unknown): z is Complex => typeof z === 'object' && z != null && 're' in z && 'im' in z diff --git a/src/core/Dispatcher.ts b/src/core/Dispatcher.ts index def1bd3..ec5491f 100644 --- a/src/core/Dispatcher.ts +++ b/src/core/Dispatcher.ts @@ -25,6 +25,7 @@ export function joinTypes(a: TypeName, b: TypeName) { // Now types used in the Dispatcher class itself type TypeSpecification = { + name: string, // just until we get reflection, then we can remove this property before?: TypeName[], test: ((x: unknown) => boolean) | ((d: DependenciesType) => (x: unknown) => boolean), @@ -53,23 +54,24 @@ export class Dispatcher { //TODO: implement me } constructor(collection: SpecificationsGroup) { + const implementations = [] for (const key in collection) { console.log('Working on', key) for (const identifier in collection[key]) { - console.log('Handling', key, ':', identifier) - const parts = identifier.split('_') - if (parts[parts.length - 1] === 'type') { - parts.pop() - const name = parts.join('_') - this.installType( - name, collection[key][identifier] as TypeSpecification) + const item = collection[key][identifier] + if (typeof item === 'function') { + implementations.push([key, identifier, item]) } else { - const name = parts[0] - this.installSpecification( - name, ['dunno'], 'unsure', {}, - collection[key][identifier] as Function) + console.log('Handling type', key, ':', identifier) + this.installType( + item.name, collection[key][identifier] as TypeSpecification) } } } + for (const trio of implementations) { + const [k, id, imp] = trio + console.log('Handling implementation', id, 'from', k) + this.installSpecification(id, ['dunno'], 'unsure', {}, imp) + } } } diff --git a/src/numbers/type.ts b/src/numbers/type.ts index 48fb95e..f234a8f 100644 --- a/src/numbers/type.ts +++ b/src/numbers/type.ts @@ -1,6 +1,7 @@ import type { Signature } from '../interfaces/type.js' export const number_type = { + name: 'number', // just until we have reflection to tell us before: ['Complex'], test: (n: unknown): n is number => typeof n === 'number', from: { string: (s: string) => +s } From 40146c2f48c23d8e41e905a885338b44ee7ebca2 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Tue, 17 Oct 2023 22:02:18 +0000 Subject: [PATCH 08/10] feat: Runtime type reflection (#17) Now each behavior specification "knows" its type information. Also bumps version number and sets up so that the scripts will run on Windows as well as Unix (thanks to Jos). Resolves #5. Resolves #16. Co-authored-by: Jos de Jong Reviewed-on: https://code.studioinfinity.org/glen/typocomath/pulls/17 Co-authored-by: Glen Whitney Co-committed-by: Glen Whitney --- README.md | 4 + package.json5 | 20 +- pnpm-lock.yaml | 899 ++++++++++++++++++++++++++++++++- src/Complex/arithmetic.ts | 11 +- src/Complex/predicate.ts | 6 +- src/Complex/relational.ts | 2 + src/Complex/type.ts | 3 + src/core/Dispatcher.ts | 19 +- src/core/parseReflectedType.ts | 273 ++++++++++ src/generic/arithmetic.ts | 4 +- src/generic/relational.ts | 2 + src/index.ts | 39 +- src/interfaces/type.ts | 15 +- src/numbers/arithmetic.ts | 46 +- src/numbers/native.ts | 2 + src/numbers/predicate.ts | 7 +- src/numbers/relational.ts | 2 + src/numbers/type.ts | 11 +- tsconfig.json | 8 +- 19 files changed, 1317 insertions(+), 56 deletions(-) create mode 100644 src/core/parseReflectedType.ts diff --git a/README.md b/README.md index d626b30..2965280 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,7 @@ Convenience scripts: * `pnpm build` -- compile the package * `pnpm exec` -- run the compiled code produced by `pnpm build` * `pnpm go` -- both of the above in sequence. + +Important installation note: + +after `pnpm install`, you must execute `npx ts-patch install` to activate the ts-macros compiler plugin. diff --git a/package.json5 b/package.json5 index f233b62..02e46f3 100644 --- a/package.json5 +++ b/package.json5 @@ -1,13 +1,14 @@ { name: 'typocomath', - version: '0.0.1', + version: '0.0.2', description: 'A hopeful final typescipt-pragmatic mathjs proof-of-concept', main: 'index.ts', scripts: { test: 'echo "Error: no test specified" && exit 1', - build: 'tsc && cp etc/package.json build', - exec: 'node build', - go: 'pnpm --sequential "/build|exec/"', + build: 'mkdirp build && cpy etc/package.json build --flat && tsc', + start: 'node build', + go: 'pnpm clean && pnpm build && pnpm start', + clean: 'del-cli build', }, packageManager: 'pnpm', keywords: [ @@ -22,8 +23,13 @@ url: 'https://code.studioinfinity.org/glen/typocomath.git', }, devDependencies: { - '@types/node': '^20.5.0', - 'source-map': '^0.7.4', - typescript: '^5.1.6', + '@types/node': '20.8.4', + 'cpy-cli': '5.0.0', + 'del-cli': '5.1.0', + mkdirp: '3.0.1', + 'source-map': '0.7.4', + 'ts-macros': '2.6.0', + 'ts-patch': '3.0.2', + typescript: '5.1.6', }, } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 682e112..6791304 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,19 +6,771 @@ settings: devDependencies: '@types/node': - specifier: ^20.5.0 - version: 20.5.0 + specifier: 20.8.4 + version: 20.8.4 + cpy-cli: + specifier: 5.0.0 + version: 5.0.0 + del-cli: + specifier: 5.1.0 + version: 5.1.0 + mkdirp: + specifier: 3.0.1 + version: 3.0.1 source-map: - specifier: ^0.7.4 + specifier: 0.7.4 version: 0.7.4 + ts-macros: + specifier: 2.6.0 + version: 2.6.0(typescript@5.1.6) + ts-patch: + specifier: 3.0.2 + version: 3.0.2 typescript: - specifier: ^5.1.6 + specifier: 5.1.6 version: 5.1.6 packages: - /@types/node@20.5.0: - resolution: {integrity: sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==} + /@babel/code-frame@7.22.13: + resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.20 + chalk: 2.4.2 + dev: true + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/highlight@7.22.20: + resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@types/minimist@1.2.2: + resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} + dev: true + + /@types/node@20.8.4: + resolution: {integrity: sha512-ZVPnqU58giiCjSxjVUESDtdPk4QR5WQhhINbc9UBrKLU68MX5BF6kbQzTrkwbolyr0X8ChBpXfavr5mZFKZQ5A==} + dependencies: + undici-types: 5.25.3 + dev: true + + /@types/normalize-package-data@2.4.1: + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + dev: true + + /aggregate-error@4.0.1: + resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} + engines: {node: '>=12'} + dependencies: + clean-stack: 4.2.0 + indent-string: 5.0.0 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + dev: true + + /arrify@3.0.0: + resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} + engines: {node: '>=12'} + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /camelcase-keys@7.0.2: + resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==} + engines: {node: '>=12'} + dependencies: + camelcase: 6.3.0 + map-obj: 4.3.0 + quick-lru: 5.1.1 + type-fest: 1.4.0 + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /clean-stack@4.2.0: + resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} + engines: {node: '>=12'} + dependencies: + escape-string-regexp: 5.0.0 + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /cp-file@10.0.0: + resolution: {integrity: sha512-vy2Vi1r2epK5WqxOLnskeKeZkdZvTKfFZQCplE3XWsP+SUJyd5XAUFC9lFgTjjXJF2GMne/UML14iEmkAaDfFg==} + engines: {node: '>=14.16'} + dependencies: + graceful-fs: 4.2.11 + nested-error-stacks: 2.1.1 + p-event: 5.0.1 + dev: true + + /cpy-cli@5.0.0: + resolution: {integrity: sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ==} + engines: {node: '>=16'} + hasBin: true + dependencies: + cpy: 10.1.0 + meow: 12.1.1 + dev: true + + /cpy@10.1.0: + resolution: {integrity: sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ==} + engines: {node: '>=16'} + dependencies: + arrify: 3.0.0 + cp-file: 10.0.0 + globby: 13.2.2 + junk: 4.0.1 + micromatch: 4.0.5 + nested-error-stacks: 2.1.1 + p-filter: 3.0.0 + p-map: 6.0.0 + dev: true + + /decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /decamelize@5.0.1: + resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==} + engines: {node: '>=10'} + dev: true + + /del-cli@5.1.0: + resolution: {integrity: sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + del: 7.1.0 + meow: 10.1.5 + dev: true + + /del@7.1.0: + resolution: {integrity: sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==} + engines: {node: '>=14.16'} + dependencies: + globby: 13.2.2 + graceful-fs: 4.2.11 + is-glob: 4.0.3 + is-path-cwd: 3.0.0 + is-path-inside: 4.0.0 + p-map: 5.5.0 + rimraf: 3.0.2 + slash: 4.0.0 + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: true + + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + dev: true + + /globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: true + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-core-module@2.13.0: + resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} + dependencies: + has: 1.0.3 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-cwd@3.0.0: + resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-path-inside@4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + dev: true + + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /junk@4.0.1: + resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} + engines: {node: '>=12.20'} + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + dev: true + + /meow@10.1.5: + resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + '@types/minimist': 1.2.2 + camelcase-keys: 7.0.2 + decamelize: 5.0.1 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 8.0.0 + redent: 4.0.0 + trim-newlines: 4.1.1 + type-fest: 1.4.0 + yargs-parser: 20.2.9 + dev: true + + /meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /nested-error-stacks@2.1.1: + resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} + dev: true + + /normalize-package-data@3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + dependencies: + hosted-git-info: 4.1.0 + is-core-module: 2.13.0 + semver: 7.5.4 + validate-npm-package-license: 3.0.4 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /p-event@5.0.1: + resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-timeout: 5.1.0 + dev: true + + /p-filter@3.0.0: + resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-map: 5.5.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-map@5.5.0: + resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} + engines: {node: '>=12'} + dependencies: + aggregate-error: 4.0.1 + dev: true + + /p-map@6.0.0: + resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} + engines: {node: '>=16'} + dev: true + + /p-timeout@5.1.0: + resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} + engines: {node: '>=12'} + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.13 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + + /read-pkg-up@8.0.0: + resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==} + engines: {node: '>=12'} + dependencies: + find-up: 5.0.0 + read-pkg: 6.0.0 + type-fest: 1.4.0 + dev: true + + /read-pkg@6.0.0: + resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==} + engines: {node: '>=12'} + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 3.0.3 + parse-json: 5.2.0 + type-fest: 1.4.0 + dev: true + + /redent@4.0.0: + resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==} + engines: {node: '>=12'} + dependencies: + indent-string: 5.0.0 + strip-indent: 4.0.0 + dev: true + + /resolve@1.22.4: + resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + hasBin: true + dependencies: + is-core-module: 2.13.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} dev: true /source-map@0.7.4: @@ -26,8 +778,143 @@ packages: engines: {node: '>= 8'} dev: true + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.15 + dev: true + + /spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.15 + dev: true + + /spdx-license-ids@3.0.15: + resolution: {integrity: sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==} + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-indent@4.0.0: + resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} + engines: {node: '>=12'} + dependencies: + min-indent: 1.0.1 + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /trim-newlines@4.1.1: + resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==} + engines: {node: '>=12'} + dev: true + + /ts-macros@2.6.0(typescript@5.1.6): + resolution: {integrity: sha512-X7c4rHPTpBYY+MJUkIDIQMbTPAcv1y1sylrnDMsTvcbImleT4Wlheg3wNbORwnX8Zvq2ldZnttNXcZ1a0VE2Kg==} + hasBin: true + peerDependencies: + typescript: 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x + dependencies: + typescript: 5.1.6 + yargs-parser: 21.1.1 + dev: true + + /ts-patch@3.0.2: + resolution: {integrity: sha512-iTg8euqiNsNM1VDfOsVIsP0bM4kAVXU38n7TGQSkky7YQX/syh6sDPIRkvSS0HjT8ZOr0pq1h+5Le6jdB3hiJQ==} + hasBin: true + dependencies: + chalk: 4.1.2 + global-prefix: 3.0.0 + minimist: 1.2.8 + resolve: 1.22.4 + semver: 7.5.4 + strip-ansi: 6.0.1 + dev: true + + /type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: true + /typescript@5.1.6: resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} engines: {node: '>=14.17'} hasBin: true dev: true + + /undici-types@5.25.3: + resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==} + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/src/Complex/arithmetic.ts b/src/Complex/arithmetic.ts index 90c8eab..0f11f2e 100644 --- a/src/Complex/arithmetic.ts +++ b/src/Complex/arithmetic.ts @@ -2,6 +2,7 @@ import {Complex} from './type.js' import type { Dependencies, Signature, Returns, RealType, AliasOf } from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' declare module "../interfaces/type" { interface Signatures { @@ -78,11 +79,10 @@ export const sqrt = & Dependencies<'zero' | 'complex', T> & Dependencies<'absquare' | 're' | 'divideReal', Complex> & { - addTR: Signature<'addReal', T>, + addTR: Signature<'addReal', T>, addRR: Signature<'add', RealType>, addCR: Signature<'addReal', Complex> - }): - Signature<'sqrt', Complex> => + }): Signature<'sqrt', Complex> => z => { const myabs = dep.conservativeSqrt(dep.absquare(z)) const r = dep.re(z) @@ -98,4 +98,7 @@ export const sqrt = return dep.divideReal(num, denom) } -export const conservativeSqrt = sqrt +$reflect!([ + add, addReal, unaryMinus, conj, subtract, multiply, absquare, divideReal, + reciprocal, divide, sqrt +]) diff --git a/src/Complex/predicate.ts b/src/Complex/predicate.ts index ffcefaa..fe26906 100644 --- a/src/Complex/predicate.ts +++ b/src/Complex/predicate.ts @@ -1,9 +1,13 @@ import {Complex} from './type.js' import type {Dependencies, Signature} from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' export const isReal = (dep: Dependencies<'add' | 'equal' | 'isReal', T>): Signature<'isReal', Complex> => z => dep.isReal(z.re) && dep.equal(z.re, dep.add(z.re, z.im)) -export const isSquare: Signature<'isSquare', Complex> = z => true // FIXME: not correct for Complex once we get there +export const isSquare = (): Signature<'isSquare', Complex> => + z => true // FIXME: not correct for Complex once we get there + +$reflect!([isReal, isSquare]) diff --git a/src/Complex/relational.ts b/src/Complex/relational.ts index 78550d7..ae0cebc 100644 --- a/src/Complex/relational.ts +++ b/src/Complex/relational.ts @@ -1,6 +1,8 @@ import {Complex} from './type.js' import {Dependencies, Signature} from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' export const equal = (dep: Dependencies<'equal', T>): Signature<'equal', Complex> => (w, z) => dep.equal(w.re, z.re) && dep.equal(w.im, z.im) +$reflect!([equal]) diff --git a/src/Complex/type.ts b/src/Complex/type.ts index 10f76b6..998003e 100644 --- a/src/Complex/type.ts +++ b/src/Complex/type.ts @@ -2,6 +2,7 @@ import {joinTypes, typeOfDependency} from '../core/Dispatcher.js' import type { ZeroType, OneType, NaNType, Dependencies, Signature, Returns } from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' export type Complex = { re: T; im: T; } @@ -62,3 +63,5 @@ export const nan = export const re = (dep: Dependencies<'re', T>): Signature<'re', Complex> => z => dep.re(z.re) + +$reflect!([complex, zero, one, nan, re]) diff --git a/src/core/Dispatcher.ts b/src/core/Dispatcher.ts index ec5491f..4ede7cd 100644 --- a/src/core/Dispatcher.ts +++ b/src/core/Dispatcher.ts @@ -5,6 +5,8 @@ * for specific types (including their own). */ +import {parseReflectedType, ImplementationDef} from './parseReflectedType.js' + // First helper types and functions for the Dispatcher type TypeName = string @@ -39,21 +41,25 @@ type SpecificationsGroup = Record export class Dispatcher { installSpecification( name: string, - signature: Signature, - returns: TypeName, - dependencies: Record, + defn: ImplementationDef, behavior: Function // possible todo: constrain this type based // on the signature, return type, and dependencies. Not sure if // that's really possible, though. ) { - console.log('Pretending to install', name, signature, '=>', returns) + console.log('Pretending to install', name, 'with signatures') + for (const signature of defn.fn.signatures) { + console.log(' ', signature.args, '=>', signature.returns) + } + if (defn.fn.aliasOf) { + console.log(' As an alias of', defn.fn.aliasOf) + } //TODO: implement me } installType(name: TypeName, typespec: TypeSpecification) { console.log('Pretending to install type', name, typespec) //TODO: implement me } - constructor(collection: SpecificationsGroup) { + constructor(collection: SpecificationsGroup) { const implementations = [] for (const key in collection) { console.log('Working on', key) @@ -71,7 +77,8 @@ export class Dispatcher { for (const trio of implementations) { const [k, id, imp] = trio console.log('Handling implementation', id, 'from', k) - this.installSpecification(id, ['dunno'], 'unsure', {}, imp) + this.installSpecification( + id, parseReflectedType(id, imp.reflectedType), imp) } } } diff --git a/src/core/parseReflectedType.ts b/src/core/parseReflectedType.ts new file mode 100644 index 0000000..e4b72a3 --- /dev/null +++ b/src/core/parseReflectedType.ts @@ -0,0 +1,273 @@ +export type FunctionDef { + name: string, + aliasOf?: string, + signatures: Array<{ + args: Array<{ name: string, type: string }> + returns: string + }> +} + + +export type ImplementationDef = { + fn: FunctionDef, + dependencies: Record +} + +/** + * Parse a reflected type coming out of TypeScript into a structured object, for example: + * + * '(dep: configDependency & { complex: ((re: number) => Complex) | ((re: number, im: number) => Complex); }) => (a: number) => number | Complex' + */ +export function parseReflectedType(name: string, reflectedType: string): ImplementationDef { + console.log('For', name, 'parsing', reflectedType) + const [factoryArgs, fnsClause] = split(reflectedType, '=>', 2).map(trim) + const fn = parseAlias(name, fnsClause) + + const factoryArgsInner = findBlockContents(factoryArgs, '(', ')') + const depArg = split(factoryArgsInner.innerText, ':').map(trim)[1] + const depArgBlocks: string[] = depArg ? split(depArg, '&').map(trim) : [] + + const deps = depArgBlocks + .filter(depArgBlock => { + if (depArgBlock.startsWith('{') || depArgBlock === 'configDependency') { + return true + } else { + throw new SyntaxError(`Cannot parse dependency "${depArgBlock}"`) + } + }) + .flatMap(parseDependencies) + + const dependencies: Record = groupBy(deps, 'name') + + return {fn, dependencies} +} + +function parseDependencies(deps: string): FunctionDef[] { + if (deps === 'configDependency') { + return [{name: 'config', signatures: [{args: [], returns: 'Config'}]}] + } + const inner = findBlockContents(deps, '{', '}').innerText + return split(inner, ';') + .map(trim) + .filter(notEmpty) + .map(parseDependency) +} + +// parse a dependency like "complex: ((re: number) => Complex) | ((re: number, im: number) => Complex)" +function parseDependency(dep: string): FunctionDef { + const [name, def] = split(dep, ':').map(trim) + + return parseAlias(name, def) +} + +// Parse a possibly aliased function +function parseAlias(name: string, alias: string): FunctionDef { + const { aliasOf, innerSignature } = parseAliasOf(alias) + + return { name, signatures: parseSignatures(innerSignature), aliasOf } +} + +// parse function signatures like ((re: number) => Complex) | ((re: number, im: number) => Complex) +// But also have to succeed on (a: number) => number | Complex +// That's why we only split on an alternation bar `|` that's followed by +// a parenthesis; that way we avoid splitting a union return type. Note +// this is not necessarily foolproof, as there could be a return type that +// is a union with a complicated piece that has to be enclosed in parens; +// but so far it seems to work in practice. +function parseSignatures(sigs: string) { + return split(sigs, /[|]\s*(?=[(])/) + .map(trim) + .map(stripParenthesis) + .map(signature => { + const [argsBlock, returns] = split(signature, '=>').map(trim) + + if (!returns) { + throw new SyntaxError(`Failed to find return type in '${signature}'`) + } + + return { + args: parseArgs(argsBlock), + returns + } + }) +} + +// parse args like "(re: number, im: number)" +function parseArgs(argsBlock: string) : Array<{name: string, type: string}> { + const args = findBlockContents(argsBlock, '(', ')').innerText + + return split(args, ',') + .map(trim) + .map(arg => { + const [name, type] = split(arg, ':').map(trim) + return { name, type} + }) +} + +// parse "AliasOf<"divide", (a: Complex, b: RealType>) => Complex>" +function parseAliasOf(signature: string) : { innerSignature: string, aliasOf: string | undefined } { + if (!signature.startsWith('AliasOf')) { + return { + innerSignature: signature, + aliasOf: undefined + } + } + + const inner = findBlockContents(signature, '<', '>').innerText.trim() + const [aliasOfWithQuotes, innerSignature] = split(inner, ',').map(trim) + return { + innerSignature, + aliasOf: aliasOfWithQuotes.substring(1, aliasOfWithQuotes.length - 1) // remove double quotes + } +} + +// remove the outer parenthesis, for example "((re: number) => Complex)" returns "(re: number) => Complex" +function stripParenthesis(text: string) : string { + return text.startsWith('(') && text.endsWith(')') + ? text.substring(1, text.length - 1) + : text +} + +function findBlockContents(text: string, blockStart: string, blockEnd: string, startIndex = 0) : { start: number, end: number, innerText: string } | undefined { + let i = startIndex + + while (!matchSubString(text, blockStart, i) && i < text.length) { + i++ + } + + if (i >= text.length) { + return undefined + } + + i++ + const start = i + + while (!matchSubString(text, blockEnd, i) || matchSubString(text, '=>', i - 1)) { + i = skipBrackets(text, i) + + i++ + } + + if (i >= text.length) { + return undefined + } + const end = i + + return { + start, + end, + innerText: text.substring(start, end) + } +} + +/** + * Given a string, generate a string source for a regexp that will match + * exactly the given string. + * Uses the fact that the only characters that need to be escaped in + * a character class are \, ], and ^ + */ +function regexpQuote(s: string) { + const special = '\\]^' + let re = '' + for (const char of s) { + if (special.includes(char)) re += `\\${char}` + else re += `[${char}]` + } + return re +} + +/** + * Split a string by a delimiter, but ignore all occurrences of the delimiter + * that are inside bracket pairs <> () [] {} + */ +export function split( + text: string, delimiter: string | RegExp, pieces = 0): string[] { + const delim: RegExp = typeof delimiter === 'string' + ? new RegExp(regexpQuote(delimiter), 'y') + : new RegExp(delimiter.source, 'y') + const parts: string[] = [] + + let i = 0 + let n = 1 + let start = 0 + while (i < text.length && (pieces === 0 || n < pieces)) { + i = skipBrackets(text, i) + + delim.lastIndex = i + const result = delim.exec(text) + if (result) { + parts.push(text.substring(start, i)) + n += 1 + i += result[0].length + start = i + } + + i++ + } + + parts.push(text.substring(start)) + + return parts +} + +function skipBrackets(text: string, startIndex: number) : number { + let level = 0 + let i = startIndex + + do { + if (isBracketOpen(text, i)) { + level++ + } + + if (isBracketClose(text, i) && level > 0) { + level-- + } + + if (level === 0) { + break + } + + i++ + } while(i < text.length) + + return i +} + +function isBracketOpen(text: string, index: number) { + const char = text[index] + return char === '(' || char === '<' || char === '[' || char === '{' +} + +function isBracketClose(text: string, index: number) { + const char = text[index] + // we need to take care of not matching the ">" of the operator "=>" + return char === ')' || (char === '>' && text[index - 1] !== '=') || char === ']' || char === '}' +} + +function matchSubString(text: string, search: string, index: number) : boolean { + for (let i = 0; i < search.length; i++) { + if (text[i + index] !== search[i]) { + return false + } + } + + return true +} + +function trim(text: string) : string { + return text.trim() +} + +function notEmpty(text: string) : boolean { + return text.length > 0 +} + +function groupBy(items: T[], key: string) : Record { + const obj: Record = {} + + items.forEach((item) => { + obj[item[key]] = item + }) + + return obj +} diff --git a/src/generic/arithmetic.ts b/src/generic/arithmetic.ts index 6f4e949..37ea84a 100644 --- a/src/generic/arithmetic.ts +++ b/src/generic/arithmetic.ts @@ -1,7 +1,9 @@ import type {Dependencies, Signature} from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' export const square = (dep: Dependencies<'multiply', T>): Signature<'square', T> => z => dep.multiply(z, z) // z => dep.fooBar(z, z) // fails as desired - // z => dep.multiply(z, 'foo') // fails as desired + // z => dep.multiply(z, 'foo') // still fails as desired +$reflect!([square]) diff --git a/src/generic/relational.ts b/src/generic/relational.ts index 714cb49..a05c535 100644 --- a/src/generic/relational.ts +++ b/src/generic/relational.ts @@ -1,5 +1,7 @@ import {Dependencies, Signature} from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' export const unequal = (dep: Dependencies<'equal', T>): Signature<'unequal', T> => (x, y) => !dep.equal(x, y) +$reflect!([unequal]) diff --git a/src/index.ts b/src/index.ts index 297b271..e3377e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +import {inspect} from 'node:util' import {Dispatcher} from './core/Dispatcher.js' import * as Specifications from './all.js' @@ -5,16 +6,48 @@ export default new Dispatcher(Specifications) import {Complex} from './Complex/type.js' import {absquare as absquare_complex} from './Complex/arithmetic.js' +import {parseReflectedType} from './core/parseReflectedType.js' const mockRealAdd = (a: number, b: number) => a+b const mockComplexAbsquare = (z: Complex) => z.re*z.re + z.im*z.im +const mockComplex = (re: number, im: number) => ({ re, im }) + +const config = { + predictable: false, + epsilon: 1e-14 +} const quatAbsquare = absquare_complex({ - add: mockRealAdd, - absquare: mockComplexAbsquare + add: mockRealAdd, + absquare: mockComplexAbsquare }) const myabs = quatAbsquare({re: {re: 0, im: 1}, im: {re:2, im: 3}}) const typeTest: typeof myabs = 7 // check myabs is just a number +console.log('Result is myabs=', myabs) -console.log('Result is', myabs) +const sqrt = Specifications.numbers.sqrt({ + config, + complex: mockComplex +}) +console.log('Result of sqrt(16)=', sqrt(16)) +console.log('Result of sqrt(-4)=', sqrt(-4)) + +console.log() +console.log('1) NUMBER SQRT') +console.log(`1.1) REFLECTED TYPE: "${Specifications.numbers.sqrt.reflectedType}"`) +console.log( + '1.2) PARSED TYPE:', + inspect( + parseReflectedType('sqrt', Specifications.numbers.sqrt.reflectedType), + { depth: null, colors: true })) + +console.log() +console.log('2) GENERIC SQUARE') +console.log(`1.1) REFLECTED TYPE: "${Specifications.generic.square.reflectedType}"`) +console.log('2.2) PARSED TYPE:', inspect(parseReflectedType('square', Specifications.generic.square.reflectedType), { depth: null, colors: true })) + +console.log() +console.log('3) COMPLEX SQRT') +console.log(`1.1) REFLECTED TYPE: "${Specifications.complex.sqrt.reflectedType}"`) +console.log('3.2) PARSED TYPE:', inspect(parseReflectedType('sqrt', Specifications.complex.sqrt.reflectedType), { depth: null, colors: true })) diff --git a/src/interfaces/type.ts b/src/interfaces/type.ts index 9fb1163..3ab1b9a 100644 --- a/src/interfaces/type.ts +++ b/src/interfaces/type.ts @@ -1,3 +1,5 @@ +import {$$typeToString} from 'ts-macros' + /***** * Every typocomath type has some associated types; they need * to be published in the following interface. The key is the @@ -73,7 +75,16 @@ export interface Signatures { type SignatureKey = keyof Signatures export type Signature, T> = Signatures[Name] -export type Returns, T> = ReturnType[Name]> -export type Dependencies, T> = {[K in Name]: Signature} +export type Returns, T> = + ReturnType[Name]> +type Deps = T extends unknown ? { [K in keyof T]: T[K] } : never; +export type Dependencies, T> = + Deps<{[K in Name]: Signature}> export type AliasOf = T & {aliasOf?: Name} + +// For defining implementations with type reflection +export function $reflect(tup: ImplTuple) { + +[[tup], (elt: T) => + elt.reflectedType = $$typeToString!(true, false, true)] +} diff --git a/src/numbers/arithmetic.ts b/src/numbers/arithmetic.ts index 11da5c2..51d2ce5 100644 --- a/src/numbers/arithmetic.ts +++ b/src/numbers/arithmetic.ts @@ -1,25 +1,35 @@ import type {configDependency} from '../core/Config.js' import type {Dependencies, Signature} from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' -export const add: Signature<'add', number> = (a, b) => a + b -export const unaryMinus: Signature<'unaryMinus', number> = a => -a -export const conj: Signature<'conj', number> = a => a -export const subtract: Signature<'subtract', number> = (a, b) => a - b -export const multiply: Signature<'multiply', number> = (a, b) => a * b -export const absquare: Signature<'absquare', number> = a => a * a -export const reciprocal: Signature<'reciprocal', number> = a => 1 / a -export const divide: Signature<'divide', number> = (a, b) => a / b +export const add = (): Signature<'add', number> => (a, b) => a + b +const unaMinus = (a: number) => -a +export const unaryMinus = (): Signature<'unaryMinus', number> => unaMinus +export const conj = (): Signature<'conj', number> => a => a +export const subtract = (): Signature<'subtract', number> => (a, b) => a - b +export const multiply = (): Signature<'multiply', number> => (a, b) => a * b +export const absquare = (): Signature<'absquare', number> => a => a * a +export const reciprocal = (): Signature<'reciprocal', number> => a => 1 / a +export const divide = (): Signature<'divide', number> => (a, b) => a / b -const basicSqrt = a => isNaN(a) ? NaN : Math.sqrt(a) -export const conservativeSqrt: Signature<'conservativeSqrt', number> = basicSqrt +const basicSqrt = (a: number) => isNaN(a) ? NaN : Math.sqrt(a) +export const conservativeSqrt = (): Signature<'conservativeSqrt', number> => + basicSqrt export const sqrt = - (dep: configDependency & Dependencies<'complex', number>): - Signature<'sqrt', number> => { - if (dep.config.predictable || !dep.complex) return basicSqrt - return a => { - if (isNaN(a)) return NaN - if (a >= 0) return Math.sqrt(a) - return dep.complex(0, Math.sqrt(unaryMinus(a))) - } + (dep: configDependency + & Dependencies<'complex', number>): Signature<'sqrt', number> => { + if (dep.config.predictable || !dep.complex) { + return basicSqrt + } + return a => { + if (isNaN(a)) return NaN + if (a >= 0) return Math.sqrt(a) + return dep.complex(0, Math.sqrt(unaMinus(a))) + } } + +$reflect!([ + add, unaryMinus, conj, subtract, multiply, absquare, reciprocal, divide, + conservativeSqrt, sqrt +]) diff --git a/src/numbers/native.ts b/src/numbers/native.ts index 10cd111..ea2f66b 100644 --- a/src/numbers/native.ts +++ b/src/numbers/native.ts @@ -1,2 +1,4 @@ export * from './type.js' export * from './arithmetic.js' +export * from './predicate.js' +export * from './relational.js' diff --git a/src/numbers/predicate.ts b/src/numbers/predicate.ts index 03bd80f..0a51d65 100644 --- a/src/numbers/predicate.ts +++ b/src/numbers/predicate.ts @@ -1,4 +1,7 @@ import type {Signature} from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' -export const isReal: Signature<'isReal', number> = (a) => true -export const isSquare: Signature<'isSquare', number> = (a) => a >= 0 +export const isReal = (): Signature<'isReal', number> => (a) => true +export const isSquare = (): Signature<'isSquare', number> => (a) => a >= 0 + +$reflect!([isReal, isSquare]) diff --git a/src/numbers/relational.ts b/src/numbers/relational.ts index 8f1ac92..9dc9891 100644 --- a/src/numbers/relational.ts +++ b/src/numbers/relational.ts @@ -1,5 +1,6 @@ import {configDependency} from '../core/Config.js' import {Signature} from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' const DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16 @@ -19,3 +20,4 @@ export const equal = return false } +$reflect!([equal]) diff --git a/src/numbers/type.ts b/src/numbers/type.ts index f234a8f..fde9337 100644 --- a/src/numbers/type.ts +++ b/src/numbers/type.ts @@ -1,4 +1,5 @@ import type { Signature } from '../interfaces/type.js' +import {$reflect} from '../interfaces/type.js' export const number_type = { name: 'number', // just until we have reflection to tell us @@ -20,7 +21,9 @@ declare module "../interfaces/type" { } // I don't like the redundancy of repeating 'zero'; any way to eliminate that? -export const zero: Signature<'zero', number> = (a) => 0 -export const one: Signature<'one', number> = (a) => 1 -export const nan: Signature<'nan', number> = (a) => NaN -export const re: Signature<'re', number> = (a) => a +export const zero = (): Signature<'zero', number> => (a) => 0 +export const one = (): Signature<'one', number> => (a) => 1 +export const nan = (): Signature<'nan', number> => (a) => NaN +export const re = (): Signature<'re', number> => (a) => a + +$reflect!([zero, one, nan, re]) diff --git a/tsconfig.json b/tsconfig.json index 13b7b6c..63c0b04 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,12 @@ { "compilerOptions": { - "target": "ES2022", + "target": "esnext", "rootDir": "./src", "outDir": "./build", - "moduleResolution": "nodenext" + "moduleResolution": "nodenext", + "plugins": [ { + "transform": "ts-macros/dist/type-resolve", + "transformProgram": true + } ] } } From 0cdc9aba7809558dfa2fe2b181a22fb4d2f377bb Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 18 Oct 2023 15:11:54 +0200 Subject: [PATCH 09/10] chore: fix typo in type definition of `FunctionDef` --- src/core/parseReflectedType.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/parseReflectedType.ts b/src/core/parseReflectedType.ts index e4b72a3..a2e9866 100644 --- a/src/core/parseReflectedType.ts +++ b/src/core/parseReflectedType.ts @@ -1,4 +1,4 @@ -export type FunctionDef { +export type FunctionDef = { name: string, aliasOf?: string, signatures: Array<{ From 6bfd06cafb29749542f835a08ccc54fbbba049ba Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 18 Oct 2023 15:22:21 +0200 Subject: [PATCH 10/10] feat: extract generic parameter from the reflectedType (see #18) --- src/core/parseReflectedType.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/parseReflectedType.ts b/src/core/parseReflectedType.ts index a2e9866..6212320 100644 --- a/src/core/parseReflectedType.ts +++ b/src/core/parseReflectedType.ts @@ -11,6 +11,7 @@ export type FunctionDef = { export type ImplementationDef = { fn: FunctionDef, dependencies: Record + genericParameter: string | null } /** @@ -23,6 +24,11 @@ export function parseReflectedType(name: string, reflectedType: string): Impleme const [factoryArgs, fnsClause] = split(reflectedType, '=>', 2).map(trim) const fn = parseAlias(name, fnsClause) + // extract the generic parameter like '' at the start of the type + const genericParameter = factoryArgs.trim().startsWith('<') + ? findBlockContents(factoryArgs, '<', '>')?.innerText || null + : null + const factoryArgsInner = findBlockContents(factoryArgs, '(', ')') const depArg = split(factoryArgsInner.innerText, ':').map(trim)[1] const depArgBlocks: string[] = depArg ? split(depArg, '&').map(trim) : [] @@ -39,7 +45,7 @@ export function parseReflectedType(name: string, reflectedType: string): Impleme const dependencies: Record = groupBy(deps, 'name') - return {fn, dependencies} + return {fn, dependencies, genericParameter } } function parseDependencies(deps: string): FunctionDef[] {