From fa8c02855bd3c4005c835e23e790a6f33727d581 Mon Sep 17 00:00:00 2001 From: Ni55aN Date: Tue, 11 Jul 2023 21:18:52 +0300 Subject: [PATCH] api docs --- .gitignore | 1 + .npmignore | 9 ---- package-lock.json | 108 +++++++++++++++++++++++++++++++++++++++-- package.json | 3 +- src/editor.ts | 69 ++++++++++++++++++++++++++ src/presets/classic.ts | 45 ++++++++++++++--- src/scope.ts | 19 ++++++++ src/types.ts | 26 +++++++++- src/utils.ts | 3 ++ 9 files changed, 261 insertions(+), 22 deletions(-) delete mode 100644 .npmignore diff --git a/.gitignore b/.gitignore index 9007215c..0f01d37a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ node_modules coverage npm-debug.log /dist +docs diff --git a/.npmignore b/.npmignore deleted file mode 100644 index e19cac05..00000000 --- a/.npmignore +++ /dev/null @@ -1,9 +0,0 @@ -node_modules -.idea/ -.vscode/ -.sonarlint -.scannerwork -coverage -.nyc_output -src -test \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index babd1ff3..8142edfe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ }, "devDependencies": { "jest-environment-jsdom": "^29.1.2", - "rete-cli": "^1.0.0-beta.29", + "rete-cli": "^1.0.0-beta.31", "typescript": "4.8.4" } }, @@ -3009,6 +3009,12 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", + "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", + "dev": true + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -5568,6 +5574,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -5665,6 +5677,12 @@ "yallist": "^3.0.2" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -5702,6 +5720,18 @@ "tmpl": "1.0.5" } }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -6394,9 +6424,9 @@ } }, "node_modules/rete-cli": { - "version": "1.0.0-beta.29", - "resolved": "https://registry.npmjs.org/rete-cli/-/rete-cli-1.0.0-beta.29.tgz", - "integrity": "sha512-5ZusghjvbnMDwNtju+EvLtmV5yQuGw0pGHgk7xQRIb/v91UlmKgpFNxHPjsow9cE7CO62pbznnwWn9m+i8vI7A==", + "version": "1.0.0-beta.31", + "resolved": "https://registry.npmjs.org/rete-cli/-/rete-cli-1.0.0-beta.31.tgz", + "integrity": "sha512-Y7Uzfx1fnJW16gTy/CP3IstPe9aLZPlEhjiSLnOnZiVsyYmGPr+KinqKghFkKl2RshajevMY1sXJQaC3Peh2zA==", "dev": true, "dependencies": { "@babel/plugin-transform-runtime": "^7.21.4", @@ -6422,6 +6452,7 @@ "rollup-plugin-terser": "7.0.2", "ts-jest": "29.0.3", "tslib": "2.4.0", + "typedoc": "^0.24.8", "typescript": "4.8.4" }, "bin": { @@ -6660,6 +6691,18 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", + "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -7069,6 +7112,51 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedoc": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", @@ -7194,6 +7282,18 @@ "node": ">=10.12.0" } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", diff --git a/package.json b/package.json index 1a556e41..f2b9a201 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "rete build -c rete.config.ts", "postinstall": "node postinstall.js", + "doc": "rete doc", "lint": "rete lint", "test": "rete test" }, @@ -27,7 +28,7 @@ }, "devDependencies": { "jest-environment-jsdom": "^29.1.2", - "rete-cli": "^1.0.0-beta.29", + "rete-cli": "^1.0.0-beta.31", "typescript": "4.8.4" }, "dependencies": { diff --git a/src/editor.ts b/src/editor.ts index ecec9dcc..da52a40c 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -1,6 +1,12 @@ import { Scope } from './scope' import { BaseSchemes } from './types' +/** + * Signal types produced by NodeEditor instance + * @typeParam Scheme - The scheme type + * @priority 10 + * @group Primary + */ export type Root = | { type: 'nodecreate', data: Scheme['Node'] } | { type: 'nodecreated', data: Scheme['Node'] } @@ -14,6 +20,12 @@ export type Root = | { type: 'clearcancelled' } | { type: 'cleared' } +/** + * The NodeEditor class is the entry class. It is used to create and manage nodes and connections. + * @typeParam Scheme - The scheme type + * @priority 7 + * @group Primary + */ export class NodeEditor extends Scope> { private nodes: Scheme['Node'][] = [] private connections: Scheme['Connection'][] = [] @@ -22,22 +34,48 @@ export class NodeEditor extends Scope> super('NodeEditor') } + /** + * Get a node by id + * @param id - The node id + * @returns The node or undefined + */ public getNode(id: Scheme['Node']['id']) { return this.nodes.find(node => node.id === id) } + /** + * Get all nodes + * @returns All nodes + */ public getNodes() { return this.nodes } + /** + * Get all connections + * @returns All connections + */ public getConnections() { return this.connections } + /** + * Get a connection by id + * @param id - The connection id + * @returns The connection or undefined + */ public getConnection(id: Scheme['Connection']['id']) { return this.connections.find(connection => connection.id === id) } + /** + * Add a node + * @param data - The node data + * @returns Whether the node was added + * @throws If the node has already been added + * @emits nodecreate + * @emits nodecreated + */ async addNode(data: Scheme['Node']) { if (this.getNode(data.id)) throw new Error('node has already been added') @@ -49,6 +87,14 @@ export class NodeEditor extends Scope> return true } + /** + * Add a connection + * @param data - The connection data + * @returns Whether the connection was added + * @throws If the connection has already been added + * @emits connectioncreate + * @emits connectioncreated + */ async addConnection(data: Scheme['Connection']) { if (this.getConnection(data.id)) throw new Error('connection has already been added') @@ -60,6 +106,14 @@ export class NodeEditor extends Scope> return true } + /** + * Remove a node + * @param id - The node id + * @returns Whether the node was removed + * @throws If the node cannot be found + * @emits noderemove + * @emits noderemoved + */ async removeNode(id: Scheme['Node']['id']) { const index = this.nodes.findIndex(n => n.id === id) const node = this.nodes[index] @@ -74,6 +128,14 @@ export class NodeEditor extends Scope> return true } + /** + * Remove a connection + * @param id - The connection id + * @returns Whether the connection was removed + * @throws If the connection cannot be found + * @emits connectionremove + * @emits connectionremoved + */ async removeConnection(id: Scheme['Connection']['id']) { const index = this.connections.findIndex(n => n.id === id) const connection = this.connections[index] @@ -88,6 +150,13 @@ export class NodeEditor extends Scope> return true } + /** + * Clear all nodes and connections + * @returns Whether the editor was cleared + * @emits clear + * @emits clearcancelled + * @emits cleared + */ async clear() { if (!await this.emit({ type: 'clear' })) { await this.emit({ type: 'clearcancelled' }) diff --git a/src/presets/classic.ts b/src/presets/classic.ts index 3dd97c80..d970a415 100644 --- a/src/presets/classic.ts +++ b/src/presets/classic.ts @@ -1,14 +1,26 @@ +/** + * Contains classes for classic scheme such as Node, Input, Output, Control, Socket, Connection + * @module + * @group Primary + */ + import { ConnectionBase, NodeBase } from '../types' import { getUID } from '../utils' type PortId = string +/** + * The socket class + */ export class Socket { constructor(public name: string) { } } +/** + * General port class + */ export class Port { id: PortId index?: number @@ -18,6 +30,9 @@ export class Port { } } +/** + * The input port class + */ export class Input extends Port { control: Control | null = null showControl = true @@ -32,12 +47,18 @@ export class Input extends Port { } } +/** + * The output port class + */ export class Output extends Port { constructor(socket: S, label?: string, multipleConnections?: boolean) { super(socket, label, multipleConnections !== false) } } +/** + * General control class + */ export class Control { id: string index?: number @@ -48,11 +69,14 @@ export class Control { } type InputControlOptions = { - readonly?: boolean, - initial?: N, - change?: (value: N) => void - } - + readonly?: boolean, + initial?: N, + change?: (value: N) => void +} +/** + * The input control class + * @example new InputControl('text', { readonly: true, initial: 'hello' }) + */ export class InputControl extends Control { value?: N readonly: boolean @@ -71,14 +95,21 @@ export class InputControl implements NodeBase { id: NodeBase['id'] - inputs: {[key in keyof Inputs]?: Input>} = {} - outputs: {[key in keyof Outputs]?: Output>} = {} + inputs: { [key in keyof Inputs]?: Input> } = {} + outputs: { [key in keyof Outputs]?: Output> } = {} controls: Controls = {} as Controls selected?: boolean diff --git a/src/scope.ts b/src/scope.ts index a5203e26..17602bc1 100644 --- a/src/scope.ts +++ b/src/scope.ts @@ -3,6 +3,15 @@ import { AcceptPartialUnion, CanAssignSignal, GetAssignmentReferences, GetNonAssignableElements, Tail } from './utility-types' +/** + * A middleware type that can modify the data + * @typeParam T - The data type + * @param data - The data to be modified + * @returns The modified data or undefined + * @example (data) => data + 1 + * @example (data) => undefined // will stop the execution + * @internal + */ export type Pipe = (data: T) => Promise | undefined | T export type CanAssignEach = D extends [infer H1, ...infer Tail1] @@ -19,6 +28,7 @@ export type ScopeAsParameter, Current extends any[]> /** * Validate the Scope signals and replace the parameter type with an error message if they are not assignable + * @internal */ export type NestedScope, Current extends any[]> = (CanAssignEach[number] extends true ? S @@ -28,6 +38,7 @@ export type NestedScope, Current extends any[]> = (C /** * Provides 'debug' method to check the detailed assignment error message * @example .debug($ => $) + * @internal */ export function useHelper, Signals>() { type T1 = S['__scope']['parents'][number] @@ -38,6 +49,11 @@ export function useHelper, Signals>() { } } +/** + * A signal is a middleware chain that can be used to modify the data + * @typeParam T - The data type + * @internal + */ export class Signal { pipes: Pipe[] = [] @@ -61,6 +77,9 @@ type Type = { new(...args: any[]): T; } | (abstract new (...args: any[]) => T) +/** + * Base class for all plugins and the core. Provides a signals mechanism to modify the data + */ export class Scope { signal = new Signal>() parent?: any // Parents['length'] extends 0 ? undefined : Scope> diff --git a/src/types.ts b/src/types.ts index 86e96c42..d65a0915 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,9 +1,33 @@ - +/** + * Node id type + */ export type NodeId = string +/** + * Connection id type + * @group Primary + */ export type ConnectionId = string +/** + * The base node type + * @group Primary + */ export type NodeBase = { id: NodeId } +/** + * The base connection type + * @group Primary + */ export type ConnectionBase = { id: ConnectionId, source: NodeId, target: NodeId } +/** + * Get the schemes + * @example GetSchemes + * @group Primary + */ export type GetSchemes = { Node: NodeData, Connection: ConnectionData } + +/** + * The base schemes + * @group Primary + */ export type BaseSchemes = GetSchemes diff --git a/src/utils.ts b/src/utils.ts index 8eeb92b6..9d26b6ab 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,6 +4,9 @@ const nodeCrypto = () => import('node:crypto') const crypto = globalThis.crypto as (typeof globalThis.crypto | Awaited>) +/** + * @returns A unique id + */ export function getUID(): string { if ('randomBytes' in crypto) { return crypto.randomBytes(8).toString('hex')