From 41d4d0db8b0b71955886ac535df4d5bf1df1efbe Mon Sep 17 00:00:00 2001 From: Samuel MT Date: Wed, 24 Jul 2024 10:10:00 -0300 Subject: [PATCH 1/3] `from char code` to input number[] char sequence --- src/system/f/string/FromCharCode/index.ts | 5 +++-- src/system/f/string/FromCharCode/spec.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/system/f/string/FromCharCode/index.ts b/src/system/f/string/FromCharCode/index.ts index bcc0920715..00d76fb4ff 100644 --- a/src/system/f/string/FromCharCode/index.ts +++ b/src/system/f/string/FromCharCode/index.ts @@ -4,7 +4,7 @@ import { System } from '../../../../system' import { ID_FROM_CHAR_CODE } from '../../../_ids' export interface I { - code: number + code: number[] } export interface O { @@ -25,7 +25,8 @@ export default class FromCharCode extends Functional, O> { } f({ code }: I, done: Done>): void { - const char = String.fromCharCode(code) + const char = String.fromCharCode(...code) + done({ char }) } } diff --git a/src/system/f/string/FromCharCode/spec.json b/src/system/f/string/FromCharCode/spec.json index 30d8ec2276..03b86d8dd3 100644 --- a/src/system/f/string/FromCharCode/spec.json +++ b/src/system/f/string/FromCharCode/spec.json @@ -2,7 +2,7 @@ "name": "from char code", "inputs": { "code": { - "type": "number" + "type": "number[]" } }, "outputs": { From 36301228282229dd8facefc429f1ab545c0ece04 Mon Sep 17 00:00:00 2001 From: Samuel MT Date: Wed, 24 Jul 2024 10:11:54 -0300 Subject: [PATCH 2/3] fix `deep destroy` to stop on undefined key --- src/util/object.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/util/object.ts b/src/util/object.ts index 46bbf5bd57..c4a98974cc 100644 --- a/src/util/object.ts +++ b/src/util/object.ts @@ -270,10 +270,12 @@ export function deepDestroy(obj: object, path: Key[]): void { const o = obj[p] - deepDestroy(o, rest) + if (o) { + deepDestroy(o, rest) - if (isEmptyObject(o)) { - delete obj[p] + if (isEmptyObject(o)) { + delete obj[p] + } } } From 0a5461a5d8e7bfb57f2e0c52d5860e184d51c140 Mon Sep 17 00:00:00 2001 From: Samuel MT Date: Wed, 24 Jul 2024 22:35:17 -0300 Subject: [PATCH 3/3] crypto --- src/API.ts | 47 ++++- src/Class/Graph/index.ts | 8 +- src/client/icons/index.ts | 6 + src/client/method.ts | 36 ++++ src/client/platform/web/api/crypto.ts | 102 ++++++++++ src/client/platform/web/api/text.ts | 4 + src/client/platform/web/boot.ts | 3 + src/host/none.ts | 60 ++++++ src/interface.ts | 12 ++ src/system/f/meta/Scope/index.ts | 2 +- src/system/platform/State/index.ts | 7 +- .../platform/api/array/typed/Buffer/index.ts | 48 +++++ .../platform/api/array/typed/Buffer/spec.json | 33 ++++ .../api/array/typed/Uint8Array/index.ts | 58 ++++++ .../api/array/typed/Uint8Array/spec.json | 31 +++ .../api/array/typed/Uint8Array0/index.ts | 58 ++++++ .../api/array/typed/Uint8Array0/spec.json | 31 +++ .../api/array/typed/Uint8Array1/index.ts | 65 +++++++ .../api/array/typed/Uint8Array1/spec.json | 29 +++ .../array}/typed/Uint8ClampedArray/index.ts | 14 +- .../array}/typed/Uint8ClampedArray/spec.json | 9 +- .../array}/typed/Uint8ClampedArray0/index.ts | 14 +- .../array}/typed/Uint8ClampedArray0/spec.json | 9 +- .../{ => api/array}/typed/method/Set/index.ts | 16 +- .../array}/typed/method/Set/spec.json | 0 .../platform/api/crypto/Decrypt/index.ts | 83 ++++++++ .../platform/api/crypto/Decrypt/spec.json | 42 ++++ .../platform/api/crypto/Encrypt/index.ts | 84 ++++++++ .../platform/api/crypto/Encrypt/spec.json | 42 ++++ .../platform/api/crypto/ExportJwtKey/index.ts | 57 ++++++ .../api/crypto/ExportJwtKey/spec.json | 29 +++ .../platform/api/crypto/ExportKey/index.ts | 62 ++++++ .../platform/api/crypto/ExportKey/spec.json | 30 +++ .../platform/api/crypto/GenerateKey/index.ts | 80 ++++++++ .../platform/api/crypto/GenerateKey/spec.json | 39 ++++ .../api/crypto/GenerateKeyPair/index.ts | 92 +++++++++ .../api/crypto/GenerateKeyPair/spec.json | 44 +++++ .../platform/api/crypto/ImportJwtKey/index.ts | 69 +++++++ .../api/crypto/ImportJwtKey/spec.json | 42 ++++ .../platform/api/crypto/ImportKey/index.ts | 75 +++++++ .../platform/api/crypto/ImportKey/spec.json | 50 +++++ .../platform/api/crypto/RsaAlgorithm/index.ts | 60 ++++++ .../api/crypto/RsaAlgorithm/spec.json | 38 ++++ src/system/platform/api/crypto/Sign/index.ts | 76 ++++++++ src/system/platform/api/crypto/Sign/spec.json | 42 ++++ .../platform/api/crypto/Verify/index.ts | 73 +++++++ .../platform/api/crypto/Verify/spec.json | 40 ++++ .../platform/api/network/Socket/index.ts | 4 +- .../platform/api/peer/PeerReceiver/index.ts | 85 +++----- .../api/peer/PeerTransmitter/index.ts | 19 +- .../platform/api/system/user/Decrypt/index.ts | 30 --- .../api/system/user/Decrypt/spec.json | 24 --- .../api/system/user/PublicKey/index.ts | 30 --- .../api/system/user/PublicKey/spec.json | 24 --- .../platform/api/system/user/Sign/index.ts | 30 --- .../platform/api/system/user/Sign/spec.json | 24 --- .../platform/api/text/TextDecoder/index.ts | 62 ++++++ .../platform/api/text/TextDecoder/spec.json | 31 +++ .../platform/api/text/TextEncoder/index.ts | 59 ++++++ .../platform/api/text/TextEncoder/spec.json | 31 +++ .../platform/api/text/method/Decode/index.ts | 56 ++++++ .../platform/api/text/method/Decode/spec.json | 32 +++ .../platform/api/text/method/Encode/index.ts | 62 ++++++ .../platform/api/text/method/Encode/spec.json | 35 ++++ .../platform/api/text/method/Encode0/index.ts | 66 +++++++ .../api/text/method/Encode0/spec.json | 36 ++++ .../component/app/Editor/Component.ts | 184 ++++++++++-------- .../platform/method/object/Set/index.ts | 4 +- .../platform/method/object/Set0/index.ts | 4 +- src/types/interface/AB.ts | 3 + src/types/interface/CK.ts | 1 + src/types/interface/TA.ts | 5 +- src/types/interface/TD.ts | 3 + src/types/interface/TE.ts | 3 + src/types/interface/async/$AB.ts | 15 ++ src/types/interface/async/$CK.ts | 11 ++ src/types/interface/async/$TD.ts | 15 ++ src/types/interface/async/$TE.ts | 18 ++ src/wrap/Array.ts | 25 ++- src/wrap/ArrayBuffer.ts | 22 +++ src/wrap/CryptoKey.ts | 18 ++ src/wrap/Object.ts | 76 +++++--- src/wrap/Socket.ts | 1 + src/wrap/TextDecoder.ts | 15 ++ src/wrap/TextEncoder.ts | 15 ++ 85 files changed, 2739 insertions(+), 390 deletions(-) create mode 100644 src/client/platform/web/api/crypto.ts create mode 100644 src/system/platform/api/array/typed/Buffer/index.ts create mode 100644 src/system/platform/api/array/typed/Buffer/spec.json create mode 100644 src/system/platform/api/array/typed/Uint8Array/index.ts create mode 100644 src/system/platform/api/array/typed/Uint8Array/spec.json create mode 100644 src/system/platform/api/array/typed/Uint8Array0/index.ts create mode 100644 src/system/platform/api/array/typed/Uint8Array0/spec.json create mode 100644 src/system/platform/api/array/typed/Uint8Array1/index.ts create mode 100644 src/system/platform/api/array/typed/Uint8Array1/spec.json rename src/system/platform/{ => api/array}/typed/Uint8ClampedArray/index.ts (60%) rename src/system/platform/{ => api/array}/typed/Uint8ClampedArray/spec.json (77%) rename src/system/platform/{ => api/array}/typed/Uint8ClampedArray0/index.ts (60%) rename src/system/platform/{ => api/array}/typed/Uint8ClampedArray0/spec.json (77%) rename src/system/platform/{ => api/array}/typed/method/Set/index.ts (55%) rename src/system/platform/{ => api/array}/typed/method/Set/spec.json (100%) create mode 100644 src/system/platform/api/crypto/Decrypt/index.ts create mode 100644 src/system/platform/api/crypto/Decrypt/spec.json create mode 100644 src/system/platform/api/crypto/Encrypt/index.ts create mode 100644 src/system/platform/api/crypto/Encrypt/spec.json create mode 100644 src/system/platform/api/crypto/ExportJwtKey/index.ts create mode 100644 src/system/platform/api/crypto/ExportJwtKey/spec.json create mode 100644 src/system/platform/api/crypto/ExportKey/index.ts create mode 100644 src/system/platform/api/crypto/ExportKey/spec.json create mode 100644 src/system/platform/api/crypto/GenerateKey/index.ts create mode 100644 src/system/platform/api/crypto/GenerateKey/spec.json create mode 100644 src/system/platform/api/crypto/GenerateKeyPair/index.ts create mode 100644 src/system/platform/api/crypto/GenerateKeyPair/spec.json create mode 100644 src/system/platform/api/crypto/ImportJwtKey/index.ts create mode 100644 src/system/platform/api/crypto/ImportJwtKey/spec.json create mode 100644 src/system/platform/api/crypto/ImportKey/index.ts create mode 100644 src/system/platform/api/crypto/ImportKey/spec.json create mode 100644 src/system/platform/api/crypto/RsaAlgorithm/index.ts create mode 100644 src/system/platform/api/crypto/RsaAlgorithm/spec.json create mode 100644 src/system/platform/api/crypto/Sign/index.ts create mode 100644 src/system/platform/api/crypto/Sign/spec.json create mode 100644 src/system/platform/api/crypto/Verify/index.ts create mode 100644 src/system/platform/api/crypto/Verify/spec.json delete mode 100644 src/system/platform/api/system/user/Decrypt/index.ts delete mode 100644 src/system/platform/api/system/user/Decrypt/spec.json delete mode 100644 src/system/platform/api/system/user/PublicKey/index.ts delete mode 100644 src/system/platform/api/system/user/PublicKey/spec.json delete mode 100644 src/system/platform/api/system/user/Sign/index.ts delete mode 100644 src/system/platform/api/system/user/Sign/spec.json create mode 100644 src/system/platform/api/text/TextDecoder/index.ts create mode 100644 src/system/platform/api/text/TextDecoder/spec.json create mode 100644 src/system/platform/api/text/TextEncoder/index.ts create mode 100644 src/system/platform/api/text/TextEncoder/spec.json create mode 100644 src/system/platform/api/text/method/Decode/index.ts create mode 100644 src/system/platform/api/text/method/Decode/spec.json create mode 100644 src/system/platform/api/text/method/Encode/index.ts create mode 100644 src/system/platform/api/text/method/Encode/spec.json create mode 100644 src/system/platform/api/text/method/Encode0/index.ts create mode 100644 src/system/platform/api/text/method/Encode0/spec.json create mode 100644 src/types/interface/AB.ts create mode 100644 src/types/interface/CK.ts create mode 100644 src/types/interface/TD.ts create mode 100644 src/types/interface/TE.ts create mode 100644 src/types/interface/async/$AB.ts create mode 100644 src/types/interface/async/$CK.ts create mode 100644 src/types/interface/async/$TD.ts create mode 100644 src/types/interface/async/$TE.ts create mode 100644 src/wrap/ArrayBuffer.ts create mode 100644 src/wrap/CryptoKey.ts create mode 100644 src/wrap/TextDecoder.ts create mode 100644 src/wrap/TextEncoder.ts diff --git a/src/API.ts b/src/API.ts index 9d322b6ddf..3c059f2910 100644 --- a/src/API.ts +++ b/src/API.ts @@ -68,6 +68,50 @@ export type API = { EventSource: typeof EventSource } channel: { local: (opt: ChannelOpt) => Channel } + crypto: { + generateKey: ( + algorithm: AlgorithmIdentifier, + extractable: boolean, + keyUsages: string[] + ) => Promise + exportKey: ( + format: T, + key: CryptoKey + ) => Promise + encrypt: ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: BufferSource + ) => Promise + decrypt: ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: BufferSource + ) => Promise + sign: ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: ArrayBuffer + ) => Promise + verify: ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + signature: BufferSource, + data: BufferSource + ) => Promise + importKey( + format: T, + keyData: T extends 'jwk' ? JsonWebKey : BufferSource, + algorithm: + | AlgorithmIdentifier + | RsaHashedImportParams + | EcKeyImportParams + | HmacImportParams + | AesKeyAlgorithm, + extractable: boolean, + keyUsages: ReadonlyArray + ): Promise + } alert: { alert: (message: string) => void prompt: (message: string, defaultValue: string) => string @@ -212,7 +256,6 @@ export type API = { createRange(): Range exitPictureInPicture(): Promise pictureInPictureElement: Element - MutationObserver: { new (callback: MutationCallback): MutationObserver } PositionObserver: PositionObserverCostructor ResizeObserver: { new (callback: ResizeObserverCallback): ResizeObserver } @@ -228,6 +271,8 @@ export type API = { parse: (str: string) => Dict } text: { + TextEncoder: typeof TextEncoder + TextDecoder: typeof TextDecoder measureText: MeasureTextFunction } worker: { diff --git a/src/Class/Graph/index.ts b/src/Class/Graph/index.ts index 9f54988078..db5adfc710 100644 --- a/src/Class/Graph/index.ts +++ b/src/Class/Graph/index.ts @@ -46,6 +46,7 @@ import { } from '../../spec/actions/G' import { cloneUnit, cloneUnitClass } from '../../spec/cloneUnit' import { evaluate } from '../../spec/evaluate' +import { evaluateDataValue } from '../../spec/evaluateDataValue' import { bundleFromId } from '../../spec/fromId' import { applyUnitDefaultIgnored } from '../../spec/fromSpec' import { renameUnitInMerges } from '../../spec/reducers/spec' @@ -5315,7 +5316,12 @@ export class Graph = any, O extends Dict = any> } setUnitPinData( - { unitId, type, pinId, data: stringify(data) }, + { + unitId, + type, + pinId, + data: evaluateDataValue(stringify(data), specs, classes), + }, this._spec, specs, classes diff --git a/src/client/icons/index.ts b/src/client/icons/index.ts index 5535f24f92..f04d33eb24 100644 --- a/src/client/icons/index.ts +++ b/src/client/icons/index.ts @@ -42,6 +42,8 @@ export default JSON.parse(`{ "arrow-up-left": "M17 17 L7 7 M7 17 L7 7 L17 7", "arrow-up-right": "M7 17 L17 7 M7 7 L17 7 L17 17", "arrow-up": "M12 19 L12 5 M5 12 L12 5 L19 12", + "arrow-down-up": "m 3 16 4 4 4-4 M 7 20 V 4 m 14 4 -4 -4 -4 4 M 17 4 v16", + "arrow-up-down": "m 11 16 -4 4 -4 -4 M 17 20 V 4 m -4 4 4-4 4 4 M 7 4 v 16", "asterisk": "M12 6v12 M17.196 9L6.804 15 M6.804 9l10.392 6", "at-sign": "M16 12 A4 4 0 0 1 12 16 A4 4 0 0 1 8 12 A4 4 0 0 1 16 12 z M16 8v5a3 3 0 006 0v-1a10 10 0 10-3.92 7.94", "atom-alt": "M 4 12 A 9 6 45 0 1 20 12 A 9 6 45 0 1 4 12 M 4 12 A 9 6 -45 0 1 20 12 A 9 6 -45 0 1 4 12 M13 12 A1 1 0 0 1 12 13 A1 1 0 0 1 11 12 A1 1 0 0 1 13 12 z M12 12 L12.001 12", @@ -209,6 +211,7 @@ export default JSON.parse(`{ "file-x-2": "M4 22h14a2 2 0 002-2V7.5L14.5 2H6a2 2 0 00-2 2v4 M14 2v6h6 M3 12.5l5 5 M8 12.5l-5 5", "file-x": "M14.5 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V7.5L14.5 2z M14 2 L14 8 L20 8 M9.5 12.5 L14.5 17.5 M14.5 12.5 L9.5 17.5", "file": "M14.5 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V7.5L14.5 2z M14 2 L14 8 L20 8", + "file-lock": "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z M 8 12 h 8 v 6 h -8 z M10 12v-2a2 2 0 1 1 4 0v2", "files": "M15.5 2H8.6c-.4 0-.8.2-1.1.5-.3.3-.5.7-.5 1.1v12.8c0 .4.2.8.5 1.1.3.3.7.5 1.1.5h9.8c.4 0 .8-.2 1.1-.5.3-.3.5-.7.5-1.1V6.5L15.5 2z M3 7.6v12.8c0 .4.2.8.5 1.1.3.3.7.5 1.1.5h9.8 M15 2v5h5", "film": "M4.18 2 H19.82 A2.18 2.18 0 0 1 22 4.18 V19.82 A2.18 2.18 0 0 1 19.82 22 H4.18 A2.18 2.18 0 0 1 2 19.82 V4.18 A2.18 2.18 0 0 1 4.18 2 z M7 2 L7 22 M17 2 L17 22 M2 12 L22 12 M2 7 L7 7 M2 17 L7 17 M17 17 L22 17 M17 7 L22 7", "filter": "M22 3 L2 3 L10 12.46 L10 19 L14 21 L14 12.46 L22 3 Z", @@ -278,6 +281,8 @@ export default JSON.parse(`{ "italic": "M19 4 L10 4 M14 20 L5 20 M15 4 L9 20", "jersey-pound": "M12 9.5V21m0-11.5L6 3m6 6.5L18 3 M6 15h12 M6 11h12", "key": "M21 2l-2 2m-7.61 7.61a5.5 5.5 0 11-7.778 7.778 5.5 5.5 0 017.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4", + "key-round": "M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z M 16 7.5 A 0.5 0.5 1 1 0 16 7.49zz", + "key-square": "M12.4 2.7c.9-.9 2.5-.9 3.4 0l5.5 5.5c.9.9.9 2.5 0 3.4l-3.7 3.7c-.9.9-2.5.9-3.4 0L8.7 9.8c-.9-.9-.9-2.5 0-3.4Z M 0 0 m14 7 3 3 M9.4 10.6 2 18v3c0 .6.4 1 1 1h4v-3h3v-3h2l1.4-1.4 ", "keyboard": "M4 4 H20 A2 2 0 0 1 22 6 V18 A2 2 0 0 1 20 20 H4 A2 2 0 0 1 2 18 V6 A2 2 0 0 1 4 4 z M6 8 L6.01 8 M10 8 L10.01 8 M14 8 L14.01 8 M18 8 L18.01 8 M8 12 L8.01 12 M12 12 L12.01 12 M16 12 L16.01 12 M10 16 L14 16 M6 16 L6.01 16 M18 16 L18.01 16", "languages": "M5 8l6 6 M4 14l6-6 2-3 M2 5h12 M7 2h1 M22 22l-5-10-5 10 M14 18h6", "laptop-2": "M5 4 H19 A2 2 0 0 1 21 6 V14 A2 2 0 0 1 19 16 H5 A2 2 0 0 1 3 14 V6 A2 2 0 0 1 5 4 z M2 20 L22 20", @@ -463,6 +468,7 @@ export default JSON.parse(`{ "square": "M5 3 H19 A2 2 0 0 1 21 5 V19 A2 2 0 0 1 19 21 H5 A2 2 0 0 1 3 19 V5 A2 2 0 0 1 5 3 z", "square-play": "M4 4 h 18 v 18 h -18 z M 1 1 m9 8 6 4-6 4Z", "square-activity": "M4 4 h 18 v 18 h -18 Z M 18 13 h -2 l -2 5 -2 -10 -2 5 H 7", + "square-function": "M 3 3 h 18 v 18 h -18 z M9 17c2 0 2.8-1 2.8-2.8V10c0-2 1-3.3 3.2-3 M9 11.2h5.7", "star-half": "M12 17.8L5.8 21 7 14.1 2 9.3l7-1L12 2", "star": "M12 2 L15.09 8.26 L22 9.27 L17 14.14 L18.18 21.02 L12 17.77 L5.82 21.02 L7 14.14 L2 9.27 L8.91 8.26 L12 2 Z", "stop-circle": "M22 12 A10 10 0 0 1 12 22 A10 10 0 0 1 2 12 A10 10 0 0 1 22 12 z M9 9 H15 V15 H9 V9 z", diff --git a/src/client/method.ts b/src/client/method.ts index 6af51fb629..dfc2e5218c 100644 --- a/src/client/method.ts +++ b/src/client/method.ts @@ -5,6 +5,11 @@ import { A_METHOD_REF, A_METHOD_WATCH, } from '../types/interface/async/$A' +import { + AB_METHOD_CALL, + AB_METHOD_REF, + AB_METHOD_WATCH, +} from '../types/interface/async/$AB' import { AC_METHOD_CALL, AC_METHOD_REF, @@ -50,6 +55,11 @@ import { CH_METHOD_REF, CH_METHOD_WATCH, } from '../types/interface/async/$CH' +import { + CK_METHOD_CALL, + CK_METHOD_REF, + CK_METHOD_WATCH, +} from '../types/interface/async/$CK' import { CS_METHOD_CALL, CS_METHOD_REF, @@ -110,6 +120,12 @@ import { S_METHOD_REF, S_METHOD_WATCH, } from '../types/interface/async/$S' +import { TD_METHOD_CALL, TD_METHOD_WATCH } from '../types/interface/async/$TD' +import { + TE_METHOD_CALL, + TE_METHOD_REF, + TE_METHOD_WATCH, +} from '../types/interface/async/$TE' import { U_METHOD_CALL, U_METHOD_REF, @@ -245,4 +261,24 @@ export const METHOD: AllKeys< watch: D_METHOD_WATCH, ref: D_METHOD_REF, }, + CK: { + call: CK_METHOD_CALL, + watch: CK_METHOD_WATCH, + ref: CK_METHOD_REF, + }, + AB: { + call: AB_METHOD_CALL, + watch: AB_METHOD_REF, + ref: AB_METHOD_WATCH, + }, + TE: { + call: TE_METHOD_CALL, + watch: TE_METHOD_WATCH, + ref: TE_METHOD_REF, + }, + TD: { + call: TD_METHOD_CALL, + watch: TD_METHOD_WATCH, + ref: TE_METHOD_REF, + }, } diff --git a/src/client/platform/web/api/crypto.ts b/src/client/platform/web/api/crypto.ts new file mode 100644 index 0000000000..e364a1f0fe --- /dev/null +++ b/src/client/platform/web/api/crypto.ts @@ -0,0 +1,102 @@ +import { API } from '../../../../API' +import { APINotSupportedError } from '../../../../exception/APINotImplementedError' +import { BootOpt } from '../../../../system' + +export function webCrypto(window: Window, opt: BootOpt): API['crypto'] { + const crypto: API['crypto'] = { + generateKey: function ( + algorithm: AlgorithmIdentifier, + extractable: boolean, + keyUsages: KeyUsage[] + ): Promise { + if (window.crypto) { + return window.crypto.subtle.generateKey( + algorithm, + extractable, + keyUsages + ) + } + + throw new APINotSupportedError('Crypto') + }, + exportKey: function ( + format: KeyFormat, + key: CryptoKey + ): Promise { + if (window.crypto) { + return window.crypto.subtle.exportKey(format, key) + } + + throw new APINotSupportedError('Crypto') + }, + importKey: function < + F extends KeyFormat, + K extends F extends 'jwk' ? JsonWebKey : BufferSource, + >( + format: F, + key: K, + algorithm: AlgorithmIdentifier, + extractable: boolean, + keyUsages: KeyUsage[] + ): Promise { + if (window.crypto) { + return window.crypto.subtle.importKey( + format as any, + key as any, + algorithm, + extractable, + keyUsages + ) + } + + throw new APINotSupportedError('Crypto') + }, + encrypt: function ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: BufferSource + ): Promise { + if (window.crypto) { + return window.crypto.subtle.encrypt(algorithm, key, data) + } + + throw new APINotSupportedError('Crypto') + }, + decrypt: function ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: BufferSource + ): Promise { + if (window.crypto) { + return window.crypto.subtle.decrypt(algorithm, key, data) + } + + throw new APINotSupportedError('Crypto') + }, + sign: function ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: ArrayBuffer + ): Promise { + if (window.crypto) { + return window.crypto.subtle.sign(algorithm, key, data) + } + + throw new APINotSupportedError('Crypto') + }, + verify: function ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + signature: BufferSource, + data: BufferSource + ): Promise { + if (window.crypto) { + return window.crypto.subtle.verify(algorithm, key, signature, data) + } + + throw new APINotSupportedError('Crypto') + }, + } + + return crypto +} diff --git a/src/client/platform/web/api/text.ts b/src/client/platform/web/api/text.ts index cb76a7ce7b..bb99fee590 100644 --- a/src/client/platform/web/api/text.ts +++ b/src/client/platform/web/api/text.ts @@ -28,6 +28,10 @@ export function webText(window: Window, opt: BootOpt): API['text'] { return measureText(ctx, text, fontSize, maxWidth) }, + // @ts-ignore + TextEncoder: window.TextEncoder, + // @ts-ignore + TextDecoder: window.TextDecoder, } return text diff --git a/src/client/platform/web/boot.ts b/src/client/platform/web/boot.ts index 621e44a6a8..a1a8a4c340 100644 --- a/src/client/platform/web/boot.ts +++ b/src/client/platform/web/boot.ts @@ -20,6 +20,7 @@ import { webAnimation } from './api/animation' import { webBluetooth } from './api/bluetooth' import { webChannel } from './api/channel' import { webClipboard } from './api/clipboard' +import { webCrypto } from './api/crypto' import { webDB } from './api/db' import { webDevice } from './api/device' import { webDocument } from './api/document' @@ -93,6 +94,7 @@ export function webBoot( const navigator = webNavigator(window, opt) const layout = webLayout(window, opt) const theme = webTheme(window, _root, opt) + const crypto = webCrypto(window, opt) const api: API = { alert, @@ -104,6 +106,7 @@ export function webBoot( screen, bluetooth, clipboard, + crypto, location, history, geolocation, diff --git a/src/host/none.ts b/src/host/none.ts index 2a14dd9e6e..51365dd083 100644 --- a/src/host/none.ts +++ b/src/host/none.ts @@ -217,6 +217,8 @@ export function noHost(): API { measureText: (text: string) => { throw new APINotSupportedError('Measure Text') }, + TextEncoder: undefined, + TextDecoder: undefined, }, worker: { start: () => { @@ -313,6 +315,64 @@ export function noHost(): API { throw new MethodNotImplementedError() }, }, + crypto: { + generateKey: function ( + algorithm: AlgorithmIdentifier, + extractable: boolean, + keyUsages: string[] + ): Promise { + throw new MethodNotImplementedError() + }, + exportKey: function ( + format: T, + key: CryptoKey + ): Promise { + throw new MethodNotImplementedError() + }, + importKey: function ( + format: T, + keyData: T extends 'jwk' ? JsonWebKey : BufferSource, + algorithm: + | AlgorithmIdentifier + | RsaHashedImportParams + | EcKeyImportParams + | HmacImportParams + | AesKeyAlgorithm, + extractable: boolean, + keyUsages: ReadonlyArray + ): Promise { + throw new MethodNotImplementedError() + }, + encrypt: function ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: ArrayBuffer + ): Promise { + throw new MethodNotImplementedError() + }, + decrypt: function ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: ArrayBuffer + ): Promise { + throw new MethodNotImplementedError() + }, + sign: function ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + data: ArrayBuffer + ): Promise { + throw new MethodNotImplementedError() + }, + verify: function ( + algorithm: AlgorithmIdentifier, + key: CryptoKey, + signature: BufferSource, + data: BufferSource + ): Promise { + throw new MethodNotImplementedError() + }, + }, } return api diff --git a/src/interface.ts b/src/interface.ts index bef03ec4d4..9d278d9819 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -40,6 +40,10 @@ export const CLASS_TYPE_MEDIA_ELEMENT = 'ME' // MediaElement export const CLASS_TYPE_OBSERVER = 'OB' // OBserver export const CLASS_TYPE_RESPONSE = 'RES' // RESponse export const CLASS_TYPE_BODY = 'BO' // BOdy +export const CLASS_TYPE_CRYPTO_KEY = 'CK' // CryptoKey +export const CLASS_TYPE_ARRAY_BUFFER = 'AB' // ArrayBuffer +export const CLASS_TYPE_TEXT_ENCODER = 'TE' // TextEncoder +export const CLASS_TYPE_TEXT_DECODER = 'TD' // TextDecoder export const INHERITANCE = { U: ['EE'], @@ -79,6 +83,10 @@ export type AllTypes = { F: T AC: T D: T + CK: T + AB: T + TE: T + TD: T } export const ALL_TYPES_MAP: AllTypes = { @@ -106,6 +114,10 @@ export const ALL_TYPES_MAP: AllTypes = { F: true, AC: true, D: true, + CK: true, + AB: true, + TE: true, + TD: true, } export const ALL_TYPES = Object.keys(ALL_TYPES_MAP) diff --git a/src/system/f/meta/Scope/index.ts b/src/system/f/meta/Scope/index.ts index 1124b1a243..90a811a100 100644 --- a/src/system/f/meta/Scope/index.ts +++ b/src/system/f/meta/Scope/index.ts @@ -55,7 +55,7 @@ export default class Scope extends Functional, O> { const sharedRef: SharedRef> = { current: localScope } - const _obj = wrapSharedRef(sharedRef, this.__system) + const _obj = wrapSharedRef(sharedRef) const obj = $wrap(this.__system, _obj, ['J']) diff --git a/src/system/platform/State/index.ts b/src/system/platform/State/index.ts index c047a075ec..1fb41cab84 100644 --- a/src/system/platform/State/index.ts +++ b/src/system/platform/State/index.ts @@ -74,16 +74,13 @@ export default class State extends Holder, O> { { api = weakMerge( api, - wrapSharedRefArrayInterface( - sharedRef as SharedRef, - this.__system - ) + wrapSharedRefArrayInterface(sharedRef as SharedRef) ) } break case 'J': { - api = weakMerge(api, wrapSharedRef(sharedRef, this.__system)) + api = weakMerge(api, wrapSharedRef(sharedRef)) } break } diff --git a/src/system/platform/api/array/typed/Buffer/index.ts b/src/system/platform/api/array/typed/Buffer/index.ts new file mode 100644 index 0000000000..2984cb64e5 --- /dev/null +++ b/src/system/platform/api/array/typed/Buffer/index.ts @@ -0,0 +1,48 @@ +import { Done } from '../../../../../../Class/Functional/Done' +import { Holder } from '../../../../../../Class/Holder' +import { System } from '../../../../../../system' +import { AB } from '../../../../../../types/interface/AB' +import { TA } from '../../../../../../types/interface/TA' +import { wrapArrayBuffer } from '../../../../../../wrap/ArrayBuffer' +import { ID_BUFFER } from '../../../../../_ids' + +export interface I { + from: TA + any: any +} + +export interface O { + array: AB +} + +export default class Buffer_ extends Holder { + constructor(system: System) { + super( + { + fi: ['from', 'any'], + fo: ['array'], + i: [], + o: [], + }, + { + output: { + array: { + ref: true, + }, + }, + }, + system, + ID_BUFFER + ) + } + + f({ from }: I, done: Done) { + const array_ = from.buffer() + + const array = wrapArrayBuffer(array_, this.__system) + + done({ + array, + }) + } +} diff --git a/src/system/platform/api/array/typed/Buffer/spec.json b/src/system/platform/api/array/typed/Buffer/spec.json new file mode 100644 index 0000000000..1d0e48384c --- /dev/null +++ b/src/system/platform/api/array/typed/Buffer/spec.json @@ -0,0 +1,33 @@ +{ + "name": "buffer", + "inputs": { + "from": { + "type": "`TA`", + "ref": true + }, + "any": { + "type": "any" + }, + "done": { + "type": "any", + "defaultIgnored": true + } + }, + "outputs": { + "array": { + "type": "`AB`", + "ref": true, + "icon": "array" + } + }, + "metadata": { + "icon": "square", + "description": "get internal `array` buffer from typed array", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "04d118fd-433e-4dd0-b828-0117eece566a", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/array/typed/Uint8Array/index.ts b/src/system/platform/api/array/typed/Uint8Array/index.ts new file mode 100644 index 0000000000..c3aca56f0f --- /dev/null +++ b/src/system/platform/api/array/typed/Uint8Array/index.ts @@ -0,0 +1,58 @@ +import { Done } from '../../../../../../Class/Functional/Done' +import { Semifunctional } from '../../../../../../Class/Semifunctional' +import { System } from '../../../../../../system' +import { A } from '../../../../../../types/interface/A' +import { TA } from '../../../../../../types/interface/TA' +import { wrapUint8Array } from '../../../../../../wrap/Array' +import { ID_8BIT_UNSIGNED_ARRAY } from '../../../../../_ids' + +export interface I { + length: number + done: any +} + +export interface O { + array: A & TA +} + +export default class Uint8Array_ extends Semifunctional { + constructor(system: System) { + super( + { + fi: ['length'], + fo: ['array'], + i: ['done'], + o: [], + }, + { + output: { + array: { + ref: true, + }, + }, + }, + system, + ID_8BIT_UNSIGNED_ARRAY + ) + } + + f({ length }: I, done: Done) { + const _array = new Uint8Array(length) + + const array = wrapUint8Array(_array, this.__system) + + done({ + array, + }) + } + + public onIterDataInputData(name: string, data: any): void { + if (name === 'done') { + this._forward_all_empty() + + this._backward('length') + + this._backward('done') + } + } +} diff --git a/src/system/platform/api/array/typed/Uint8Array/spec.json b/src/system/platform/api/array/typed/Uint8Array/spec.json new file mode 100644 index 0000000000..978e39ce75 --- /dev/null +++ b/src/system/platform/api/array/typed/Uint8Array/spec.json @@ -0,0 +1,31 @@ +{ + "name": "8-bit unsigned array", + "inputs": { + "length": { + "type": "number", + "metadata": { + "description": "length of the array" + } + }, + "done": { + "type": "any" + } + }, + "outputs": { + "array": { + "type": "`V`&`A`&`TA`", + "ref": true, + "icon": "array" + } + }, + "metadata": { + "icon": "circle", + "description": "array of 8-bit unsigned integers", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "c91ce066-ea5f-496d-8783-8f46c29673de", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/array/typed/Uint8Array0/index.ts b/src/system/platform/api/array/typed/Uint8Array0/index.ts new file mode 100644 index 0000000000..1860173912 --- /dev/null +++ b/src/system/platform/api/array/typed/Uint8Array0/index.ts @@ -0,0 +1,58 @@ +import { Done } from '../../../../../../Class/Functional/Done' +import { Semifunctional } from '../../../../../../Class/Semifunctional' +import { System } from '../../../../../../system' +import { A } from '../../../../../../types/interface/A' +import { TA } from '../../../../../../types/interface/TA' +import { wrapUint8Array } from '../../../../../../wrap/Array' +import { ID_8BIT_UNSIGNED_ARRAY_0 } from '../../../../../_ids' + +export interface I { + init: number[] + done: any +} + +export interface O { + array: A & TA +} + +export default class Uint8Array0 extends Semifunctional { + constructor(system: System) { + super( + { + fi: ['init'], + fo: ['array'], + i: ['done'], + o: [], + }, + { + output: { + array: { + ref: true, + }, + }, + }, + system, + ID_8BIT_UNSIGNED_ARRAY_0 + ) + } + + f({ init }: I, done: Done) { + const _array = new Uint8Array(init) + + const array = wrapUint8Array(_array, this.__system) + + done({ + array, + }) + } + + public onIterDataInputData(name: string, data: any): void { + if (name === 'done') { + this._forward_all_empty() + + this._backward('init') + + this._backward('done') + } + } +} diff --git a/src/system/platform/api/array/typed/Uint8Array0/spec.json b/src/system/platform/api/array/typed/Uint8Array0/spec.json new file mode 100644 index 0000000000..4294d95eac --- /dev/null +++ b/src/system/platform/api/array/typed/Uint8Array0/spec.json @@ -0,0 +1,31 @@ +{ + "name": "8-bit unsigned array", + "inputs": { + "init": { + "type": "number[]", + "metadata": { + "examples": ["[]"] + } + }, + "done": { + "type": "any" + } + }, + "outputs": { + "array": { + "type": "`V`&`A`&`TA`", + "ref": true, + "icon": "array" + } + }, + "metadata": { + "icon": "circle", + "description": "array of 8-bit unsigned integers clamped to 0-255", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "5500c4ae-e464-40fa-9cfb-6af11c8f2c7e", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/array/typed/Uint8Array1/index.ts b/src/system/platform/api/array/typed/Uint8Array1/index.ts new file mode 100644 index 0000000000..80382b6d22 --- /dev/null +++ b/src/system/platform/api/array/typed/Uint8Array1/index.ts @@ -0,0 +1,65 @@ +import { Done } from '../../../../../../Class/Functional/Done' +import { Semifunctional } from '../../../../../../Class/Semifunctional' +import { System } from '../../../../../../system' +import { A } from '../../../../../../types/interface/A' +import { AB } from '../../../../../../types/interface/AB' +import { TA } from '../../../../../../types/interface/TA' +import { V } from '../../../../../../types/interface/V' +import { wrapUint8Array } from '../../../../../../wrap/Array' +import { ID_8BIT_UNSIGNED_ARRAY_0 } from '../../../../../_ids' + +export interface I { + init: AB + done: any +} + +export interface O { + array: V & A & TA +} + +export default class Uint8Array1 extends Semifunctional { + constructor(system: System) { + super( + { + fi: ['init'], + fo: ['array'], + i: ['done'], + o: [], + }, + { + output: { + init: { + ref: true, + }, + array: { + ref: true, + }, + }, + }, + system, + ID_8BIT_UNSIGNED_ARRAY_0 + ) + } + + async f({ init }: I, done: Done) { + const init_ = await init.arrayBuffer() + + const array_ = new Uint8Array(init_) + + const array = wrapUint8Array(array_, this.__system) + + done({ + array, + }) + } + + public onIterDataInputData(name: string, data: any): void { + if (name === 'done') { + this._forward_all_empty() + + this._backward('init') + + this._backward('done') + } + } +} diff --git a/src/system/platform/api/array/typed/Uint8Array1/spec.json b/src/system/platform/api/array/typed/Uint8Array1/spec.json new file mode 100644 index 0000000000..9f62462c18 --- /dev/null +++ b/src/system/platform/api/array/typed/Uint8Array1/spec.json @@ -0,0 +1,29 @@ +{ + "name": "8-bit unsigned array", + "inputs": { + "init": { + "type": "`AB`", + "ref": true + }, + "done": { + "type": "any" + } + }, + "outputs": { + "array": { + "type": "`V`&`A`&`TA`", + "ref": true, + "icon": "array" + } + }, + "metadata": { + "icon": "circle", + "description": "array of 8-bit unsigned integers clamped to 0-255", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "364fad98-9190-47a8-bd5c-33d7b882ddd6", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/typed/Uint8ClampedArray/index.ts b/src/system/platform/api/array/typed/Uint8ClampedArray/index.ts similarity index 60% rename from src/system/platform/typed/Uint8ClampedArray/index.ts rename to src/system/platform/api/array/typed/Uint8ClampedArray/index.ts index 8f3d4ad53b..c2021a1e16 100644 --- a/src/system/platform/typed/Uint8ClampedArray/index.ts +++ b/src/system/platform/api/array/typed/Uint8ClampedArray/index.ts @@ -1,10 +1,10 @@ -import { Done } from '../../../../Class/Functional/Done' -import { Holder } from '../../../../Class/Holder' -import { System } from '../../../../system' -import { A } from '../../../../types/interface/A' -import { TA } from '../../../../types/interface/TA' -import { wrapUint8Array } from '../../../../wrap/Array' -import { ID_8BIT_UNSIGNED_CLAMPED_ARRAY } from '../../../_ids' +import { Done } from '../../../../../../Class/Functional/Done' +import { Holder } from '../../../../../../Class/Holder' +import { System } from '../../../../../../system' +import { A } from '../../../../../../types/interface/A' +import { TA } from '../../../../../../types/interface/TA' +import { wrapUint8Array } from '../../../../../../wrap/Array' +import { ID_8BIT_UNSIGNED_CLAMPED_ARRAY } from '../../../../../_ids' export interface I { length: number diff --git a/src/system/platform/typed/Uint8ClampedArray/spec.json b/src/system/platform/api/array/typed/Uint8ClampedArray/spec.json similarity index 77% rename from src/system/platform/typed/Uint8ClampedArray/spec.json rename to src/system/platform/api/array/typed/Uint8ClampedArray/spec.json index 3962305f33..b5d33874f9 100644 --- a/src/system/platform/typed/Uint8ClampedArray/spec.json +++ b/src/system/platform/api/array/typed/Uint8ClampedArray/spec.json @@ -13,15 +13,16 @@ }, "outputs": { "array": { - "type": "`A`&`TA`", - "ref": true + "type": "`V`&`A`&`TA`", + "ref": true, + "icon": "array" } }, "metadata": { - "icon": "square", + "icon": "circle", "description": "array of 8-bit unsigned integers clamped to 0-255", "complexity": 3, - "tags": ["platform"] + "tags": ["platform", "array", "typed"] }, "id": "cd8c1d94-1471-49e2-8b43-d98ae93b70f3", "base": true, diff --git a/src/system/platform/typed/Uint8ClampedArray0/index.ts b/src/system/platform/api/array/typed/Uint8ClampedArray0/index.ts similarity index 60% rename from src/system/platform/typed/Uint8ClampedArray0/index.ts rename to src/system/platform/api/array/typed/Uint8ClampedArray0/index.ts index a2b5610db2..921f757679 100644 --- a/src/system/platform/typed/Uint8ClampedArray0/index.ts +++ b/src/system/platform/api/array/typed/Uint8ClampedArray0/index.ts @@ -1,10 +1,10 @@ -import { Done } from '../../../../Class/Functional/Done' -import { Holder } from '../../../../Class/Holder' -import { System } from '../../../../system' -import { A } from '../../../../types/interface/A' -import { TA } from '../../../../types/interface/TA' -import { wrapUint8Array } from '../../../../wrap/Array' -import { ID_8BIT_UNSIGNED_CLAMPED_ARRAY_0 } from '../../../_ids' +import { Done } from '../../../../../../Class/Functional/Done' +import { Holder } from '../../../../../../Class/Holder' +import { System } from '../../../../../../system' +import { A } from '../../../../../../types/interface/A' +import { TA } from '../../../../../../types/interface/TA' +import { wrapUint8Array } from '../../../../../../wrap/Array' +import { ID_8BIT_UNSIGNED_CLAMPED_ARRAY_0 } from '../../../../../_ids' export interface I { init: number[] diff --git a/src/system/platform/typed/Uint8ClampedArray0/spec.json b/src/system/platform/api/array/typed/Uint8ClampedArray0/spec.json similarity index 77% rename from src/system/platform/typed/Uint8ClampedArray0/spec.json rename to src/system/platform/api/array/typed/Uint8ClampedArray0/spec.json index b841b8cb26..04c205b804 100644 --- a/src/system/platform/typed/Uint8ClampedArray0/spec.json +++ b/src/system/platform/api/array/typed/Uint8ClampedArray0/spec.json @@ -13,15 +13,16 @@ }, "outputs": { "array": { - "type": "`A`&`TA`", - "ref": true + "type": "`V`&`A`&`TA`", + "ref": true, + "icon": "array" } }, "metadata": { - "icon": "square", + "icon": "circle", "description": "array of 8-bit unsigned integers clamped to 0-255", "complexity": 3, - "tags": ["platform"] + "tags": ["platform", "array", "typed"] }, "id": "4d68d552-46d6-4ee4-9823-63f9b9479fae", "base": true, diff --git a/src/system/platform/typed/method/Set/index.ts b/src/system/platform/api/array/typed/method/Set/index.ts similarity index 55% rename from src/system/platform/typed/method/Set/index.ts rename to src/system/platform/api/array/typed/method/Set/index.ts index 2bd79bed4c..e13944378b 100644 --- a/src/system/platform/typed/method/Set/index.ts +++ b/src/system/platform/api/array/typed/method/Set/index.ts @@ -1,9 +1,9 @@ -import { $ } from '../../../../../Class/$' -import { Functional } from '../../../../../Class/Functional' -import { Done } from '../../../../../Class/Functional/Done' -import { System } from '../../../../../system' -import { TA } from '../../../../../types/interface/TA' -import { ID_SET_2 } from '../../../../_ids' +import { $ } from '../../../../../../../Class/$' +import { Functional } from '../../../../../../../Class/Functional' +import { Done } from '../../../../../../../Class/Functional/Done' +import { System } from '../../../../../../../system' +import { TA } from '../../../../../../../types/interface/TA' +import { ID_SET_0 } from '../../../../../../_ids' export interface I { array: TA & $ @@ -13,7 +13,7 @@ export interface I { export interface O {} -export default class Set2 extends Functional { +export default class Set0 extends Functional { constructor(system: System) { super( { @@ -31,7 +31,7 @@ export default class Set2 extends Functional { }, }, system, - ID_SET_2 + ID_SET_0 ) } diff --git a/src/system/platform/typed/method/Set/spec.json b/src/system/platform/api/array/typed/method/Set/spec.json similarity index 100% rename from src/system/platform/typed/method/Set/spec.json rename to src/system/platform/api/array/typed/method/Set/spec.json diff --git a/src/system/platform/api/crypto/Decrypt/index.ts b/src/system/platform/api/crypto/Decrypt/index.ts new file mode 100644 index 0000000000..f9bf92a84b --- /dev/null +++ b/src/system/platform/api/crypto/Decrypt/index.ts @@ -0,0 +1,83 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { AB } from '../../../../../types/interface/AB' +import { CK } from '../../../../../types/interface/CK' +import { J } from '../../../../../types/interface/J' +import { wrapArrayBuffer } from '../../../../../wrap/ArrayBuffer' +import { ID_DECRYPT } from '../../../../_ids' + +export type I = { + key: CK & $ + algorithm: J & $ + data: AB & $ + opt: {} +} + +export type O = { + data: AB & $ +} + +export default class Decrypt extends Holder { + constructor(system: System) { + super( + { + fi: ['algorithm', 'key', 'data', 'opt'], + fo: ['data'], + }, + { + input: { + algorithm: { + ref: true, + }, + key: { + ref: true, + }, + data: { + ref: true, + }, + }, + output: { + data: { + ref: true, + }, + }, + }, + system, + ID_DECRYPT + ) + } + + async f({ opt, key, algorithm, data }: I, done: Done): Promise { + const { + api: { + crypto: { decrypt }, + }, + } = this.__system + + const key_ = (await key.raw()) as CryptoKey + const algorithm_ = (await algorithm.raw()) as AlgorithmIdentifier + const data_ = (await data.raw()) as ArrayBuffer + + let _data: ArrayBuffer + + try { + _data = await decrypt(algorithm_, key_, data_) + } catch (err) { + if (err.name === 'OperationError') { + done(undefined, 'operation error') + + return + } + + done(undefined, err.message.toLowerCase()) + + return + } + + const __data = wrapArrayBuffer(_data, this.__system) + + done({ data: __data }) + } +} diff --git a/src/system/platform/api/crypto/Decrypt/spec.json b/src/system/platform/api/crypto/Decrypt/spec.json new file mode 100644 index 0000000000..51ed18f4dc --- /dev/null +++ b/src/system/platform/api/crypto/Decrypt/spec.json @@ -0,0 +1,42 @@ +{ + "name": "decrypt", + "inputs": { + "opt": { + "type": "{}" + }, + "key": { + "type": "`CK`", + "ref": true + }, + "algorithm": { + "type": "`J`", + "ref": true + }, + "data": { + "type": "`AB`", + "ref": true + }, + "done": { + "type": "any", + "defaultIgnored": true + } + }, + "outputs": { + "data": { + "type": "`AB`", + "ref": true, + "icon": "file" + } + }, + "metadata": { + "icon": "lock", + "description": "dencrypts `data` with given `key` and `algorithm`", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/decrypt", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "f6400b55-10af-4983-96bc-6b915433f3b6", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/Encrypt/index.ts b/src/system/platform/api/crypto/Encrypt/index.ts new file mode 100644 index 0000000000..64fca7542a --- /dev/null +++ b/src/system/platform/api/crypto/Encrypt/index.ts @@ -0,0 +1,84 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { AB } from '../../../../../types/interface/AB' +import { CK } from '../../../../../types/interface/CK' +import { J } from '../../../../../types/interface/J' +import { wrapArrayBuffer } from '../../../../../wrap/ArrayBuffer' +import { ID_ENCRYPT } from '../../../../_ids' + +export type I = { + key: CK & $ + algorithm: J & $ + data: AB & $ +} + +export type O = { + data: AB & $ +} + +export default class Encrypt extends Holder { + constructor(system: System) { + super( + { + fi: ['opt', 'algorithm', 'key', 'data'], + fo: ['data'], + }, + { + input: { + algorithm: { + ref: true, + }, + key: { + ref: true, + }, + data: { + ref: true, + }, + }, + output: { + data: { + ref: true, + }, + }, + }, + system, + ID_ENCRYPT + ) + } + + async f({ key, algorithm, data }: I, done: Done): Promise { + const { + api: { + crypto: { encrypt }, + }, + } = this.__system + + const key_ = (await key.raw()) as CryptoKey + const algorithm_ = (await algorithm.raw()) as AlgorithmIdentifier + const data_ = (await data.raw()) as ArrayBuffer + + let _data: ArrayBuffer + + try { + _data = (await encrypt(algorithm_, key_, data_)) as ArrayBuffer + } catch (err) { + if (err.message) { + done(undefined, err.message.toLowerCase()) + } else { + if (err.name === 'OperationError') { + done(undefined, 'encrypt operation error') + } else { + done(undefined, 'encrypt failed for an unknown reason') + } + } + + return + } + + const __data = wrapArrayBuffer(_data, this.__system) + + done({ data: __data }) + } +} diff --git a/src/system/platform/api/crypto/Encrypt/spec.json b/src/system/platform/api/crypto/Encrypt/spec.json new file mode 100644 index 0000000000..a028ac5c3d --- /dev/null +++ b/src/system/platform/api/crypto/Encrypt/spec.json @@ -0,0 +1,42 @@ +{ + "name": "encrypt", + "inputs": { + "opt": { + "type": "{}" + }, + "key": { + "type": "`CK`", + "ref": true + }, + "algorithm": { + "type": "`J`", + "ref": true + }, + "data": { + "type": "`AB`", + "ref": true + }, + "done": { + "type": "any", + "defaultIgnored": true + } + }, + "outputs": { + "data": { + "type": "`AB`", + "ref": true, + "icon": "file-lock" + } + }, + "metadata": { + "icon": "lock", + "description": "encrypts `data` with given `key` and `algorithm`", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "8edf4dd9-4d11-444c-bfe5-b54dc141cded", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/ExportJwtKey/index.ts b/src/system/platform/api/crypto/ExportJwtKey/index.ts new file mode 100644 index 0000000000..8e9165122a --- /dev/null +++ b/src/system/platform/api/crypto/ExportJwtKey/index.ts @@ -0,0 +1,57 @@ +import { $ } from '../../../../../Class/$' +import { Functional } from '../../../../../Class/Functional' +import { Done } from '../../../../../Class/Functional/Done' +import { System } from '../../../../../system' +import { CK } from '../../../../../types/interface/CK' +import { ID_EXPORT_JWK_KEY } from '../../../../_ids' + +export type I = { + key: CK & $ + format: 'jwk' +} + +export type O = { + key: JsonWebKey +} + +export default class ExportJwtKey extends Functional { + constructor(system: System) { + super( + { + i: ['key', 'format'], + o: ['key'], + }, + { + input: { + key: { + ref: true, + }, + }, + }, + system, + ID_EXPORT_JWK_KEY + ) + } + + async f({ key, format }: I, done: Done): Promise { + const { + api: { + crypto: { exportKey }, + }, + } = this.__system + + const key__ = (await key.raw()) as CryptoKey + + let key_: JsonWebKey + + try { + key_ = (await exportKey(format, key__)) as JsonWebKey + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + done({ key: key_ }) + } +} diff --git a/src/system/platform/api/crypto/ExportJwtKey/spec.json b/src/system/platform/api/crypto/ExportJwtKey/spec.json new file mode 100644 index 0000000000..b61ce5664a --- /dev/null +++ b/src/system/platform/api/crypto/ExportJwtKey/spec.json @@ -0,0 +1,29 @@ +{ + "name": "export jwk key", + "inputs": { + "key": { + "type": "`CK`", + "ref": true + }, + "format": { + "type": "'jwk'" + } + }, + "outputs": { + "key": { + "type": "object", + "icon": "key" + } + }, + "metadata": { + "icon": "lock", + "description": "export jwt key as a `data` array buffer", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/exportKey", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "6183465e-381f-4546-8c42-6b7eaaa25926", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/ExportKey/index.ts b/src/system/platform/api/crypto/ExportKey/index.ts new file mode 100644 index 0000000000..10bd7edc3f --- /dev/null +++ b/src/system/platform/api/crypto/ExportKey/index.ts @@ -0,0 +1,62 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { AB } from '../../../../../types/interface/AB' +import { CK } from '../../../../../types/interface/CK' +import { wrapArrayBuffer } from '../../../../../wrap/ArrayBuffer' +import { ID_EXPORT_KEY } from '../../../../_ids' + +export type I = { + key: CK & $ + format: Exclude +} + +export type O = { + key: AB +} + +export default class ExportKey extends Holder { + constructor(system: System) { + super( + { + fi: ['key', 'format'], + fo: ['key'], + }, + { + input: { + key: { + ref: true, + }, + }, + output: {}, + }, + system, + ID_EXPORT_KEY + ) + } + + async f({ key, format }: I, done: Done): Promise { + const { + api: { + crypto: { exportKey }, + }, + } = this.__system + + const key___ = (await key.raw()) as CryptoKey + + let key__: ArrayBuffer + + try { + key__ = (await exportKey(format, key___)) as ArrayBuffer + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + const key_ = wrapArrayBuffer(key__, this.__system) + + done({ key: key_ }) + } +} diff --git a/src/system/platform/api/crypto/ExportKey/spec.json b/src/system/platform/api/crypto/ExportKey/spec.json new file mode 100644 index 0000000000..ac907499f8 --- /dev/null +++ b/src/system/platform/api/crypto/ExportKey/spec.json @@ -0,0 +1,30 @@ +{ + "name": "export key", + "inputs": { + "key": { + "type": "`CK`", + "ref": true + }, + "format": { + "type": "'raw'|'pkcs8'|'spki'" + } + }, + "outputs": { + "key": { + "type": "`AB`", + "ref": true, + "icon": "key" + } + }, + "metadata": { + "icon": "lock", + "description": "export raw key as a `data` array buffer", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/exportKey", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "d54cd5d2-91eb-4f95-be2d-62fdaf86f474", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/GenerateKey/index.ts b/src/system/platform/api/crypto/GenerateKey/index.ts new file mode 100644 index 0000000000..e3c92bf8c8 --- /dev/null +++ b/src/system/platform/api/crypto/GenerateKey/index.ts @@ -0,0 +1,80 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { CK } from '../../../../../types/interface/CK' +import { J } from '../../../../../types/interface/J' +import { wrapCryptoKey } from '../../../../../wrap/CryptoKey' +import { ID_GENERATE_KEY } from '../../../../_ids' + +export type I = { + algorithm: J & $ + extractable: boolean + keyUsages: string[] +} + +export type O = { + key: CK +} + +export default class GenerateKey extends Holder { + constructor(system: System) { + super( + { + fi: ['algorithm', 'extractable', 'keyUsages'], + fo: ['key'], + }, + { + input: { + algorithm: { + ref: true, + }, + }, + output: { + key: { + ref: true, + }, + }, + }, + system, + ID_GENERATE_KEY + ) + } + + async f( + { algorithm, extractable, keyUsages }: I, + done: Done + ): Promise { + const { + api: { + crypto: { generateKey }, + }, + } = this.__system + + const algorithm_ = algorithm.raw() + + if (!['HMAC'].includes(algorithm_.name)) { + done(undefined, 'invalid algorithm single key generation') + + return + } + + let key_: CryptoKey + + try { + key_ = (await generateKey( + algorithm_, + extractable, + keyUsages + )) as CryptoKey + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + const key = wrapCryptoKey(key_, this.__system) + + done({ key }) + } +} diff --git a/src/system/platform/api/crypto/GenerateKey/spec.json b/src/system/platform/api/crypto/GenerateKey/spec.json new file mode 100644 index 0000000000..0f90e05829 --- /dev/null +++ b/src/system/platform/api/crypto/GenerateKey/spec.json @@ -0,0 +1,39 @@ +{ + "name": "generate key", + "inputs": { + "algorithm": { + "type": "`J`", + "ref": true + }, + "extractable": { + "type": "boolean" + }, + "keyUsages": { + "type": "string[]", + "metadata": { + "examples": [ + "['encrypt','decrypt']", + "['encrypt','decrypt','sign','verify','deriveKey','deriveBits','wrapKey','unwrapKey']" + ] + } + } + }, + "outputs": { + "key": { + "type": "`CK`", + "ref": true, + "icon": "key" + } + }, + "metadata": { + "icon": "lock", + "description": "generate single cryptographic key based on `algorithm`", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "00e14b7e-7339-4c9f-a3ff-a16562558a28", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/GenerateKeyPair/index.ts b/src/system/platform/api/crypto/GenerateKeyPair/index.ts new file mode 100644 index 0000000000..ea2fdc2f7b --- /dev/null +++ b/src/system/platform/api/crypto/GenerateKeyPair/index.ts @@ -0,0 +1,92 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { Dict } from '../../../../../types/Dict' +import { CK } from '../../../../../types/interface/CK' +import { J } from '../../../../../types/interface/J' +import { wrapCryptoKey } from '../../../../../wrap/CryptoKey' +import { ID_GENERATE_KEY_PAIR } from '../../../../_ids' + +export type I = { + algorithm: J<{ name: string } & Dict> & $ + extractable: boolean + keyUsages: string[] +} + +export type O = { + public: CK + private: CK +} + +export default class GenerateKeyPair extends Holder { + constructor(system: System) { + super( + { + fi: ['algorithm', 'extractable', 'keyUsages'], + fo: ['public', 'private'], + }, + { + input: { + algorithm: { + ref: true, + }, + }, + output: { + public: { + ref: true, + }, + private: { + ref: true, + }, + }, + }, + system, + ID_GENERATE_KEY_PAIR + ) + } + + async f( + { algorithm, extractable, keyUsages }: I, + done: Done + ): Promise { + const { + api: { + crypto: { generateKey }, + }, + } = this.__system + + const algorithm_ = algorithm.raw() as { name: string } + + if ( + !['RSASSA-PKCS1-v1_5', 'RSA-PSS', 'RSA-OAEP', 'ECDSA'].includes( + algorithm_.name + ) + ) { + done(undefined, 'invalid algorithm for key pair generation') + + return + } + + let keyPair: CryptoKeyPair + + try { + keyPair = (await generateKey( + algorithm_, + extractable, + keyUsages + )) as CryptoKeyPair + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + const { publicKey, privateKey } = keyPair + + const public_ = wrapCryptoKey(publicKey, this.__system) + const private_ = wrapCryptoKey(privateKey, this.__system) + + done({ public: public_, private: private_ }) + } +} diff --git a/src/system/platform/api/crypto/GenerateKeyPair/spec.json b/src/system/platform/api/crypto/GenerateKeyPair/spec.json new file mode 100644 index 0000000000..7ba2cc2623 --- /dev/null +++ b/src/system/platform/api/crypto/GenerateKeyPair/spec.json @@ -0,0 +1,44 @@ +{ + "name": "generate key pair", + "inputs": { + "algorithm": { + "type": "`J`", + "ref": true + }, + "extractable": { + "type": "boolean" + }, + "keyUsages": { + "type": "string[]", + "metadata": { + "examples": [ + "['encrypt','decrypt']", + "['encrypt','decrypt','sign','verify','deriveKey','deriveBits','wrapKey','unwrapKey']" + ] + } + } + }, + "outputs": { + "public": { + "type": "`CK`", + "ref": true, + "icon": "key" + }, + "private": { + "type": "`CK`", + "ref": true, + "icon": "key" + } + }, + "metadata": { + "icon": "lock", + "description": "generate cryptographic public and private key pairs based on `algorithm`", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "089d3cef-2597-4777-8558-9942b4029472", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/ImportJwtKey/index.ts b/src/system/platform/api/crypto/ImportJwtKey/index.ts new file mode 100644 index 0000000000..b5727635a9 --- /dev/null +++ b/src/system/platform/api/crypto/ImportJwtKey/index.ts @@ -0,0 +1,69 @@ +import { $ } from '../../../../../Class/$' +import { Functional } from '../../../../../Class/Functional' +import { Done } from '../../../../../Class/Functional/Done' +import { System } from '../../../../../system' +import { CK } from '../../../../../types/interface/CK' +import { J } from '../../../../../types/interface/J' +import { wrapCryptoKey } from '../../../../../wrap/CryptoKey' +import { ID_IMPORT_JWT_KEY } from '../../../../_ids' + +export type I = { + data: JsonWebKey + algorithm: J & $ + extractable: boolean + keyUsages: KeyUsage[] +} + +export type O = { + key: CK +} + +export default class ImportJwkKey extends Functional { + constructor(system: System) { + super( + { + i: ['algorithm', 'extractable', 'keyUsages', 'data'], + o: ['key'], + }, + { + input: { + algorithm: { + ref: true, + }, + }, + output: { + key: { + ref: true, + }, + }, + }, + system, + ID_IMPORT_JWT_KEY + ) + } + + async f( + { data, algorithm, extractable, keyUsages }: I, + done: Done + ): Promise { + const { + api: { + crypto: { importKey }, + }, + } = this.__system + + let algorithm_ = algorithm.raw() as AlgorithmIdentifier + + const key_ = await importKey( + 'jwk', + data, + algorithm_, + extractable, + keyUsages + ) + + const key = wrapCryptoKey(key_, this.__system) + + done({ key }) + } +} diff --git a/src/system/platform/api/crypto/ImportJwtKey/spec.json b/src/system/platform/api/crypto/ImportJwtKey/spec.json new file mode 100644 index 0000000000..f188e6d58c --- /dev/null +++ b/src/system/platform/api/crypto/ImportJwtKey/spec.json @@ -0,0 +1,42 @@ +{ + "name": "import jwt key", + "inputs": { + "data": { + "type": "object" + }, + "algorithm": { + "type": "`J`", + "ref": true + }, + "extractable": { + "type": "boolean" + }, + "keyUsages": { + "type": "string[]", + "metadata": { + "examples": [ + "['encrypt','decrypt']", + "['encrypt','decrypt','sign','verify','deriveKey','deriveBits','wrapKey','unwrapKey']" + ] + } + } + }, + "outputs": { + "key": { + "type": "`CK`", + "ref": true, + "icon": "key" + } + }, + "metadata": { + "icon": "lock", + "description": "parse cryto jwk `key` given knowledge of `format`, `algorithm`, `extractable` and `keyUsages`", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "4830eec3-2a72-4e36-b68a-902aa73c6ead", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/ImportKey/index.ts b/src/system/platform/api/crypto/ImportKey/index.ts new file mode 100644 index 0000000000..1f5d6e7844 --- /dev/null +++ b/src/system/platform/api/crypto/ImportKey/index.ts @@ -0,0 +1,75 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { AB } from '../../../../../types/interface/AB' +import { CK } from '../../../../../types/interface/CK' +import { J } from '../../../../../types/interface/J' +import { wrapCryptoKey } from '../../../../../wrap/CryptoKey' +import { ID_IMPORT_KEY } from '../../../../_ids' + +export type I = { + data: AB & $ + format: Exclude + algorithm: J & $ + extractable: boolean + keyUsages: KeyUsage[] + done: any +} + +export type O = { + key: CK +} + +export default class ImportKey extends Holder { + constructor(system: System) { + super( + { + fi: ['format', 'algorithm', 'extractable', 'keyUsages'], + fo: ['key'], + i: [], + o: [], + }, + { + input: { + algorithm: { + ref: true, + }, + }, + output: { + key: { + ref: true, + }, + }, + }, + system, + ID_IMPORT_KEY + ) + } + + async f( + { format, data, algorithm, extractable, keyUsages }: I, + done: Done + ): Promise { + const { + api: { + crypto: { importKey }, + }, + } = this.__system + + let data_ = data.raw() as ArrayBuffer + let algorithm_ = algorithm.raw() as AlgorithmIdentifier + + const key_ = await importKey( + format, + data_, + algorithm_, + extractable, + keyUsages + ) + + const key = wrapCryptoKey(key_, this.__system) + + done({ key }) + } +} diff --git a/src/system/platform/api/crypto/ImportKey/spec.json b/src/system/platform/api/crypto/ImportKey/spec.json new file mode 100644 index 0000000000..8910a11efa --- /dev/null +++ b/src/system/platform/api/crypto/ImportKey/spec.json @@ -0,0 +1,50 @@ +{ + "name": "import key", + "inputs": { + "data": { + "type": "string", + "ref": true, + "icon": "key" + }, + "format": { + "type": "'raw'|'pkcs8'|'spki'|'jwk'" + }, + "algorithm": { + "type": "`J`", + "ref": true + }, + "extractable": { + "type": "boolean" + }, + "keyUsages": { + "type": "string[]", + "metadata": { + "examples": [ + "['encrypt','decrypt']", + "['encrypt','decrypt','sign','verify','deriveKey','deriveBits','wrapKey','unwrapKey']" + ] + } + }, + "done": { + "type": "any", + "defaultIgnored": true + } + }, + "outputs": { + "key": { + "type": "`CK`", + "ref": true + } + }, + "metadata": { + "icon": "lock", + "description": "parse cryto `key` given knowledge of `format`, `algorithm`, `extractable` and `keyUsages`", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "6fdcf0d8-39ce-4d63-ad68-97d25be769ab", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/RsaAlgorithm/index.ts b/src/system/platform/api/crypto/RsaAlgorithm/index.ts new file mode 100644 index 0000000000..0fcf437e09 --- /dev/null +++ b/src/system/platform/api/crypto/RsaAlgorithm/index.ts @@ -0,0 +1,60 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { J } from '../../../../../types/interface/J' +import { TA } from '../../../../../types/interface/TA' +import { wrapObject } from '../../../../../wrap/Object' +import { ID_RSA_ALGORITHM } from '../../../../_ids' + +export type I = { + name: string + modulusLength: number + publicExponent: TA & $ + hash: string +} + +export type O = { + algorithm: J & $ +} + +export default class RsaAlgorithm extends Holder { + constructor(system: System) { + super( + { + fi: ['name', 'modulusLength', 'publicExponent', 'hash'], + fo: ['algorithm'], + }, + { + input: { + publicExponent: { + ref: true, + }, + }, + output: { + algorithm: { + ref: true, + }, + }, + }, + system, + ID_RSA_ALGORITHM + ) + } + + async f( + { name, modulusLength, publicExponent, hash }: I, + done: Done + ): Promise { + const algorithm_ = { + name, + modulusLength, + publicExponent: publicExponent.raw(), + hash, + } + + const algorithm = wrapObject(algorithm_, this.__system) + + done({ algorithm }) + } +} diff --git a/src/system/platform/api/crypto/RsaAlgorithm/spec.json b/src/system/platform/api/crypto/RsaAlgorithm/spec.json new file mode 100644 index 0000000000..8a87eb6567 --- /dev/null +++ b/src/system/platform/api/crypto/RsaAlgorithm/spec.json @@ -0,0 +1,38 @@ +{ + "name": "rsa algorithm", + "inputs": { + "name": { + "type": "'RSASSA-PKCS1-v1_5'|'RSA-PSS'|'RSA-OAEP'" + }, + "modulusLength": { + "type": "number", + "metadata": { + "examples": ["2048", "4096"] + } + }, + "publicExponent": { + "type": "`TA`", + "ref": true + }, + "hash": { + "type": "'SHA-256'|'SHA-384'|'SHA-512'" + } + }, + "outputs": { + "algorithm": { + "type": "`J`", + "ref": true, + "icon": "brackets-curly" + } + }, + "metadata": { + "icon": "square-function", + "description": "instantiate an RSA algorithm parameter object", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "378b4049-860a-44a3-82f2-12a15499859c", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/Sign/index.ts b/src/system/platform/api/crypto/Sign/index.ts new file mode 100644 index 0000000000..7b6deffc6e --- /dev/null +++ b/src/system/platform/api/crypto/Sign/index.ts @@ -0,0 +1,76 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { AB } from '../../../../../types/interface/AB' +import { CK } from '../../../../../types/interface/CK' +import { J } from '../../../../../types/interface/J' +import { wrapArrayBuffer } from '../../../../../wrap/ArrayBuffer' +import { ID_ENCRYPT } from '../../../../_ids' + +export type I = { + key: CK & $ + algorithm: J & $ + data: AB & $ +} + +export type O = { + signature: AB & $ +} + +export default class Sign extends Holder { + constructor(system: System) { + super( + { + fi: ['opt', 'algorithm', 'key', 'data'], + fo: ['data'], + }, + { + input: { + algorithm: { + ref: true, + }, + key: { + ref: true, + }, + data: { + ref: true, + }, + }, + output: { + signature: { + ref: true, + }, + }, + }, + system, + ID_ENCRYPT + ) + } + + async f({ key, algorithm, data }: I, done: Done): Promise { + const { + api: { + crypto: { sign }, + }, + } = this.__system + + const key_ = (await key.raw()) as CryptoKey + const algorithm_ = (await algorithm.raw()) as AlgorithmIdentifier + const data_ = (await data.raw()) as ArrayBuffer + + let _signature: ArrayBuffer + + try { + _signature = (await sign(algorithm_, key_, data_)) as ArrayBuffer + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + const signature = wrapArrayBuffer(_signature, this.__system) + + done({ signature }) + } +} diff --git a/src/system/platform/api/crypto/Sign/spec.json b/src/system/platform/api/crypto/Sign/spec.json new file mode 100644 index 0000000000..f7786c8b8b --- /dev/null +++ b/src/system/platform/api/crypto/Sign/spec.json @@ -0,0 +1,42 @@ +{ + "name": "sign", + "inputs": { + "opt": { + "type": "{}" + }, + "key": { + "type": "`CK`", + "ref": true + }, + "algorithm": { + "type": "`J`", + "ref": true + }, + "data": { + "type": "`AB`|`TA`", + "ref": true + }, + "done": { + "type": "any", + "defaultIgnored": true + } + }, + "outputs": { + "signature": { + "type": "`AB`", + "ref": true, + "icon": "file-lock" + } + }, + "metadata": { + "icon": "lock", + "description": "cryptographically generate `signature` of `data` with `key`", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/sign", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "d3719453-ca94-4827-a6b6-5aa8f87b1dc5", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/crypto/Verify/index.ts b/src/system/platform/api/crypto/Verify/index.ts new file mode 100644 index 0000000000..fc8e78aeed --- /dev/null +++ b/src/system/platform/api/crypto/Verify/index.ts @@ -0,0 +1,73 @@ +import { $ } from '../../../../../Class/$' +import { Functional } from '../../../../../Class/Functional' +import { Done } from '../../../../../Class/Functional/Done' +import { System } from '../../../../../system' +import { AB } from '../../../../../types/interface/AB' +import { CK } from '../../../../../types/interface/CK' +import { J } from '../../../../../types/interface/J' +import { ID_VERIFY } from '../../../../_ids' + +export type I = { + key: CK & $ + algorithm: J & $ + signature: AB & $ + data: AB & $ +} + +export type O = { + valid: boolean +} + +export default class Verify extends Functional { + constructor(system: System) { + super( + { + i: ['opt', 'algorithm', 'key', 'signature', 'data'], + o: ['valid'], + }, + { + input: { + algorithm: { + ref: true, + }, + key: { + ref: true, + }, + data: { + ref: true, + }, + }, + }, + system, + ID_VERIFY + ) + } + + async f( + { key, algorithm, signature, data }: I, + done: Done + ): Promise { + const { + api: { + crypto: { verify }, + }, + } = this.__system + + const key_ = (await key.raw()) as CryptoKey + const algorithm_ = (await algorithm.raw()) as AlgorithmIdentifier + const data_ = (await data.raw()) as ArrayBuffer + const signature_ = (await signature.raw()) as ArrayBuffer + + let valid: boolean + + try { + valid = await verify(algorithm_, key_, signature_, data_) + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + done({ valid }) + } +} diff --git a/src/system/platform/api/crypto/Verify/spec.json b/src/system/platform/api/crypto/Verify/spec.json new file mode 100644 index 0000000000..7750849eaa --- /dev/null +++ b/src/system/platform/api/crypto/Verify/spec.json @@ -0,0 +1,40 @@ +{ + "name": "verify", + "inputs": { + "opt": { + "type": "{}" + }, + "key": { + "type": "`CK`", + "ref": true + }, + "algorithm": { + "type": "`J`", + "ref": true + }, + "signature": { + "type": "`AB`", + "ref": true + }, + "data": { + "type": "`AB`", + "ref": true + } + }, + "outputs": { + "valid": { + "type": "boolean" + } + }, + "metadata": { + "icon": "lock", + "description": "cryptographically verify signature", + "link": "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify", + "complexity": 3, + "tags": ["platform", "api", "crypto"] + }, + "id": "65180989-78be-414a-88c7-bf58af08e0f5", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/network/Socket/index.ts b/src/system/platform/api/network/Socket/index.ts index 1bf5e75cba..dfaa7289f6 100644 --- a/src/system/platform/api/network/Socket/index.ts +++ b/src/system/platform/api/network/Socket/index.ts @@ -19,7 +19,7 @@ export type O = { channel: CH & $ } -export type Socket_EE = { message: [any] } +export type Socket_EE = { message: [any]; close: [any, any] } export type SocketEvents = SemifunctionalEvents & Socket_EE @@ -81,7 +81,7 @@ export default class Socket extends Holder implements CH { this._web_socket.onclose = (event: CloseEvent) => { const { code, reason } = event - this.d() + channel.emit('close', code, reason) } } diff --git a/src/system/platform/api/peer/PeerReceiver/index.ts b/src/system/platform/api/peer/PeerReceiver/index.ts index 0cb9bea7ab..8dbffb3a5b 100644 --- a/src/system/platform/api/peer/PeerReceiver/index.ts +++ b/src/system/platform/api/peer/PeerReceiver/index.ts @@ -1,9 +1,6 @@ import { Peer } from '../../../../../api/peer/Peer' -import { FunctionalEvents } from '../../../../../Class/Functional' -import { Semifunctional } from '../../../../../Class/Semifunctional' -import { stringify } from '../../../../../spec/stringify' +import { Holder } from '../../../../../Class/Holder' import { System } from '../../../../../system' -import { Callback } from '../../../../../types/Callback' import { EE } from '../../../../../types/interface/EE' import { MS } from '../../../../../types/interface/MS' import { Unlisten } from '../../../../../types/Unlisten' @@ -11,28 +8,19 @@ import { wrapEventEmitter } from '../../../../../wrap/EventEmitter' import { wrapMediaStream } from '../../../../../wrap/MediaStream' import { ID_PEER_RECEIVER } from '../../../../_ids' -export interface I { +export interface I { offer: string close: any opt: RTCConfiguration } -export interface O { +export interface O { stream: MS answer: string emitter: EE } -export type PeerReceiver_EE = { message: [any] } - -export type PeerReceiverEvents = FunctionalEvents & - PeerReceiver_EE - -export default class PeerReceiver extends Semifunctional< - I, - O, - PeerReceiverEvents -> { +export default class PeerReceiver extends Holder { private _peer: Peer | null = null private _unlisten: Unlisten | undefined = undefined @@ -45,15 +33,24 @@ export default class PeerReceiver extends Semifunctional< super( { fi: ['opt'], - fo: ['answer'], - i: ['close', 'offer'], - o: ['stream', 'emitter'], + fo: [], + i: ['offer'], + o: ['stream', 'emitter', 'answer'], }, { input: {}, + output: { + emitter: { + ref: true, + }, + stream: { + ref: true, + }, + }, }, system, - ID_PEER_RECEIVER + ID_PEER_RECEIVER, + 'close' ) this.addListener('take_err', () => { @@ -67,7 +64,7 @@ export default class PeerReceiver extends Semifunctional< }) } - async f({ opt }: I) { + async f({ opt }: I) { this._peer = new Peer(this.__system, false, opt) this._setup_peer() @@ -107,32 +104,25 @@ export default class PeerReceiver extends Semifunctional< this._output.answer.push(answer) } - async onDataInputData(name: string, data: any): Promise { - if (name === 'close') { - this._disconnect() + async onIterDataInputData(name: keyof I, data: any): Promise { + super.onIterDataInputData(name, data) - this._backward('close') - } else if (name === 'offer') { + if (name === 'offer') { if (this._input.opt.active()) { this._output_answer(data) } } } - onDataInputDrop(name: string): void { - if (name === 'opt') { - if (!this._backwarding) { - this._disconnect() - } - } else if (name === 'offer') { + onIterDataInputDrop(name: keyof I | 'done'): void { + super.onIterDataInputDrop(name) + + if (name === 'offer') { if (this._flag_err_invalid_offer) { this._flag_err_invalid_offer = false - this.takeErr() - return } - this._forward_empty('emitter') this._forward_empty('stream') this._forward_empty('answer') @@ -145,22 +135,6 @@ export default class PeerReceiver extends Semifunctional< } } - private _send_data = (data: any, callback: Callback) => { - this._send({ type: 'data', data }, callback) - } - - private _send = (data: any, callback: Callback): void => { - if (this._connected) { - const message = stringify(data) - - this._peer.send(message) - - callback() - } else { - callback(undefined, 'peer not connected') - } - } - private _setup_peer = (): Unlisten => { const connect_listener = () => { // console.log('Receiver', 'Peer', 'connect') @@ -181,7 +155,7 @@ export default class PeerReceiver extends Semifunctional< const close_listener = () => { // console.log('Receiver', 'Peer', 'close') - this._disconnect() + this.d() } const message_listener = (message: string) => { @@ -223,11 +197,4 @@ export default class PeerReceiver extends Semifunctional< this._peer.removeListener('stop', stop_listener) } } - - private _disconnect = (): void => { - this.d() - - this._forward_empty('emitter') - this._forward_empty('stream') - } } diff --git a/src/system/platform/api/peer/PeerTransmitter/index.ts b/src/system/platform/api/peer/PeerTransmitter/index.ts index 7e171bf4fa..3e73d8bf38 100644 --- a/src/system/platform/api/peer/PeerTransmitter/index.ts +++ b/src/system/platform/api/peer/PeerTransmitter/index.ts @@ -1,7 +1,6 @@ import { Peer } from '../../../../../api/peer/Peer' import { $ } from '../../../../../Class/$' import { Holder } from '../../../../../Class/Holder' -import { stringify } from '../../../../../spec/stringify' import { System } from '../../../../../system' import { CH } from '../../../../../types/interface/CH' import { MS } from '../../../../../types/interface/MS' @@ -173,6 +172,8 @@ export default class PeerTransmitter extends Holder implements CH { } onDataInputDrop(name: string) { + // console.log('PeerTransmitter', 'onDataInputDrop', name) + if (name === 'answer') { if (this._flag_err_answer_without_offer) { this.takeErr() @@ -223,14 +224,12 @@ export default class PeerTransmitter extends Holder implements CH { this._peer.removeStream() } - private async _send_data(data: any) { - return this._send({ type: 'data', data }) + private async _send_data(data: string) { + return this._send(data) } - private async _send(data: any): Promise { - const message = stringify(data) - - this._peer.send(message) + private async _send(data: string): Promise { + this._peer.send(data) return } @@ -243,10 +242,8 @@ export default class PeerTransmitter extends Holder implements CH { const channel = new (class Channel extends $ implements CH { __: string[] = ['MS'] - async send(data: any): Promise { - const _data = stringify(data) - - peer.send(_data) + async send(data: string): Promise { + peer.send(data) return } diff --git a/src/system/platform/api/system/user/Decrypt/index.ts b/src/system/platform/api/system/user/Decrypt/index.ts deleted file mode 100644 index 5a4e39ebb7..0000000000 --- a/src/system/platform/api/system/user/Decrypt/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Functional } from '../../../../../../Class/Functional' -import { Done } from '../../../../../../Class/Functional/Done' -import { System } from '../../../../../../system' -import { ID_DECRYPT } from '../../../../../_ids' - -export type I = { - hash: string -} - -export type O = { - value: string -} - -export default class Decrypt extends Functional { - constructor(system: System) { - super( - { - i: ['hash'], - o: ['value'], - }, - {}, - system, - ID_DECRYPT - ) - } - - f({ hash }, done: Done): void { - done() - } -} diff --git a/src/system/platform/api/system/user/Decrypt/spec.json b/src/system/platform/api/system/user/Decrypt/spec.json deleted file mode 100644 index ce1f4913b4..0000000000 --- a/src/system/platform/api/system/user/Decrypt/spec.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "decrypt", - "inputs": { - "hash": { - "type": "string" - } - }, - "outputs": { - "value": { - "type": "string" - } - }, - "metadata": { - "icon": "table", - "description": "decrypt `hash` with user private key", - "complexity": 12, - "tags": ["platform", "api", "storage"], - "globals": ["LocalStorage"] - }, - "id": "08ff535a-93a7-403c-a1ef-c59cdb50ccf0", - "base": true, - "type": "`U`", - "system": true -} diff --git a/src/system/platform/api/system/user/PublicKey/index.ts b/src/system/platform/api/system/user/PublicKey/index.ts deleted file mode 100644 index 3fe98d0989..0000000000 --- a/src/system/platform/api/system/user/PublicKey/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Functional } from '../../../../../../Class/Functional' -import { Done } from '../../../../../../Class/Functional/Done' -import { System } from '../../../../../../system' -import { ID_PUBLIC_KEY } from '../../../../../_ids' - -export type I = { - any: any -} - -export type O = { - key: string -} - -export default class PublicKey extends Functional { - constructor(system: System) { - super( - { - i: ['any'], - o: ['key'], - }, - {}, - system, - ID_PUBLIC_KEY - ) - } - - f({ any }, done: Done): void { - done() - } -} diff --git a/src/system/platform/api/system/user/PublicKey/spec.json b/src/system/platform/api/system/user/PublicKey/spec.json deleted file mode 100644 index 514ebc6479..0000000000 --- a/src/system/platform/api/system/user/PublicKey/spec.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "public key", - "inputs": { - "any": { - "type": "any" - } - }, - "outputs": { - "key": { - "type": "string" - } - }, - "metadata": { - "icon": "table", - "description": "get user's public key", - "complexity": 12, - "tags": ["platform", "api", "storage"], - "globals": ["LocalStorage"] - }, - "id": "0f041192-1ff3-4094-93da-9264480ad5e2", - "base": true, - "type": "`U`", - "system": true -} diff --git a/src/system/platform/api/system/user/Sign/index.ts b/src/system/platform/api/system/user/Sign/index.ts deleted file mode 100644 index ad9bb3c0fe..0000000000 --- a/src/system/platform/api/system/user/Sign/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Functional } from '../../../../../../Class/Functional' -import { Done } from '../../../../../../Class/Functional/Done' -import { System } from '../../../../../../system' -import { ID_SIGN_0 } from '../../../../../_ids' - -export type I = { - value: string -} - -export type O = { - hash: string -} - -export default class Sign extends Functional { - constructor(system: System) { - super( - { - i: ['value'], - o: ['hash'], - }, - {}, - system, - ID_SIGN_0 - ) - } - - f({ value }, done: Done): void { - done() - } -} diff --git a/src/system/platform/api/system/user/Sign/spec.json b/src/system/platform/api/system/user/Sign/spec.json deleted file mode 100644 index 01a6399396..0000000000 --- a/src/system/platform/api/system/user/Sign/spec.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "sign", - "inputs": { - "value": { - "type": "string" - } - }, - "outputs": { - "hash": { - "type": "string" - } - }, - "metadata": { - "icon": "table", - "description": "sign `value` with user's private key", - "complexity": 12, - "tags": ["platform", "api", "storage"], - "globals": ["LocalStorage"] - }, - "id": "58846eae-1650-41e7-ad42-a75b9c32332a", - "base": true, - "type": "`U`", - "system": true -} diff --git a/src/system/platform/api/text/TextDecoder/index.ts b/src/system/platform/api/text/TextDecoder/index.ts new file mode 100644 index 0000000000..0bd6b5743d --- /dev/null +++ b/src/system/platform/api/text/TextDecoder/index.ts @@ -0,0 +1,62 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { TD } from '../../../../../types/interface/TD' +import { wrapTextDecoder } from '../../../../../wrap/TextDecoder' +import { ID_TEXT_DECODER } from '../../../../_ids' + +export interface I { + label: string + opt: TextDecoderOptions +} + +export interface O { + decoder: TD & $ +} + +export default class TextDecoder_ extends Holder { + constructor(system: System) { + super( + { + fi: ['label', 'opt'], + fo: ['decoder'], + i: [], + o: [], + }, + { + output: { + decoder: { + ref: true, + }, + }, + }, + system, + ID_TEXT_DECODER + ) + } + + f({ label, opt }: I, done: Done) { + const { + api: { + text: { TextDecoder }, + }, + } = this.__system + + let decoder_: TextDecoder + + try { + decoder_ = new TextDecoder(label, opt) + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + const decoder = wrapTextDecoder(decoder_, this.__system) + + done({ + decoder, + }) + } +} diff --git a/src/system/platform/api/text/TextDecoder/spec.json b/src/system/platform/api/text/TextDecoder/spec.json new file mode 100644 index 0000000000..a573cf4e89 --- /dev/null +++ b/src/system/platform/api/text/TextDecoder/spec.json @@ -0,0 +1,31 @@ +{ + "name": "text decoder", + "inputs": { + "label": { + "type": "'utf-8'" + }, + "opt": { + "type": "{fatal?:boolean,ignoreBOM?:boolean}" + }, + "done": { + "type": "any", + "defaultIgnored": true + } + }, + "outputs": { + "decoder": { + "type": "`TD`", + "ref": true + } + }, + "metadata": { + "icon": "square", + "description": "`decoder` takes a stream of bytes as input and emits a stream of code points", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "a64f3008-ad0d-401b-8294-cf222a5a4ca7", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/text/TextEncoder/index.ts b/src/system/platform/api/text/TextEncoder/index.ts new file mode 100644 index 0000000000..8c2d2bb99c --- /dev/null +++ b/src/system/platform/api/text/TextEncoder/index.ts @@ -0,0 +1,59 @@ +import { $ } from '../../../../../Class/$' +import { Done } from '../../../../../Class/Functional/Done' +import { Holder } from '../../../../../Class/Holder' +import { System } from '../../../../../system' +import { TE } from '../../../../../types/interface/TE' +import { wrapTextEncoder } from '../../../../../wrap/TextEncoder' +import { ID_TEXT_ENCODER } from '../../../../_ids' + +export interface I { + opt: TextEncoderCommon +} + +export interface O { + encoder: TE & $ +} + +export default class TextEncoder_ extends Holder { + constructor(system: System) { + super( + { + fi: ['opt'], + fo: ['encoder'], + }, + { + output: { + encoder: { + ref: true, + }, + }, + }, + system, + ID_TEXT_ENCODER + ) + } + + f({ opt }: I, done: Done) { + const { + api: { + text: { TextEncoder }, + }, + } = this.__system + + let encoder_: TextEncoder + + try { + encoder_ = new TextEncoder() + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + const encoder = wrapTextEncoder(encoder_, this.__system) + + done({ + encoder, + }) + } +} diff --git a/src/system/platform/api/text/TextEncoder/spec.json b/src/system/platform/api/text/TextEncoder/spec.json new file mode 100644 index 0000000000..3cd9f7b835 --- /dev/null +++ b/src/system/platform/api/text/TextEncoder/spec.json @@ -0,0 +1,31 @@ +{ + "name": "text encoder", + "inputs": { + "opt": { + "type": "{encoding:string}", + "metadata": { + "examples": ["{encoding:'utf8'}"] + } + }, + "done": { + "type": "any", + "defaultIgnored": true + } + }, + "outputs": { + "encoder": { + "type": "`TE`", + "ref": true + } + }, + "metadata": { + "icon": "square", + "description": "`encoder` takes a stream of code points as input and emits a stream of UTF-8 bytes", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "ffc86129-e199-4ffb-bea0-f7307e62eafc", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/text/method/Decode/index.ts b/src/system/platform/api/text/method/Decode/index.ts new file mode 100644 index 0000000000..2d449f3d13 --- /dev/null +++ b/src/system/platform/api/text/method/Decode/index.ts @@ -0,0 +1,56 @@ +import { $ } from '../../../../../../Class/$' +import { Functional } from '../../../../../../Class/Functional' +import { Done } from '../../../../../../Class/Functional/Done' +import { System } from '../../../../../../system' +import { AB } from '../../../../../../types/interface/AB' +import { TD } from '../../../../../../types/interface/TD' +import { ID_DECODE_0 } from '../../../../../_ids' + +export interface I { + opt: TextDecodeOptions + decoder: TD & $ + data: AB & $ +} + +export interface O { + text: string +} + +export default class Decode extends Functional { + constructor(system: System) { + super( + { + i: ['opt', 'data', 'decoder'], + o: ['text'], + }, + { + input: { + data: { + ref: true, + }, + decoder: { + ref: true, + }, + }, + }, + system, + ID_DECODE_0 + ) + } + + async f({ opt, decoder, data }: I, done: Done) { + let text: string + + const data_ = (await data.raw()) as ArrayBuffer + + try { + text = decoder.decode(opt, data_) + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + done({ text }) + } +} diff --git a/src/system/platform/api/text/method/Decode/spec.json b/src/system/platform/api/text/method/Decode/spec.json new file mode 100644 index 0000000000..6d8cc9cb9a --- /dev/null +++ b/src/system/platform/api/text/method/Decode/spec.json @@ -0,0 +1,32 @@ +{ + "name": "decode", + "inputs": { + "decoder": { + "type": "`TD`", + "ref": true + }, + "opt": { + "type": "object" + }, + "data": { + "type": "`AB`", + "ref": true + } + }, + "outputs": { + "text": { + "type": "string", + "icon": "text" + } + }, + "metadata": { + "icon": "tilde", + "description": "decode binary `data` into `text`", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "24b50c35-e558-4911-a3e3-8ee37777b1f5", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/text/method/Encode/index.ts b/src/system/platform/api/text/method/Encode/index.ts new file mode 100644 index 0000000000..73a0a482e4 --- /dev/null +++ b/src/system/platform/api/text/method/Encode/index.ts @@ -0,0 +1,62 @@ +import { Done } from '../../../../../../Class/Functional/Done' +import { Holder } from '../../../../../../Class/Holder' +import { System } from '../../../../../../system' +import { TA } from '../../../../../../types/interface/TA' +import { TE } from '../../../../../../types/interface/TE' +import { wrapUint8Array } from '../../../../../../wrap/Array' +import { ID_ENCODE_0 } from '../../../../../_ids' + +export interface I { + opt: object + text: string + encoder: TE +} + +export interface O { + data: TA +} + +export default class Encode extends Holder { + constructor(system: System) { + super( + { + fi: ['opt', 'text', 'encoder'], + fo: ['data'], + i: [], + o: [], + }, + { + input: { + encoder: { + ref: true, + }, + }, + output: { + data: { + ref: true, + }, + }, + }, + system, + ID_ENCODE_0 + ) + } + + async f({ opt, text, encoder }: I, done: Done) { + let data_: Uint8Array + + try { + data_ = encoder.encode(opt, text) + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + const data = wrapUint8Array(data_, this.__system) + + done({ + data, + }) + } +} diff --git a/src/system/platform/api/text/method/Encode/spec.json b/src/system/platform/api/text/method/Encode/spec.json new file mode 100644 index 0000000000..571c168a24 --- /dev/null +++ b/src/system/platform/api/text/method/Encode/spec.json @@ -0,0 +1,35 @@ +{ + "name": "encode", + "inputs": { + "encoder": { + "type": "`TE`", + "ref": true + }, + "opt": { + "type": "object" + }, + "text": { + "type": "string" + }, + "done": { + "type": "any" + } + }, + "outputs": { + "data": { + "type": "`TA`", + "ref": true, + "icon": "hash" + } + }, + "metadata": { + "icon": "tilde", + "description": "encode `text` into binary `data`", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "12de8298-28f6-4b2b-8962-51cb41e5f99b", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/api/text/method/Encode0/index.ts b/src/system/platform/api/text/method/Encode0/index.ts new file mode 100644 index 0000000000..2d090caec5 --- /dev/null +++ b/src/system/platform/api/text/method/Encode0/index.ts @@ -0,0 +1,66 @@ +import { $ } from '../../../../../../Class/$' +import { Done } from '../../../../../../Class/Functional/Done' +import { Holder } from '../../../../../../Class/Holder' +import { System } from '../../../../../../system' +import { AB } from '../../../../../../types/interface/AB' +import { TA } from '../../../../../../types/interface/TA' +import { TE } from '../../../../../../types/interface/TE' +import { wrapUint8Array } from '../../../../../../wrap/Array' +import { ID_ENCODE_1 } from '../../../../../_ids' + +export interface I { + opt: object + text: AB & $ + encoder: TE +} + +export interface O { + data: TA +} + +export default class Encode0 extends Holder { + constructor(system: System) { + super( + { + fi: ['opt', 'text', 'encoder'], + fo: ['data'], + i: [], + o: [], + }, + { + input: { + encoder: { + ref: true, + }, + }, + output: { + data: { + ref: true, + }, + }, + }, + system, + ID_ENCODE_1 + ) + } + + async f({ opt, text, encoder }: I, done: Done) { + let data_: Uint8Array + + try { + const text_ = text.raw() as Uint8Array + + data_ = encoder.encode(opt, text_) + } catch (err) { + done(undefined, err.message.toLowerCase()) + + return + } + + const data = wrapUint8Array(data_, this.__system) + + done({ + data, + }) + } +} diff --git a/src/system/platform/api/text/method/Encode0/spec.json b/src/system/platform/api/text/method/Encode0/spec.json new file mode 100644 index 0000000000..8a609f3d5d --- /dev/null +++ b/src/system/platform/api/text/method/Encode0/spec.json @@ -0,0 +1,36 @@ +{ + "name": "encode", + "inputs": { + "encoder": { + "type": "`TE`", + "ref": true + }, + "opt": { + "type": "object" + }, + "text": { + "type": "`AB`", + "ref": true + }, + "done": { + "type": "any" + } + }, + "outputs": { + "data": { + "type": "`AB`", + "ref": true, + "icon": "hash" + } + }, + "metadata": { + "icon": "tilde", + "description": "encode `text` into binary `data`", + "complexity": 3, + "tags": ["platform", "array", "typed"] + }, + "id": "56125930-6819-4c03-87c6-3fa042824715", + "base": true, + "type": "`U`", + "system": true +} diff --git a/src/system/platform/component/app/Editor/Component.ts b/src/system/platform/component/app/Editor/Component.ts index 7aed9970a5..9bc755b755 100644 --- a/src/system/platform/component/app/Editor/Component.ts +++ b/src/system/platform/component/app/Editor/Component.ts @@ -760,9 +760,16 @@ export const describeArrowShape = (shape: Shape, r: number): string => { } const saveToUnitFile = async ( + system: System, fileHandle: FileSystemFileHandle, bundle: BundleSpec ) => { + const { + api: { + text: { TextEncoder }, + }, + } = system + const json = JSON.stringify(bundle, null, 2) try { @@ -996,6 +1003,8 @@ export default class Editor extends Element { this._editor.addEventListeners([ makeCustomListener('data_removed', ({ datumId, specId }) => { + // console.log('data_removed', { datumId, specId }) + const { specs } = this._registry if (this._spec_id_to_file_name[specId]) { @@ -1003,10 +1012,13 @@ export default class Editor extends Element { removeDatum({ datumId }, spec) - this._registry.setSpec(specId, spec) + // this._sync_spec_file(specId, spec, specs) + // this._registry.setSpec(specId, spec) } }), makeCustomListener('data_added', ({ datumId, specId, value }) => { + // console.log('data_added', { datumId, specId, value }) + const { specs } = this._registry if (this._spec_id_to_file_name[specId]) { @@ -1014,7 +1026,8 @@ export default class Editor extends Element { setDatum({ datumId, value }, spec) - this._registry.setSpec(specId, spec) + // this._sync_spec_file(specId, spec, specs) + // this._registry.setSpec(specId, spec) } }), ]) @@ -1150,7 +1163,7 @@ export default class Editor extends Element { this._spec_id_to_file_name[spec_id] = fileName } - await saveToUnitFile(fileHandle, bundle_) + await saveToUnitFile(this.$system, fileHandle, bundle_) } }, 1 @@ -3694,7 +3707,7 @@ export class Editor_ extends Element { } else if (file.type.startsWith('video/')) { return this._drop_video_file(file, position) } else if ( - file.type.startsWith('"text/plain"') || + file.type.startsWith('text/plain') || file.type.startsWith('application/json') ) { const text = await readFileAsText(file) @@ -3933,6 +3946,12 @@ export class Editor_ extends Element { } private _read_bundle_file = async (file: File): Promise => { + const { + api: { + text: { TextDecoder }, + }, + } = this.$system + let json: string if (file.name.endsWith('.unit')) { @@ -40094,6 +40113,10 @@ export class Editor_ extends Element { int_node_id ) + if (!path) { + return + } + const start_marker_d = this._get_pin_default_marker( type, ext_node_id, @@ -46566,57 +46589,57 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K, pin: Pin, opt: PinOpt) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, setInputIgnored: function ( name: K, ignore?: boolean ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, getOutput: function ( name: K ): Pin { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, push: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushInput: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushOutput: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, takeInput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, takeOutput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, take: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, takeAll: function (): Dict { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peakInput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peakOutput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peak: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, renamePin: function < T extends IO, @@ -46624,16 +46647,16 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K, newName: K): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, renameInput: function ( name: K, newName: K ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, renameOutput: function (name: string, newName: string): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefPinNamed: function < T extends IO, @@ -46641,30 +46664,30 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefInputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefOutputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasPinNamed: function (type: IO, name: string): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasInputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasOutputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, } @@ -50116,72 +50139,72 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K, pin: Pin, opt: PinOpt) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, setPinIgnored: function (type: IO, name: string, ignored: boolean): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, setInputIgnored: function ( name: K, ignore?: boolean ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, getRefOutputs: function (): Pins> { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, getOutput: function ( name: K ): Pin { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, push: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushInput: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushAllInput: function (data: Partial): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushOutput: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushAllOutput: function (data: Partial): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushAll: function (data: Partial): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, takeInput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, takeOutput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, take: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, takeAll: function (): Dict { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peakInput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peakOutput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peak: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, renamePin: function < T extends IO, @@ -50189,16 +50212,16 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K, newName: K): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, renameInput: function ( name: K, newName: K ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, renameOutput: function (name: string, newName: string): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefPinNamed: function < T extends IO, @@ -50206,27 +50229,27 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefInputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefOutputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasInputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasOutputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, } @@ -50430,72 +50453,72 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K, pin: Pin, opt: PinOpt) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, setPinIgnored: function (type: IO, name: string, ignored: boolean): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, setInputIgnored: function ( name: K, ignore?: boolean ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, getOutput: function ( name: K ): Pin { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, push: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushInput: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushAllInput: function (data: Partial): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushOutput: function ( name: K, data: any ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushAllOutput: function (data: Partial): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, pushAll: function (data: Partial): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, takeInput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, takeOutput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, take: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peakInput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peakOutput: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peak: function (name: K) { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peakAllOutput: function (): Dict { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, peakAll: function (): Dict { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, renamePin: function < T extends IO, @@ -50503,13 +50526,13 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K, newName: K): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, renameInput: function ( name: K, newName: K ): void { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefPinNamed: function < T extends IO, @@ -50517,27 +50540,27 @@ export class Editor_ extends Element { ? string | number | symbol : string | number | symbol, >(type: T, name: K): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefInputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasRefOutputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasInputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, hasOutputNamed: function ( name: K ): boolean { - throw new Error('Function not implemented.') + throw new MethodNotImplementedError() }, } @@ -51879,7 +51902,7 @@ export class Editor_ extends Element { if (this._last_save_file_handle) { const writableStream = await this._last_save_file_handle.createWritable() - await saveToUnitFile(this._last_save_file_handle, bundle) + await saveToUnitFile(this.$system, this._last_save_file_handle, bundle) } else { throw new Error('cannot save silently without previous file handler') } @@ -52063,7 +52086,7 @@ export class Editor_ extends Element { if ( (datum_pin_node_id && node_ids.includes(datum_pin_node_id)) || - datum_plug_node_id + (datum_plug_node_id && node_ids.includes(datum_plug_node_id)) ) { // } else { @@ -52276,6 +52299,8 @@ export class Editor_ extends Element { const text = await item.getType('text/plain') this._drop_file(text, position) + + return } } } catch (err) { @@ -57084,7 +57109,6 @@ export class Editor_ extends Element { private _on_set_unit_pin_data = (data: GraphSetUnitPinDataMomentData) => { // console.log('Graph', '_on_set_unit_pin_data', data) - // TODO } private _on_bulk_edit = (data: GraphBulkEditData) => { diff --git a/src/system/platform/method/object/Set/index.ts b/src/system/platform/method/object/Set/index.ts index 232bf238ef..233037be4c 100644 --- a/src/system/platform/method/object/Set/index.ts +++ b/src/system/platform/method/object/Set/index.ts @@ -2,7 +2,7 @@ import { Functional } from '../../../../../Class/Functional' import { Done } from '../../../../../Class/Functional/Done' import { System } from '../../../../../system' import { J } from '../../../../../types/interface/J' -import { ID_SET_0 } from '../../../../_ids' +import { ID_SET_1 } from '../../../../_ids' export interface I { obj: J @@ -29,7 +29,7 @@ export default class Set extends Functional, O> { }, }, system, - ID_SET_0 + ID_SET_1 ) } diff --git a/src/system/platform/method/object/Set0/index.ts b/src/system/platform/method/object/Set0/index.ts index 9b407a0ff0..28e7412e73 100644 --- a/src/system/platform/method/object/Set0/index.ts +++ b/src/system/platform/method/object/Set0/index.ts @@ -3,7 +3,7 @@ import { Done } from '../../../../../Class/Functional/Done' import { Holder } from '../../../../../Class/Holder' import { System } from '../../../../../system' import { J } from '../../../../../types/interface/J' -import { ID_SET_1 } from '../../../../_ids' +import { ID_SET_2 } from '../../../../_ids' export interface I { obj: J @@ -36,7 +36,7 @@ export default class Set0 extends Holder, O> { }, }, system, - ID_SET_1 + ID_SET_2 ) } diff --git a/src/types/interface/AB.ts b/src/types/interface/AB.ts new file mode 100644 index 0000000000..7559d75de4 --- /dev/null +++ b/src/types/interface/AB.ts @@ -0,0 +1,3 @@ +export interface AB { + arrayBuffer(): Promise +} diff --git a/src/types/interface/CK.ts b/src/types/interface/CK.ts new file mode 100644 index 0000000000..72f88794e1 --- /dev/null +++ b/src/types/interface/CK.ts @@ -0,0 +1 @@ +export interface CK {} diff --git a/src/types/interface/TA.ts b/src/types/interface/TA.ts index b3db6bd999..fccc1eb305 100644 --- a/src/types/interface/TA.ts +++ b/src/types/interface/TA.ts @@ -1,3 +1,6 @@ -export interface TA { +import { A } from './A' + +export interface TA extends A { set(array: Uint8ClampedArray, offset: number): void + buffer(): ArrayBuffer } diff --git a/src/types/interface/TD.ts b/src/types/interface/TD.ts new file mode 100644 index 0000000000..8ce7cf59c7 --- /dev/null +++ b/src/types/interface/TD.ts @@ -0,0 +1,3 @@ +export interface TD { + decode(opt: TextDecodeOptions, data: ArrayBuffer): string +} diff --git a/src/types/interface/TE.ts b/src/types/interface/TE.ts new file mode 100644 index 0000000000..71d31895fc --- /dev/null +++ b/src/types/interface/TE.ts @@ -0,0 +1,3 @@ +export interface TE { + encode(opt: {}, text: string | ArrayBuffer): Uint8Array +} diff --git a/src/types/interface/async/$AB.ts b/src/types/interface/async/$AB.ts new file mode 100644 index 0000000000..a45fce8395 --- /dev/null +++ b/src/types/interface/async/$AB.ts @@ -0,0 +1,15 @@ +import { Callback } from '../../Callback' + +export const AB_METHOD_CALL = ['arrayBuffer'] +export const AB_METHOD_WATCH = [] +export const AB_METHOD_REF = [] + +export interface $AB_C { + $arrayBuffer(data: {}, callback: Callback): void +} + +export interface $AB_W {} + +export interface $AB_R {} + +export interface $AB extends $AB_C, $AB_W, $AB_R {} diff --git a/src/types/interface/async/$CK.ts b/src/types/interface/async/$CK.ts new file mode 100644 index 0000000000..1d47b33c3e --- /dev/null +++ b/src/types/interface/async/$CK.ts @@ -0,0 +1,11 @@ +export const CK_METHOD_CALL = [] +export const CK_METHOD_WATCH = [] +export const CK_METHOD_REF = [] + +export interface $CK_C {} + +export interface $CK_W {} + +export interface $CK_R {} + +export interface $CK extends $CK_C, $CK_W, $CK_R {} diff --git a/src/types/interface/async/$TD.ts b/src/types/interface/async/$TD.ts new file mode 100644 index 0000000000..b5bfac247b --- /dev/null +++ b/src/types/interface/async/$TD.ts @@ -0,0 +1,15 @@ +import { Callback } from '../../Callback' + +export const TD_METHOD_CALL = ['decode'] +export const TD_METHOD_WATCH = [] +export const TD_METHOD_REF = [] + +export interface $TD_C { + $decode(data: TextDecodeOptions, callback: Callback): void +} + +export interface $TD_W {} + +export interface $TD_R {} + +export interface $TD extends $TD_C, $TD_W, $TD_R {} diff --git a/src/types/interface/async/$TE.ts b/src/types/interface/async/$TE.ts new file mode 100644 index 0000000000..24a578a635 --- /dev/null +++ b/src/types/interface/async/$TE.ts @@ -0,0 +1,18 @@ +import { Callback } from '../../Callback' + +export const TE_METHOD_CALL = ['encode'] +export const TE_METHOD_WATCH = [] +export const TE_METHOD_REF = [] + +export interface $TE_C { + $encode( + data: { opt: {}; text: string | ArrayBuffer }, + callback: Callback + ): void +} + +export interface $TE_W {} + +export interface $TE_R {} + +export interface $TE extends $TE_C, $TE_W, $TE_R {} diff --git a/src/wrap/Array.ts b/src/wrap/Array.ts index e2ea8bf0f6..ce284383f7 100644 --- a/src/wrap/Array.ts +++ b/src/wrap/Array.ts @@ -4,15 +4,13 @@ import { MethodNotImplementedError } from '../exception/MethodNotImplementedErro import { System } from '../system' import { A } from '../types/interface/A' import { TA } from '../types/interface/TA' +import { V } from '../types/interface/V' export function wrapSharedRefArrayInterface( - data: SharedRef, - _system: System + data: SharedRef ): A { return { append(a: T): Promise { - const b: any[] = [] - data.current.push(a) return @@ -63,10 +61,25 @@ export function wrapArray(array: T[], system: System): A & $ { export function wrapUint8Array( array: Uint8Array | Uint8ClampedArray, system: System -): A & TA & $ { - const _array = new (class Array extends $ implements A, TA { +): V & A & TA & $ { + const _array = new (class Array + extends $ + implements V, A, TA + { __: string[] = ['A'] + buffer(): ArrayBuffer { + return array.buffer + } + + async read(): Promise { + return [...array] + } + + async write(data: number[]): Promise { + throw new Error('read only') + } + append(a: number): Promise { array[array.length] = a diff --git a/src/wrap/ArrayBuffer.ts b/src/wrap/ArrayBuffer.ts new file mode 100644 index 0000000000..16686df309 --- /dev/null +++ b/src/wrap/ArrayBuffer.ts @@ -0,0 +1,22 @@ +import { $ } from '../Class/$' +import { System } from '../system' +import { AB } from '../types/interface/AB' + +export function wrapArrayBuffer( + arrayBuffer: ArrayBuffer, + system: System +): AB & $ { + const _array = new (class Array extends $ implements AB { + __: string[] = ['AB'] + + async arrayBuffer(): Promise { + return arrayBuffer + } + + raw() { + return arrayBuffer + } + })(system) + + return _array +} diff --git a/src/wrap/CryptoKey.ts b/src/wrap/CryptoKey.ts new file mode 100644 index 0000000000..7c317eea14 --- /dev/null +++ b/src/wrap/CryptoKey.ts @@ -0,0 +1,18 @@ +import { $ } from '../Class/$' +import { System } from '../system' +import { CK } from '../types/interface/CK' + +export function wrapCryptoKey( + cryptoKey: CryptoKey | CryptoKeyPair, + system: System +): CK & $ { + const stream = new (class Stream extends $ implements CK { + __: string[] = ['CK'] + + raw() { + return cryptoKey + } + })(system) + + return stream +} diff --git a/src/wrap/Object.ts b/src/wrap/Object.ts index 377836d2d6..203b4f24a0 100644 --- a/src/wrap/Object.ts +++ b/src/wrap/Object.ts @@ -1,43 +1,59 @@ +import { $ } from '../Class/$' import { Object_ } from '../Object' import { ObjectUpdateType } from '../ObjectUpdateType' import { SharedRef } from '../SharefRef' -import { MethodNotImplementedError } from '../exception/MethodNotImplementedError' import { System } from '../system' import { Dict } from '../types/Dict' -import { Unlisten } from '../types/Unlisten' import { J } from '../types/interface/J' +import { Unlisten } from '../types/Unlisten' + +export function wrapSharedRef>(data: SharedRef): J { + const _data = new Object_(data.current) + + return _data +} + +export function wrapObject( + data: T, + system: System +): J & $ { + const _data = new Object_(data) -export function wrapSharedRef>( - data: SharedRef, - _system: System -): J { - const _data = new Object_(data) + const _obj = new (class Array extends $ implements J { + __: string[] = ['J'] - return { get(name: K): Promise { - throw new MethodNotImplementedError() - }, + return _data.get(name) + } + set(name: K, data: T[K]): Promise { - return _data.deepSet(['current', name] as string[], data) - }, + return _data.set(name, data) + } + delete(name: K): Promise { - throw new MethodNotImplementedError() - }, + return _data.delete(name) + } + hasKey(name: K): Promise { - throw new MethodNotImplementedError() - }, + return _data.hasKey(name) + } + keys(): Promise { - throw new MethodNotImplementedError() - }, + return _data.keys() + } + deepGet(path: string[]): Promise { - throw new MethodNotImplementedError() - }, + return _data.deepGet(path) + } + deepSet(path: string[], data: any): Promise { - throw new MethodNotImplementedError() - }, + return _data.deepSet(path, data) + } + deepDelete(path: string[]): Promise { - throw new MethodNotImplementedError() - }, + return _data.deepDelete(path) + } + subscribe( path: string[], key: string, @@ -48,7 +64,13 @@ export function wrapSharedRef>( data: any ) => void ): Unlisten { - return _data.subscribe(['current', ...path], key, listener) - }, - } + return _data.subscribe(path, key, listener) + } + + raw() { + return data + } + })(system) + + return _obj } diff --git a/src/wrap/Socket.ts b/src/wrap/Socket.ts index a68e12ae0d..702d18fcad 100644 --- a/src/wrap/Socket.ts +++ b/src/wrap/Socket.ts @@ -5,6 +5,7 @@ import { CH } from '../types/interface/CH' export type SocketEE = { message: [string] + close: [number, string] } export type SocketEvents<_EE extends Dict> = $Events<_EE & SocketEE> & diff --git a/src/wrap/TextDecoder.ts b/src/wrap/TextDecoder.ts new file mode 100644 index 0000000000..020126c623 --- /dev/null +++ b/src/wrap/TextDecoder.ts @@ -0,0 +1,15 @@ +import { $ } from '../Class/$' +import { System } from '../system' +import { TD } from '../types/interface/TD' + +export function wrapTextDecoder(decoder: TextDecoder, system: System): TD & $ { + const ctx = new (class Node extends $ implements TD { + __: string[] = ['TD'] + + decode(opt: TextDecodeOptions, data: ArrayBuffer): string { + return decoder.decode(data, opt) + } + })(system) + + return ctx +} diff --git a/src/wrap/TextEncoder.ts b/src/wrap/TextEncoder.ts new file mode 100644 index 0000000000..8848475daf --- /dev/null +++ b/src/wrap/TextEncoder.ts @@ -0,0 +1,15 @@ +import { $ } from '../Class/$' +import { System } from '../system' +import { TE } from '../types/interface/TE' + +export function wrapTextEncoder(encoder: TextEncoder, system: System): TE & $ { + const ctx = new (class Node extends $ implements TE { + __: string[] = ['TD'] + + encode(opt: {}, text: string): Uint8Array { + return encoder.encode(text) + } + })(system) + + return ctx +}