diff --git a/.vscode/settings.json b/.vscode/settings.json index 8a3d3d8..c8dc691 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "prettier.configPath": ".prettierrc.js", "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true -} \ No newline at end of file + "editor.formatOnSave": true, + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/package.json b/package.json index 24809d2..432a7b1 100644 --- a/package.json +++ b/package.json @@ -19,19 +19,19 @@ "url": "https://github.com/bhouston/behave-graph" }, "devDependencies": { - "@openzeppelin/contracts": "^4.7.3", - "@preconstruct/cli": "^2.2.2", - "@typechain/ethers-v5": "^10.1.1", - "@typechain/hardhat": "^6.1.4", "@babel/core": "^7.17.10", "@babel/preset-env": "^7.17.10", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.16.7", + "@openzeppelin/contracts": "^4.7.3", + "@preconstruct/cli": "^2.2.2", + "@typechain/ethers-v5": "^10.1.1", + "@typechain/hardhat": "^6.1.4", "dotenv": "^16.0.3", - "prettier": "^2.7.1", + "prettier": "^2.8.0", "ts-node": ">=8.0.0", "typechain": "^8.1.1", - "typescript": ">=4.5.0" + "typescript": "^4.9.3" }, "resolutions": { "undici": "5.5.1" @@ -57,7 +57,8 @@ ], "preconstruct": { "packages": [ - "editor" + "editor", + "packages/*" ] } } diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 0000000..3599478 --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,24 @@ +{ + "name": "@interx/core", + "version": "0.0.1", + "description": "", + "main": "index.js", + "scripts": { + "test": "mocha --require ts-node/register 'src/**/*.ts'" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@behave-graph/core": "^0.9.11", + "chai": "^4.3.7", + "hardhat": "^2.12.2", + "mocha": "^10.1.0", + "typescript": "^4.9.3" + }, + "devDependencies": { + "@types/expect": "^24.3.0", + "@types/mocha": "^10.0.0", + "ts-mocha": "^10.0.0", + "type-fest": "^3.2.0" + } +} diff --git a/packages/core/src/nodes/flow/Branch.test.ts b/packages/core/src/nodes/flow/Branch.test.ts new file mode 100644 index 0000000..4a2dc2b --- /dev/null +++ b/packages/core/src/nodes/flow/Branch.test.ts @@ -0,0 +1,38 @@ +import { expect } from 'chai'; +import { buildStubEngineForFlowNode } from '../schema/testUtils'; +import Branch from './Branch'; + +describe('Branch', () => { + describe('trigger', () => { + it('commits the true output when value is true', () => { + const { trigger, writeInput, getOutputWrites } = buildStubEngineForFlowNode(Branch); + + writeInput('condition', true); + trigger('flow'); + + const expected = [ + { + writeType: 'flow', + socketName: 'true', + }, + ]; + + expect(getOutputWrites()).to.eql(expected); + }); + it('commits the true output when value is false', () => { + const { trigger, writeInput, getOutputWrites } = buildStubEngineForFlowNode(Branch); + + writeInput('condition', false); + trigger('flow'); + + const expected = [ + { + writeType: 'flow', + socketName: 'false', + }, + ]; + + expect(getOutputWrites()).to.eql(expected); + }); + }); +}); diff --git a/packages/core/src/nodes/flow/Branch.ts b/packages/core/src/nodes/flow/Branch.ts new file mode 100644 index 0000000..21b9a5a --- /dev/null +++ b/packages/core/src/nodes/flow/Branch.ts @@ -0,0 +1,27 @@ +import { makeFlowNodeDefinition } from '../schema/FlowNodes'; + +const Branch = makeFlowNodeDefinition({ + inputSockets: { + flow: { + valueType: 'flow', + }, + condition: { + valueType: 'boolean', + }, + }, + outputSockets: { + true: { + valueType: 'flow', + }, + false: { + valueType: 'flow', + }, + }, + triggered: ({ commit, readInput }) => { + const value = readInput('condition'); + commit(value ? 'true' : 'false'); + }, + initialState: () => undefined, +}); + +export default Branch; diff --git a/packages/core/src/nodes/flow/Counter.test.ts b/packages/core/src/nodes/flow/Counter.test.ts new file mode 100644 index 0000000..ce52a97 --- /dev/null +++ b/packages/core/src/nodes/flow/Counter.test.ts @@ -0,0 +1,78 @@ +import { expect } from 'chai'; +import { buildStubEngineForFlowNode, RecordedOutputWrites } from '../schema/testUtils'; +import Counter from './Counter'; + +describe('Branch', () => { + describe('trigger', () => { + it('writes to the output and triggers a flow for each trigger', () => { + const { trigger, getOutputWrites } = buildStubEngineForFlowNode(Counter); + + trigger('flow'); + trigger('flow'); + + const expected: RecordedOutputWrites = [ + { + writeType: 'value', + socketName: 'count', + value: 1n, + }, + { + writeType: 'flow', + socketName: 'flow', + }, + { + writeType: 'value', + socketName: 'count', + value: 2n, + }, + { + writeType: 'flow', + socketName: 'flow', + }, + ]; + + expect(getOutputWrites()).to.eql(expected); + }); + it('resets the value to 0 but doesnt write the update on reset', () => { + const { trigger, getOutputWrites } = buildStubEngineForFlowNode(Counter); + + trigger('flow'); + trigger('flow'); + trigger('reset'); + trigger('flow'); + + const expected: RecordedOutputWrites = [ + { + writeType: 'value', + socketName: 'count', + value: 1n, + }, + { + writeType: 'flow', + socketName: 'flow', + }, + { + writeType: 'value', + socketName: 'count', + value: 2n, + }, + { + writeType: 'flow', + socketName: 'flow', + }, + // reset triggered - goes back to 0 but value isnt emitted + { + writeType: 'value', + socketName: 'count', + value: 1n, + }, + { + writeType: 'flow', + socketName: 'flow', + }, + ]; + + expect(getOutputWrites()).to.eql(expected); + }); + }); +}); diff --git a/packages/core/src/nodes/flow/Counter.ts b/packages/core/src/nodes/flow/Counter.ts new file mode 100644 index 0000000..f3488f1 --- /dev/null +++ b/packages/core/src/nodes/flow/Counter.ts @@ -0,0 +1,48 @@ +import { makeFlowNodeDefinition } from '../schema/FlowNodes'; + +const Counter = makeFlowNodeDefinition({ + inputSockets: { + flow: { + valueType: 'flow', + }, + reset: { + valueType: 'flow', + }, + }, + outputSockets: { + flow: { + valueType: 'flow', + }, + count: { + valueType: 'integer', + }, + }, + triggered: ({ commit, writeOutput, state, triggeringSocketName }) => { + // duplicate count to not modify the state + let count = state.count + 0n; + + switch (triggeringSocketName) { + case 'flow': { + count++; + writeOutput('count', count); + commit('flow'); + break; + } + case 'reset': { + count = 0n; + break; + } + default: + throw new Error('should not get here'); + } + + return { + count, + }; + }, + initialState: () => ({ + count: 0n, + }), +}); + +export default Counter; diff --git a/packages/core/src/nodes/schema/FlowNodes.ts b/packages/core/src/nodes/schema/FlowNodes.ts new file mode 100644 index 0000000..d6e61ad --- /dev/null +++ b/packages/core/src/nodes/schema/FlowNodes.ts @@ -0,0 +1,60 @@ +import { FlowSocketNames, FlowSockets, IHasSockets, Sockets, ValueSockets, ValueTypeNameMapping } from './Sockets'; +/** Node Engine Access Functions */ + +export type readNodeInputFn = < + TValueSockets extends ValueSockets, + KValueSocket extends keyof TValueSockets +>( + param: KValueSocket +) => ValueTypeNameMapping; + +export type writeNodeOutputFn = , J extends keyof V>( + param: J, + value: ValueTypeNameMapping +) => void; + +export type commitFn = >(param: J) => void; + +/** Flow Node Definitions */ + +export type ReadWriteToNodeParams = { + /** reads a value from an input node */ + readInput: readNodeInputFn; + /** writes to an output node */ + writeOutput: writeNodeOutputFn; +}; + +/** Arguments for the triggered function on a flow node */ +export type TriggeredParams = ReadWriteToNodeParams< + TInput, + TOutput +> & { + /** commits a trigger to a flow node */ + commit: commitFn; + /** The local node's state */ + readonly state: TNodeState; + /** The name of the flow input socket that was triggered */ + triggeringSocketName: FlowSocketNames; +}; + +export type TriggeredFunction< + TInput extends Sockets, + TOutput extends Sockets, + TNodeState +> = TNodeState extends undefined + ? (params: TriggeredParams) => void + : (params: TriggeredParams) => TNodeState; + +export interface IFlowNode + extends IHasSockets { + /** Called when an input flow node is triggered */ + triggered: TriggeredFunction; + initialState: () => TNodeState; +} +export function makeFlowNodeDefinition< + TInputSockets extends Sockets, + TOutputSockets extends Sockets, + TNodeState = undefined +>(flowNode: IFlowNode) { + return flowNode; +} diff --git a/packages/core/src/nodes/schema/INodeDefinition.test.ts b/packages/core/src/nodes/schema/INodeDefinition.test.ts new file mode 100644 index 0000000..ea41df0 --- /dev/null +++ b/packages/core/src/nodes/schema/INodeDefinition.test.ts @@ -0,0 +1,69 @@ +import { makeFlowNodeDefinition, readNodeInputFn } from './FlowNodes'; +import { FlowSockets, ValueSockets, ExtractValueType, ValueTypeNameMapping, Sockets } from './Sockets'; +import { expectType } from './testUtils'; + +describe('TriggeredParams', () => { + describe('writeOutput', () => { + it('can only write output to a socket in the output definition that is a value type', () => { + const flowDef = makeFlowNodeDefinition({ + inputSockets: { + a: { + valueType: 'boolean', + }, + b: { + valueType: 'string', + }, + c: { + valueType: 'flow', + }, + }, + outputSockets: { + c: { + valueType: 'float', + }, + d: { + valueType: 'integer', + }, + e: { + valueType: 'flow', + }, + f: { + valueType: 'string', + }, + }, + triggered: ({ commit, readInput, writeOutput }) => { + const a = readInput('a'); + + writeOutput('c', a ? 1.0 : 0.0); + + commit('e'); + + return undefined; + }, + initialState: () => undefined, + }); + + expectType>({ + a: { + valueType: 'boolean', + }, + b: { + valueType: 'string', + }, + }); + + expectType>({ + c: { + valueType: 'flow', + }, + }); + + expectType>(true); + expectType>('asdfasfd'); + expectType>(false); + + expectType>>(['a']); + expectType>>(['b']); + }); + }); +}); diff --git a/packages/core/src/nodes/schema/INodeDefinition.ts b/packages/core/src/nodes/schema/INodeDefinition.ts new file mode 100644 index 0000000..5974f7e --- /dev/null +++ b/packages/core/src/nodes/schema/INodeDefinition.ts @@ -0,0 +1,8 @@ +import { NodeCategory } from '@behave-graph/core'; +import { IHasSockets } from './Sockets'; + +// export interface INodeDefinition extends IHasSockets { +// typeName: string; +// category: NodeCategory; +// label: string; +// } diff --git a/packages/core/src/nodes/schema/ImmediateNodes.ts b/packages/core/src/nodes/schema/ImmediateNodes.ts new file mode 100644 index 0000000..9015db6 --- /dev/null +++ b/packages/core/src/nodes/schema/ImmediateNodes.ts @@ -0,0 +1,78 @@ +import { ReadWriteToNodeParams } from './FlowNodes'; +import { Sockets } from './Sockets'; + +// type PickSocket = TSockets[k]; + +// type PickValueTypes = { +// readonly [K in keyof inputOrder]: ValueTypeNameMapping['valueType']>; +// }; + +// type unaryEvalFunction< +// TInput extends Sockets, +// TOutputs extends Sockets, +// inputOrder extends readonly (keyof TInput)[], +// outputOrder extends readonly (keyof TOutputs)[] +// > = (...params: PickValueTypes) => PickValueTypes; + +export type ImmediateExecFn = ( + params: ReadWriteToNodeParams +) => void; + +export interface IImmediateNode { + inputSockets: TIn; + outputSockets: TOut; + exec: ImmediateExecFn; +} + +export function makeImmediateNodeDefinition( + nodeDefinition: IImmediateNode +) { + return nodeDefinition; +} + +export function makeExec(exec: ImmediateExecFn) { + return exec; +} + +// export function makeImmediateInNOutNodeDefinition< +// TIn extends Sockets, +// TOut extends Sockets, +// inputOrder extends (keyof TIn)[], +// outputOrder extends (keyof TOut)[] +// >({ +// inputValueTypes, +// outputValueTypes, +// unaryEvalFunc, +// }: { +// inputValueTypes: TIn; +// outputValueTypes: TOut; +// inputOrder: keyof TIn[]; +// outputOrder: keyof TOut[]; +// unaryEvalFunc: unaryEvalFunction; +// }): IImmediateNode { +// const exec: ReadWriteToNodeParams = ({ readInput }) => { +// return; +// }; + +// // = ({ readInput, writeOutput }) => { +// // const inputNames = inputValueTypes.map(({ name }) => name) as SocketNames; +// // const outputNames = outputValueTypes.map(({ name }) => name) as SocketNames; + +// // const inputValues = inputNames.map((x) => readInput(x)) as unknown as SocketValueTypes; + +// // const outputValues = unaryEvalFunc(...inputValues) as unknown as SocketValueTypes; + +// // outputNames.forEach((outputName, i) => { +// // // @ts-ignore +// // writeOutput(outputName, outputValues[i]); +// // }); +// // }; + +// const node: IImmediateNode = { +// inputSockets: inputValueTypes, +// outputSockets: outputValueTypes, +// exec, +// }; + +// return node; +// } diff --git a/packages/core/src/nodes/schema/Sockets.ts b/packages/core/src/nodes/schema/Sockets.ts new file mode 100644 index 0000000..9552e2b --- /dev/null +++ b/packages/core/src/nodes/schema/Sockets.ts @@ -0,0 +1,88 @@ +import { UnionToIntersection } from 'type-fest'; + +export type SocketValueType = 'flow' | 'boolean' | 'integer' | 'float' | 'string' | 'jsonPath'; + +export type ValueTypeNameMapping = { + boolean: boolean; + integer: bigint; + float: number; + string: string; + jsonPath: string; + flow: void; +}[K]; + +export type ValueTypeMappings = { + [K in keyof SocketValueTypes]: ValueTypeNameMapping; +}; + +export type OptionalValueTypeMapping = ValueTypeNameMapping | undefined; + +export interface ISocketDefinition { + readonly valueType: SocketValueType; +} + +export type Sockets = { + readonly [key: string]: ISocketDefinition; +}; + +type FlowSocketDef = { + valueType: 'flow'; +}; + +export type ValueSockets = Pick< + T, + { [K in keyof T]-?: T[K] extends FlowSocketDef ? never : K }[keyof T] +>; + +export type FlowSockets = Pick< + T, + { [K in keyof T]-?: T[K] extends FlowSocketDef ? K : never }[keyof T] +>; + +export type FlowSocketNames = keyof FlowSockets; + +/** IHasSockets Utils */ + +export type IHasSockets = { + readonly inputSockets: TInputSockets; + readonly outputSockets: TOutputSockets; +}; + +export type ExtractValueType = ValueTypeNameMapping; + +export type SocketValueTypes = { + [K in keyof T]: ValueTypeNameMapping; +}; + +export type SocketSpec = { + name: string; + valueType: SocketValueType; +}; + +export type SocketNames = { + [K in keyof T]: T[K]['name']; +}; + +type ToSocket = { + [P in T['name']]: { + valueType: T['valueType']; + }; +}; + +export type ToObjectsArray = { + [I in keyof T]: ToSocket; +}; + +export type Known = Exclude; + +export type SocketsFromSpec = Known[number]>>; + +export function makeSocketsFromSpec(socketSpecs: TSockets) { + const sockets: any = {}; + + for (const { name, valueType } of socketSpecs) { + sockets[name] = { valueType } satisfies ISocketDefinition; + } + + return sockets as SocketsFromSpec; +} diff --git a/packages/core/src/nodes/schema/testUtils.ts b/packages/core/src/nodes/schema/testUtils.ts new file mode 100644 index 0000000..3b9eec6 --- /dev/null +++ b/packages/core/src/nodes/schema/testUtils.ts @@ -0,0 +1,86 @@ +import { IFlowNode, TriggeredParams } from './FlowNodes'; +import { FlowSocketNames, Sockets, ValueSockets, ValueTypeNameMapping } from './Sockets'; + +/** + * Assert parameter is of a specific type. + * + * @param value - Value that should be identical to type `T`. + */ +export function expectType(value: T): void {} + +type RecordedOutputWrite = + | { + writeType: 'flow'; + socketName: FlowSocketNames; + } + | { + writeType: 'value'; + socketName: keyof ValueSockets; + value: any; + }; + +type NodeInputValues = { + [K in keyof TSockets]?: ValueTypeNameMapping; +}; + +export type RecordedOutputWrites = RecordedOutputWrite[]; + +export const buildStubEngineForFlowNode = ( + flowNodeDefinition: IFlowNode +) => { + const outputWrites: RecordedOutputWrites = []; + + const getOutputWrites = () => outputWrites; + + let inputValuesState: NodeInputValues> = {}; + + const triggeredParams: Omit, 'state' | 'triggeringSocketName'> = { + commit: (param) => { + outputWrites.push({ + writeType: 'flow', + socketName: param, + }); + }, + readInput: (param) => { + // @ts-ignore + return inputValuesState[param]; + }, + writeOutput: (param, value) => { + outputWrites.push({ + writeType: 'value', + // @ts-ignore + socketName: param, + value, + }); + }, + }; + + let nodeState = flowNodeDefinition.initialState(); + + const trigger = (triggeringSocketName: FlowSocketNames) => { + // trigger node and update the state with the triggered result. + const result = flowNodeDefinition.triggered({ + ...triggeredParams, + state: nodeState, + triggeringSocketName, + }); + // if there is no node state, result will be undefined + // so then we know that we dont need to update the node state + if (typeof result !== 'undefined') nodeState = result; + }; + + const writeInput = , J extends keyof TValueSockets>( + param: J, + value: ValueTypeNameMapping + ) => { + // build fake write input fn that stores the write to an interval value store + // @ts-ignore + inputValuesState[param] = value; + }; + + return { + getOutputWrites, + trigger, + writeInput, + }; +}; diff --git a/packages/core/src/nodes/values/BooleanNodes.ts b/packages/core/src/nodes/values/BooleanNodes.ts new file mode 100644 index 0000000..d6ae5ff --- /dev/null +++ b/packages/core/src/nodes/values/BooleanNodes.ts @@ -0,0 +1,61 @@ +import { makeImmediateNodeDefinition } from '../schema/ImmediateNodes'; +import { Sockets, SocketSpec } from '../schema/Sockets'; +import { makeConstant, makeEqual } from './Shared'; + +const singleBoolean = { + a: { + valueType: 'boolean', + }, +} satisfies Sockets; +const doubleBoolean = { + ...singleBoolean, + b: { + valueType: 'boolean', + }, +} satisfies Sockets; + +const singleOutput = { + result: { + valueType: 'boolean', + }, +} satisfies Sockets; + +export const Constant = makeConstant('boolean'); + +export const And = makeImmediateNodeDefinition({ + inputSockets: doubleBoolean, + outputSockets: singleOutput, + exec: ({ readInput, writeOutput }) => { + writeOutput('result', readInput('a') && readInput('b')); + }, +}); + +export const Or = makeImmediateNodeDefinition({ + inputSockets: doubleBoolean, + outputSockets: singleOutput, + exec: ({ readInput, writeOutput }) => { + writeOutput('result', readInput('a') || readInput('b')); + }, +}); + +export const Not = makeImmediateNodeDefinition({ + inputSockets: singleBoolean, + outputSockets: singleOutput, + exec: ({ readInput, writeOutput }) => { + writeOutput('result', !readInput('a')); + }, +}); + +export const ToFloat = makeImmediateNodeDefinition({ + inputSockets: singleBoolean, + outputSockets: { + result: { + valueType: 'float', + }, + }, + exec: ({ readInput, writeOutput }) => { + writeOutput('result', readInput('a') ? 1 : 0); + }, +}); + +export const Equal = makeEqual('boolean'); diff --git a/packages/core/src/nodes/values/FloatNodes.ts b/packages/core/src/nodes/values/FloatNodes.ts new file mode 100644 index 0000000..628a25d --- /dev/null +++ b/packages/core/src/nodes/values/FloatNodes.ts @@ -0,0 +1,276 @@ +import { makeAdd, makeConstant, makeEqual, makeNegate, makeSub } from './Shared'; + +export const Constant = makeConstant('float'); +export const Equal = makeEqual('float'); +export const Add = makeAdd('float'); +export const Subtract = makeSub('float'); +export const Negate = makeNegate('float'); + +// export const Multiply = new NodeDescription( +// 'math/multiply/float', +// 'Logic', +// '×', +// (description, graph) => +// new In2Out1FuncNode(description, graph, ['float', 'float'], 'float', (a: number, b: number) => a * b) +// ); +// export const Divide = new NodeDescription( +// 'math/divide/float', +// 'Logic', +// '÷', +// (description, graph) => +// new In2Out1FuncNode(description, graph, ['float', 'float'], 'float', (a: number, b: number) => a / b) +// ); +// export const Modulus = new NodeDescription( +// 'math/modulus/float', +// 'Logic', +// 'MOD', +// (description, graph) => +// new In2Out1FuncNode(description, graph, ['float', 'float'], 'float', (a: number, b: number) => a % b) +// ); + +// export const Power = new NodeDescription( +// 'math/pow/float', +// 'Logic', +// 'POW', +// (description, graph) => new In2Out1FuncNode(description, graph, ['float', 'float'], 'float', Math.pow) +// ); +// export const SquareRoot = new NodeDescription( +// 'math/sqrt/float', +// 'Logic', +// '√', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.sqrt) +// ); + +// export const E = new NodeDescription( +// 'math/e/float', +// 'Logic', +// '𝑒', +// (description, graph) => new In0Out1FuncNode(description, graph, 'float', () => Math.E) +// ); +// export const Exp = new NodeDescription( +// 'math/exp/float', +// 'Logic', +// 'EXP', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.exp) +// ); +// export const Ln = new NodeDescription( +// 'math/ln/float', +// 'Logic', +// 'LN', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.log) +// ); +// export const Log2 = new NodeDescription( +// 'math/log2/float', +// 'Logic', +// 'LOG2', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.log2) +// ); +// export const Log10 = new NodeDescription( +// 'math/log10/float', +// 'Logic', +// 'LOG10', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.log10) +// ); + +// export const PI = new NodeDescription( +// 'math/pi/float', +// 'Logic', +// 'π', +// (description, graph) => new In0Out1FuncNode(description, graph, 'float', () => Math.PI) +// ); +// export const Sin = new NodeDescription( +// 'math/sin/float', +// 'Logic', +// 'SIN', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.sin) +// ); +// export const Asin = new NodeDescription( +// 'math/asin/float', +// 'Logic', +// 'ASIN', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.asin) +// ); +// export const Cos = new NodeDescription( +// 'math/cos/float', +// 'Logic', +// 'COS', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.cos) +// ); +// export const Acos = new NodeDescription( +// 'math/acos/float', +// 'Logic', +// 'ACOS', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.acos) +// ); +// export const Tan = new NodeDescription( +// 'math/tan/float', +// 'Logic', +// 'TAN', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.tan) +// ); +// export const Atan = new NodeDescription( +// 'math/atan/float', +// 'Logic', +// 'ATAN', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.atan) +// ); + +// export const Mix = new NodeDescription( +// 'math/mix/float', +// 'Logic', +// 'MIX', +// (description, graph) => +// new In3Out1FuncNode( +// description, +// graph, +// ['float', 'float', 'float'], +// 'float', +// (a: number, b: number, t: number) => { +// const s = 1 - t; +// return a * s + b * t; +// }, +// ['a', 'b', 't'] +// ) +// ); + +// export const ToFloat = new NodeDescription( +// 'math/toFloat/float', +// 'Logic', +// 'To Float', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', (a: number) => Number(a)) +// ); + +// export const Min = new NodeDescription( +// 'math/min/float', +// 'Logic', +// 'MIN', +// (description, graph) => +// new In2Out1FuncNode( +// description, +// graph, +// ['float', 'float'], +// 'float', +// (a: number, b: number) => Math.min(a, b) // TODO: can I jsut pass in Math.min? +// ) +// ); +// export const Max = new NodeDescription( +// 'math/max/float', +// 'Logic', +// 'MAX', +// (description, graph) => +// new In2Out1FuncNode( +// description, +// graph, +// ['float', 'float'], +// 'float', +// (a: number, b: number) => Math.max(a, b) // TODO: can I jsut pass in Math.max? +// ) +// ); +// export const Clamp = new NodeDescription( +// 'math/clamp/float', +// 'Logic', +// 'CLAMP', +// (description, graph) => +// new In3Out1FuncNode( +// description, +// graph, +// ['float', 'float', 'float'], +// 'float', +// (value: number, min: number, max: number) => (value < min ? min : value > max ? max : value), +// ['value', 'min', 'max'] +// ) +// ); + +// export const Abs = new NodeDescription( +// 'math/abs/float', +// 'Logic', +// 'ABS', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.abs) +// ); +// export const Sign = new NodeDescription( +// 'math/sign/float', +// 'Logic', +// 'SIGN', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.sign) +// ); + +// export const Floor = new NodeDescription( +// 'math/floor/float', +// 'Logic', +// 'FLOOR', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.floor) +// ); +// export const Ceil = new NodeDescription( +// 'math/ceil/float', +// 'Logic', +// 'CEIL', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.ceil) +// ); +// export const Round = new NodeDescription( +// 'math/round/float', +// 'Logic', +// 'ROUND', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.round) +// ); +// export const Trunc = new NodeDescription( +// 'math/trunc/float', +// 'Logic', +// 'TRUNC', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'float', Math.trunc) +// ); + +// export const Random = new NodeDescription( +// 'math/random/float', +// 'Logic', +// 'RANDOM', +// (description, graph) => new In0Out1FuncNode(description, graph, 'float', Math.random) +// ); + +// export const GreaterThan = new NodeDescription( +// 'math/greaterThan/float', +// 'Logic', +// '>', +// (description, graph) => +// new In2Out1FuncNode(description, graph, ['float', 'float'], 'boolean', (a: number, b: number) => a > b) +// ); +// export const GreaterThanOrEqual = new NodeDescription( +// 'math/greaterThanOrEqual/float', +// 'Logic', +// '≥', +// (description, graph) => +// new In2Out1FuncNode(description, graph, ['float', 'float'], 'boolean', (a: number, b: number) => a >= b) +// ); +// export const LessThan = new NodeDescription( +// 'math/lessThan/float', +// 'Logic', +// '<', +// (description, graph) => +// new In2Out1FuncNode(description, graph, ['float', 'float'], 'boolean', (a: number, b: number) => a < b) +// ); +// export const LessThanOrEqual = new NodeDescription( +// 'math/lessThanOrEqual/float', +// 'Logic', +// '≤', +// (description, graph) => +// new In2Out1FuncNode(description, graph, ['float', 'float'], 'boolean', (a: number, b: number) => a <= b) +// ); + +// export const IsNaN = new NodeDescription( +// 'math/isNaN/float', +// 'Logic', +// 'isNaN', +// (description, graph) => new In1Out1FuncNode(description, graph, ['float'], 'boolean', Number.isNaN) +// ); +// export const IsInf = new NodeDescription( +// 'math/isInf/float', +// 'Logic', +// 'isInf', +// (description, graph) => +// new In1Out1FuncNode( +// description, +// graph, +// ['float'], +// 'boolean', +// (a: number) => !Number.isFinite(a) && !Number.isNaN(a) +// ) +// ); diff --git a/packages/core/src/nodes/values/Shared.ts b/packages/core/src/nodes/values/Shared.ts new file mode 100644 index 0000000..be7df80 --- /dev/null +++ b/packages/core/src/nodes/values/Shared.ts @@ -0,0 +1,62 @@ +import { makeImmediateNodeDefinition } from '../schema/ImmediateNodes'; +import { Sockets, SocketValueType } from '../schema/Sockets'; + +export function makeConstant(valueType: TValueType) { + return makeImmediateNodeDefinition({ + inputSockets: { a: { valueType } } satisfies Sockets, + outputSockets: { result: { valueType } } satisfies Sockets, + exec: ({ readInput, writeOutput }) => { + writeOutput('result', readInput('a')); + }, + }); +} + +export function makeEqual(valueType: TValueType) { + return makeImmediateNodeDefinition({ + inputSockets: { a: { valueType }, b: { valueType } } satisfies Sockets, + outputSockets: { result: { valueType } } satisfies Sockets, + exec: ({ readInput, writeOutput }) => { + writeOutput('result', readInput('a') === readInput('b')); + }, + }); +} + +type NumberSocketValueTypes = Extract; + +export function makeAdd(valueType: TValueType) { + return makeImmediateNodeDefinition({ + inputSockets: { a: { valueType }, b: { valueType } } satisfies Sockets, + outputSockets: { result: { valueType } } satisfies Sockets, + exec: ({ readInput, writeOutput }) => { + writeOutput( + 'result', + // @ts-ignore + readInput('a') + readInput('b') + ); + }, + }); +} + +export function makeSub(valueType: TValueType) { + return makeImmediateNodeDefinition({ + inputSockets: { a: { valueType }, b: { valueType } } satisfies Sockets, + outputSockets: { result: { valueType } } satisfies Sockets, + exec: ({ readInput, writeOutput }) => { + writeOutput( + 'result', + // @ts-ignore + readInput('a') - readInput('b') + ); + }, + }); +} + +export function makeNegate(valueType: TValueType) { + return makeImmediateNodeDefinition({ + inputSockets: { a: { valueType } } satisfies Sockets, + outputSockets: { result: { valueType } } satisfies Sockets, + exec: ({ readInput, writeOutput }) => { + writeOutput('result', -readInput('a')); + }, + }); +} diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json new file mode 100644 index 0000000..59e9518 --- /dev/null +++ b/packages/core/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*"], + "compilerOptions": { + "target": "ES2020", + "lib": ["es2019", "dom"], + "module": "commonjs", + "moduleResolution": "node", + "esModuleInterop": true, + "jsx": "react", + "pretty": true, + "strict": true, + "skipLibCheck": true, + "declaration": true, + "removeComments": true, + "emitDeclarationOnly": true, + "resolveJsonModule": true, + "noImplicitThis": false, + "types": ["mocha"] + } +} diff --git a/test/package.json b/test/package.json index a48a177..79f2848 100644 --- a/test/package.json +++ b/test/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "ts-mocha src/**/*.test.ts" }, "author": "", "license": "ISC", diff --git a/yarn.lock b/yarn.lock index b3c0a96..87ed632 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,7 +22,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.5.5": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.5.5": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== @@ -1612,6 +1612,32 @@ dependencies: multiformats "^9.5.4" +"@jest/expect-utils@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.3.1.tgz#531f737039e9b9e27c42449798acb5bba01935b6" + integrity sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g== + dependencies: + jest-get-type "^29.2.0" + +"@jest/schemas@^29.0.0": + version "29.0.0" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" + integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== + dependencies: + "@sinclair/typebox" "^0.24.1" + +"@jest/types@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" + integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== + dependencies: + "@jest/schemas" "^29.0.0" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -2429,6 +2455,11 @@ "@sentry/types" "5.30.0" tslib "^1.9.3" +"@sinclair/typebox@^0.24.1": + version "0.24.51" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" + integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== + "@solana/buffer-layout@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz#75b1b11adc487234821c81dfae3119b73a5fd734" @@ -2798,6 +2829,13 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/expect@^24.3.0": + version "24.3.0" + resolved "https://registry.yarnpkg.com/@types/expect/-/expect-24.3.0.tgz#d7cab8b3c10c2d92a0cbb31981feceb81d3486f1" + integrity sha512-aq5Z+YFBz5o2b6Sp1jigx5nsmoZMK5Ceurjwy6PZmRv7dEi1jLtkARfvB1ME+OXJUG+7TZUDcv3WoCr/aor6dQ== + dependencies: + expect "*" + "@types/form-data@0.0.33": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" @@ -2818,6 +2856,25 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -2853,6 +2910,11 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== +"@types/mocha@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.0.tgz#3d9018c575f0e3f7386c1de80ee66cc21fbb7a52" + integrity sha512-rADY+HtTOA52l9VZWtgQfn4p+UDVM2eDVkMZT1I6syp0YKxW2F9v+0pbRZLsvskhQv/vMb6ZfCay81GHbz5SHg== + "@types/node@*", "@types/node@>=13.7.0": version "18.11.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" @@ -2969,6 +3031,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + "@types/three@^0.146.0": version "0.146.0" resolved "https://registry.yarnpkg.com/@types/three/-/three-0.146.0.tgz#83813ba0d2fff6bdc6d7fda3a77993a932bba45f" @@ -2993,6 +3060,18 @@ dependencies: "@types/node" "*" +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.8": + version "17.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.14.tgz#0943473052c24bd8cf2d1de25f1a710259327237" + integrity sha512-9Pj7abXoW1RSTcZaL2Hk6G2XyLMlp5ECdVC/Zf2p/KBjC3srijLGgRAXOBjtFrJoIrvxdTKyKDA14bEcbxBaWw== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/eslint-plugin@^4.26.1": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" @@ -3683,6 +3762,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + antlr4ts@^0.5.0-alpha.4: version "0.5.0-alpha.4" resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" @@ -3801,7 +3885,7 @@ array.prototype.reduce@^1.0.4: es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" -arrify@^1.0.1: +arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== @@ -4237,7 +4321,7 @@ buffer-fill@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== -buffer-from@^1.0.0, buffer-from@^1.1.1: +buffer-from@^1.0.0, buffer-from@^1.1.0, buffer-from@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -4383,6 +4467,19 @@ chai@^4.3.6: pathval "^1.1.1" type-detect "^4.0.5" +chai@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -4457,6 +4554,11 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +ci-info@^3.2.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.0.tgz#6d01b3696c59915b6ce057e4aa4adfc2fa25f5ef" + integrity sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -4927,6 +5029,13 @@ deep-eql@^4.0.1: dependencies: type-detect "^4.0.0" +deep-eql@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.2.tgz#270ceb902f87724077e6f6449aed81463f42fc1c" + integrity sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w== + dependencies: + type-detect "^4.0.0" + deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -5019,7 +5128,12 @@ didyoumean@^1.2.2: resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== -diff@3.5.0: +diff-sequences@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" + integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ== + +diff@3.5.0, diff@^3.1.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== @@ -5388,6 +5502,11 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" @@ -6055,6 +6174,17 @@ evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +expect@*: + version "29.3.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.3.1.tgz#92877aad3f7deefc2e3f6430dd195b92295554a6" + integrity sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA== + dependencies: + "@jest/expect-utils" "^29.3.1" + jest-get-type "^29.2.0" + jest-matcher-utils "^29.3.1" + jest-message-util "^29.3.1" + jest-util "^29.3.1" + extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -7513,6 +7643,58 @@ jayson@^3.4.4: uuid "^8.3.2" ws "^7.4.5" +jest-diff@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.3.1.tgz#d8215b72fed8f1e647aed2cae6c752a89e757527" + integrity sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.3.1" + jest-get-type "^29.2.0" + pretty-format "^29.3.1" + +jest-get-type@^29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" + integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== + +jest-matcher-utils@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz#6e7f53512f80e817dfa148672bd2d5d04914a572" + integrity sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ== + dependencies: + chalk "^4.0.0" + jest-diff "^29.3.1" + jest-get-type "^29.2.0" + pretty-format "^29.3.1" + +jest-message-util@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.3.1.tgz#37bc5c468dfe5120712053dd03faf0f053bd6adb" + integrity sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.3.1" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.3.1" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-util@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" + integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== + dependencies: + "@jest/types" "^29.3.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + jest-worker@^26.3.0: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -8152,7 +8334,7 @@ mkdirp@0.5.5: dependencies: minimist "^1.2.5" -mkdirp@0.5.x: +mkdirp@0.5.x, mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -8206,7 +8388,7 @@ mocha@7.1.2: yargs-parser "13.1.2" yargs-unparser "1.6.0" -mocha@^10.0.0: +mocha@^10.0.0, mocha@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.1.0.tgz#dbf1114b7c3f9d0ca5de3133906aea3dfc89ef7a" integrity sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg== @@ -8835,7 +9017,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -8961,11 +9143,25 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== -prettier@^2.3.1, prettier@^2.7.1: +prettier@^2.3.1: version "2.7.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== +prettier@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.0.tgz#c7df58393c9ba77d6fba3921ae01faf994fb9dc9" + integrity sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA== + +pretty-format@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.3.1.tgz#1841cac822b02b4da8971dacb03e8a871b4722da" + integrity sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg== + dependencies: + "@jest/schemas" "^29.0.0" + ansi-styles "^5.0.0" + react-is "^18.0.0" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -9143,6 +9339,11 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -9876,7 +10077,7 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-support@^0.5.13, source-map-support@^0.5.16, source-map-support@~0.5.20: +source-map-support@^0.5.13, source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -9957,6 +10158,13 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + stacktrace-parser@^0.1.10: version "0.1.10" resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" @@ -10441,6 +10649,29 @@ ts-essentials@^7.0.1: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== +ts-mocha@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" + integrity sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw== + dependencies: + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" + ts-node@>=8.0.0: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -10479,7 +10710,7 @@ ts-standard@^11.0.0: pkg-conf "^3.1.0" standard-engine "^14.0.1" -tsconfig-paths@^3.14.1: +tsconfig-paths@^3.14.1, tsconfig-paths@^3.5.0: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== @@ -10592,6 +10823,11 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.2.0.tgz#2c8b49e775d9e314a73ea6fcee0b2e8549d5f886" + integrity sha512-Il3wdLRzWvbAEtocgxGQA9YOoRVeVUGOMBtel5LdEpNeEAol6GJTLw8GbX6Z8EIMfvfhoOXs2bwOijtAZdK5og== + typechain@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" @@ -10620,11 +10856,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@>=4.5.0, typescript@^4.6.4: +typescript@^4.6.4: version "4.8.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== +typescript@^4.9.3: + version "4.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.3.tgz#3aea307c1746b8c384435d8ac36b8a2e580d85db" + integrity sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA== + typical@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" @@ -11210,6 +11451,11 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"