@ny4n/chord 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +261 -2
- package/dist/api.d.ts +20 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +77 -0
- package/dist/api.js.map +1 -0
- package/dist/bundler.d.ts +6 -0
- package/dist/bundler.d.ts.map +1 -0
- package/dist/bundler.js +3 -0
- package/dist/bundler.js.map +1 -0
- package/dist/context/index.d.ts +24 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +97 -0
- package/dist/context/index.js.map +1 -0
- package/dist/delta/apply-immutable-trusted.d.ts +4 -0
- package/dist/delta/apply-immutable-trusted.d.ts.map +1 -0
- package/dist/delta/apply-immutable-trusted.js +127 -0
- package/dist/delta/apply-immutable-trusted.js.map +1 -0
- package/dist/delta/core.d.ts +108 -0
- package/dist/delta/core.d.ts.map +1 -0
- package/dist/delta/core.js +645 -0
- package/dist/delta/core.js.map +1 -0
- package/dist/delta/diff.d.ts +5 -0
- package/dist/delta/diff.d.ts.map +1 -0
- package/dist/delta/diff.js +433 -0
- package/dist/delta/diff.js.map +1 -0
- package/dist/delta/draft.d.ts +5 -0
- package/dist/delta/draft.d.ts.map +1 -0
- package/dist/delta/draft.js +2 -0
- package/dist/delta/draft.js.map +1 -0
- package/dist/delta/index.d.ts +5 -0
- package/dist/delta/index.d.ts.map +1 -0
- package/dist/delta/index.js +6 -0
- package/dist/delta/index.js.map +1 -0
- package/dist/delta/revision-validator.d.ts +7 -0
- package/dist/delta/revision-validator.d.ts.map +1 -0
- package/dist/delta/revision-validator.js +71 -0
- package/dist/delta/revision-validator.js.map +1 -0
- package/dist/delta/tracker.d.ts +26 -0
- package/dist/delta/tracker.d.ts.map +1 -0
- package/dist/delta/tracker.js +2069 -0
- package/dist/delta/tracker.js.map +1 -0
- package/dist/facets/host.d.ts +12 -0
- package/dist/facets/host.d.ts.map +1 -0
- package/dist/facets/host.js +763 -0
- package/dist/facets/host.js.map +1 -0
- package/dist/facets/loader.d.ts +3 -0
- package/dist/facets/loader.d.ts.map +1 -0
- package/dist/facets/loader.js +5 -0
- package/dist/facets/loader.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +10 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +124 -0
- package/dist/json.js.map +1 -0
- package/dist/node/bundle-loader.d.ts +30 -0
- package/dist/node/bundle-loader.d.ts.map +1 -0
- package/dist/node/bundle-loader.js +377 -0
- package/dist/node/bundle-loader.js.map +1 -0
- package/dist/node/bundle.d.ts +26 -0
- package/dist/node/bundle.d.ts.map +1 -0
- package/dist/node/bundle.js +183 -0
- package/dist/node/bundle.js.map +1 -0
- package/dist/node/manifest.d.ts +36 -0
- package/dist/node/manifest.d.ts.map +1 -0
- package/dist/node/manifest.js +6 -0
- package/dist/node/manifest.js.map +1 -0
- package/dist/node/package.d.ts +15 -0
- package/dist/node/package.d.ts.map +1 -0
- package/dist/node/package.js +199 -0
- package/dist/node/package.js.map +1 -0
- package/dist/node.d.ts +5 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +3 -0
- package/dist/node.js.map +1 -0
- package/dist/services/consumer.d.ts +11 -0
- package/dist/services/consumer.d.ts.map +1 -0
- package/dist/services/consumer.js +585 -0
- package/dist/services/consumer.js.map +1 -0
- package/dist/services/errors.d.ts +8 -0
- package/dist/services/errors.d.ts.map +1 -0
- package/dist/services/errors.js +22 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/handle.d.ts +15 -0
- package/dist/services/handle.d.ts.map +1 -0
- package/dist/services/handle.js +101 -0
- package/dist/services/handle.js.map +1 -0
- package/dist/services/instances.d.ts +26 -0
- package/dist/services/instances.d.ts.map +1 -0
- package/dist/services/instances.js +140 -0
- package/dist/services/instances.js.map +1 -0
- package/dist/services/loopback.d.ts +5 -0
- package/dist/services/loopback.d.ts.map +1 -0
- package/dist/services/loopback.js +15 -0
- package/dist/services/loopback.js.map +1 -0
- package/dist/services/provider.d.ts +37 -0
- package/dist/services/provider.d.ts.map +1 -0
- package/dist/services/provider.js +521 -0
- package/dist/services/provider.js.map +1 -0
- package/dist/services/state-codec.d.ts +15 -0
- package/dist/services/state-codec.d.ts.map +1 -0
- package/dist/services/state-codec.js +133 -0
- package/dist/services/state-codec.js.map +1 -0
- package/dist/services/state-internals.d.ts +13 -0
- package/dist/services/state-internals.d.ts.map +1 -0
- package/dist/services/state-internals.js +10 -0
- package/dist/services/state-internals.js.map +1 -0
- package/dist/services/state.d.ts +28 -0
- package/dist/services/state.d.ts.map +1 -0
- package/dist/services/state.js +397 -0
- package/dist/services/state.js.map +1 -0
- package/dist/services/wire.d.ts +63 -0
- package/dist/services/wire.d.ts.map +1 -0
- package/dist/services/wire.js +186 -0
- package/dist/services/wire.js.map +1 -0
- package/dist/types.d.ts +277 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -5
- package/src/delta/README.md +191 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/services/state.ts"],"names":[],"mappings":"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","sourcesContent":["import { BACKGROUND_CONTEXT } from \"../context/index.ts\";\nimport { applyImmutable, isBase, type Op, type Prepared, type Tracker, track } from \"../delta/index.ts\";\nimport { JsonRevisionValidator } from \"../delta/revision-validator.ts\";\nimport type {\n\tAttachedReplicatedState,\n\tContext,\n\tJsonValue,\n\tMutableReplicatedState,\n\tReplicatedState,\n\tReplicatedStateDelivery,\n\tReplicatedStateSource,\n\tReplicatedStateSourceAttachment,\n\tReplicatedStateSourceFrame,\n\tReplicatedStateSourceOptions,\n} from \"../types.ts\";\nimport { registerReplicatedStateInternals } from \"./state-internals.ts\";\n\n/** The void signature also accepts synchronous callbacks that return an ignored value. */\ntype StateListener<T> = (value: T, context: Context, delivery: ReplicatedStateDelivery) => void;\n\ntype StateDelivery<T> = {\n\treadonly value: T;\n\treadonly context: Context;\n\treadonly delivery: ReplicatedStateDelivery;\n};\n\n/** One public subscription, independent of producer and other subscriber progress. */\nclass StateSubscriber<T> {\n\treadonly #listener: StateListener<T>;\n\treadonly #reportError: (error: Error) => void;\n\treadonly #pending: StateDelivery<T>[] = [];\n\t#running = false;\n\t#started = false;\n\t#closed = false;\n\n\tconstructor(listener: StateListener<T>, reportError: (error: Error) => void) {\n\t\tthis.#listener = listener;\n\t\tthis.#reportError = reportError;\n\t}\n\n\tpush(frame: StateDelivery<T>): void {\n\t\tif (this.#closed) return;\n\t\tif (this.#pending.length === 100) {\n\t\t\t// A cold replica can queue updates reentrantly before this subscriber's first hydration starts.\n\t\t\tconst hydration = this.#started ? undefined : this.#pending[0];\n\t\t\tthis.#pending.length = 0;\n\t\t\tif (hydration !== undefined) this.#pending.push(hydration);\n\t\t}\n\t\tthis.#pending.push(frame);\n\t}\n\n\tdrain(): void {\n\t\tif (this.#running || this.#closed) return;\n\t\tthis.#running = true;\n\t\tfor (let frame = this.#pending.shift(); frame !== undefined; frame = this.#pending.shift()) {\n\t\t\tthis.#started = true;\n\t\t\ttry {\n\t\t\t\tconst result: unknown = this.#listener(frame.value, frame.context, frame.delivery);\n\t\t\t\tif (isPromiseLike(result)) {\n\t\t\t\t\tvoid Promise.resolve(result).then(\n\t\t\t\t\t\t() => this.#resume(),\n\t\t\t\t\t\t(error: unknown) => {\n\t\t\t\t\t\t\tthis.#report(error);\n\t\t\t\t\t\t\tthis.#resume();\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.#report(error);\n\t\t\t}\n\t\t}\n\t\tthis.#running = false;\n\t}\n\n\tclear(): void {\n\t\tthis.#pending.length = 0;\n\t}\n\n\tclose(): void {\n\t\tthis.#closed = true;\n\t\tthis.clear();\n\t}\n\n\t#resume(): void {\n\t\tthis.#running = false;\n\t\tthis.drain();\n\t}\n\n\t#report(error: unknown): void {\n\t\ttry {\n\t\t\tthis.#reportError(toError(error));\n\t\t} catch (reportError) {\n\t\t\treportErrorAsync(toError(reportError));\n\t\t}\n\t}\n}\n\ntype SourceListener = (ops: readonly Op[], sequence: number, context: Context) => void;\n\ntype Publication<T> = {\n\treadonly value: T;\n\treadonly ops: readonly Op[];\n\treadonly sequence: number;\n\treadonly context: Context;\n};\n\n/** Maintains local publication order independently of how revisions are produced. */\nclass ReplicatedStatePublisher<T> {\n\treadonly #listeners = new Map<StateSubscriber<T>, number>();\n\treadonly #reportError: (error: Error) => void;\n\treadonly #sourceListeners = new Set<SourceListener>();\n\treadonly #publications: Publication<T>[] = [];\n\t#value: T;\n\t#sequence = 0;\n\t#delivering = false;\n\n\tconstructor(initial: T, reportError: (error: Error) => void = reportErrorAsync) {\n\t\tthis.#value = initial;\n\t\tthis.#reportError = reportError;\n\t}\n\n\tget value(): T {\n\t\treturn this.#value;\n\t}\n\n\tsnapshot(): { readonly value: T; readonly sequence: number } {\n\t\treturn { value: this.#value, sequence: this.#sequence };\n\t}\n\n\tsubscribe(listener: StateListener<T>): () => void {\n\t\tconst { value, sequence } = this.snapshot();\n\t\tconst subscriber = new StateSubscriber(listener, this.#reportError);\n\t\tthis.#listeners.set(subscriber, sequence);\n\t\tsubscriber.push({ value, context: serviceDeliveryContext(), delivery: { kind: \"hydrate\", sequence } });\n\t\tsubscriber.drain();\n\t\treturn () => {\n\t\t\tsubscriber.close();\n\t\t\tthis.#listeners.delete(subscriber);\n\t\t};\n\t}\n\n\tsubscribeSource(listener: SourceListener): () => void {\n\t\tthis.#sourceListeners.add(listener);\n\t\treturn () => this.#sourceListeners.delete(listener);\n\t}\n\n\t/** Publish an already-prepared immutable revision and return isolated listener failures. */\n\tpublish(value: T, ops: readonly Op[], context: Context): unknown[] {\n\t\tthis.#value = value;\n\t\tthis.#sequence += 1;\n\t\tthis.#publications.push({ value, ops, sequence: this.#sequence, context });\n\t\tif (this.#delivering) return [];\n\n\t\tthis.#delivering = true;\n\t\tconst errors: unknown[] = [];\n\t\ttry {\n\t\t\tfor (\n\t\t\t\tlet publication = this.#publications.shift();\n\t\t\t\tpublication !== undefined;\n\t\t\t\tpublication = this.#publications.shift()\n\t\t\t) {\n\t\t\t\tfor (const listener of [...this.#sourceListeners]) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlistener(publication.ops, publication.sequence, publication.context);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\terrors.push(error);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst delivery = { kind: \"update\", sequence: publication.sequence } as const;\n\t\t\t\tfor (const [subscriber, hydratedSequence] of [...this.#listeners]) {\n\t\t\t\t\tif (publication.sequence <= hydratedSequence) continue;\n\t\t\t\t\tsubscriber.push({ value: publication.value, context: publication.context, delivery });\n\t\t\t\t\tsubscriber.drain();\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#delivering = false;\n\t\t}\n\t\treturn errors;\n\t}\n}\n\nexport class MutableReplicatedStateImpl<T extends object> implements MutableReplicatedState<T> {\n\treadonly #tracker: Tracker<T>;\n\treadonly #publisher: ReplicatedStatePublisher<T>;\n\t#changing = false;\n\n\tconstructor(initial: T) {\n\t\tthis.#tracker = track(initial);\n\t\tthis.#publisher = new ReplicatedStatePublisher(this.#tracker.value);\n\t\tregisterReplicatedStateInternals(this, {\n\t\t\tsnapshot: () => this.#publisher.snapshot(),\n\t\t\tsubscribe: (listener) => this.#publisher.subscribeSource(listener),\n\t\t});\n\t}\n\n\tget value(): T {\n\t\treturn this.#tracker.value;\n\t}\n\n\tchange(context: Context, mutate: Parameters<MutableReplicatedState<T>[\"change\"]>[1]): void {\n\t\tif (this.#changing) throw new Error(\"Replicated state cannot be changed reentrantly from a change callback\");\n\t\tthis.#changing = true;\n\t\tlet prepared: Prepared<T>;\n\t\ttry {\n\t\t\tconst change = this.#tracker.beginChange();\n\t\t\ttry {\n\t\t\t\tconst outcome = (mutate as (draft: typeof change.state) => unknown)(change.state);\n\t\t\t\tif (isPromiseLike(outcome)) {\n\t\t\t\t\tvoid Promise.resolve(outcome).catch(() => undefined);\n\t\t\t\t\tthrow new TypeError(\"Replicated state change callbacks must be synchronous\");\n\t\t\t\t}\n\t\t\t\tprepared = change.prepare();\n\t\t\t} catch (error) {\n\t\t\t\tchange.abort();\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#changing = false;\n\t\t}\n\n\t\tthis.#tracker.adopt(prepared);\n\t\tif (prepared.ops.length === 0) return;\n\t\tthrowCollectedErrors(\n\t\t\tthis.#publisher.publish(prepared.value, prepared.ops, context),\n\t\t\t\"Replicated state listeners failed\",\n\t\t);\n\t}\n\n\treplace(context: Context, value: T): void {\n\t\tif (this.#changing) throw new Error(\"Replicated state cannot be replaced from a change callback\");\n\t\tconst prepared = this.#tracker.prepareReplace(value);\n\t\tthis.#tracker.adopt(prepared);\n\t\tif (prepared.ops.length === 0) return;\n\t\tthrowCollectedErrors(\n\t\t\tthis.#publisher.publish(prepared.value, prepared.ops, context),\n\t\t\t\"Replicated state listeners failed\",\n\t\t);\n\t}\n\n\tsubscribe(listener: StateListener<T>): () => void {\n\t\treturn this.#publisher.subscribe(listener);\n\t}\n}\n\nclass AttachedReplicatedStateImpl<T> implements AttachedReplicatedState<T> {\n\treadonly #publisher: ReplicatedStatePublisher<T>;\n\treadonly #attachment: ReplicatedStateSourceAttachment<T>;\n\treadonly #reportError: (error: Error) => void;\n\t#cursor: number;\n\t#disposed = false;\n\n\tconstructor(attachment: ReplicatedStateSourceAttachment<T>, options: ReplicatedStateSourceOptions) {\n\t\tconst { snapshot } = attachment;\n\t\tassertCursor(snapshot.cursor, \"snapshot\");\n\t\tthis.#attachment = attachment;\n\t\tthis.#cursor = snapshot.cursor;\n\t\tthis.#reportError = options.onError ?? reportErrorAsync;\n\t\tthis.#publisher = new ReplicatedStatePublisher(snapshot.value, (error) => this.#report(error));\n\t\tregisterReplicatedStateInternals(this, {\n\t\t\tsnapshot: () => this.#publisher.snapshot(),\n\t\t\tsubscribe: (listener) => this.#publisher.subscribeSource(listener),\n\t\t});\n\t}\n\n\tget value(): T {\n\t\treturn this.#publisher.value;\n\t}\n\n\tsubscribe(listener: StateListener<T>): () => void {\n\t\treturn this.#publisher.subscribe(listener);\n\t}\n\n\tactivate(): void {\n\t\tthis.#attachment.activate((frame) => this.#receive(frame));\n\t}\n\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tthis.#attachment.dispose();\n\t}\n\n\t#receive(frame: ReplicatedStateSourceFrame<T>): void {\n\t\tif (this.#disposed) return;\n\t\ttry {\n\t\t\tassertCursor(frame.cursor, \"frame\");\n\t\t\tconst expected = this.#cursor + 1;\n\t\t\tif (frame.cursor !== expected) {\n\t\t\t\tthrow new Error(`Replicated state source cursor has a gap: expected ${expected}, received ${frame.cursor}`);\n\t\t\t}\n\t\t\tthis.#cursor = frame.cursor;\n\t\t\tconst errors = this.#publisher.publish(frame.value, frame.ops, frame.context);\n\t\t\tif (errors.length === 1) this.#report(errors[0]);\n\t\t\telse if (errors.length > 1) this.#report(new AggregateError(errors, \"Replicated state listeners failed\"));\n\t\t} catch (error) {\n\t\t\tthis.#fail(toError(error));\n\t\t}\n\t}\n\n\t#fail(error: Error): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\ttry {\n\t\t\tthis.#attachment.dispose();\n\t\t} catch (disposeError) {\n\t\t\tthis.#report(new AggregateError([error, disposeError], \"Replicated state source contract failed\"));\n\t\t\treturn;\n\t\t}\n\t\tthis.#report(error);\n\t}\n\n\t#report(error: unknown): void {\n\t\ttry {\n\t\t\tthis.#reportError(toError(error));\n\t\t} catch (reportError) {\n\t\t\treportErrorAsync(toError(reportError));\n\t\t}\n\t}\n}\n\n/** Attach a publication-only replicated state to one authoritative immutable source stream. */\nexport function attachReplicatedStateSource<T>(\n\tsource: ReplicatedStateSource<T>,\n\toptions: ReplicatedStateSourceOptions = {},\n): AttachedReplicatedState<T> {\n\tconst attachment = source.attach();\n\ttry {\n\t\tconst state = new AttachedReplicatedStateImpl(attachment, options);\n\t\tstate.activate();\n\t\treturn state;\n\t} catch (error) {\n\t\ttry {\n\t\t\tattachment.dispose();\n\t\t} catch (disposeError) {\n\t\t\tthrow new AggregateError([error, disposeError], \"Failed to attach replicated state source\");\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** A cold read-only state used by service consumers until a complete snapshot arrives. */\nexport class ReplicatedStateReplica<T extends JsonValue = JsonValue> implements ReplicatedState<T> {\n\treadonly #listeners = new Set<StateSubscriber<T>>();\n\treadonly #reportError: (error: Error) => void;\n\treadonly #validator = new JsonRevisionValidator();\n\t#value: T | undefined;\n\t#sequence: number | undefined;\n\n\tconstructor(reportError: (error: Error) => void) {\n\t\tthis.#reportError = reportError;\n\t}\n\n\tget value(): T | undefined {\n\t\treturn this.#value;\n\t}\n\n\tsubscribe(listener: StateListener<T>): () => void {\n\t\tconst subscriber = new StateSubscriber(listener, this.#reportError);\n\t\tthis.#listeners.add(subscriber);\n\t\tif (this.#value !== undefined) {\n\t\t\tsubscriber.push({\n\t\t\t\tvalue: this.#value,\n\t\t\t\tcontext: serviceDeliveryContext(),\n\t\t\t\tdelivery: { kind: \"hydrate\", sequence: this.#sequence! },\n\t\t\t});\n\t\t\tsubscriber.drain();\n\t\t}\n\t\treturn () => {\n\t\t\tsubscriber.close();\n\t\t\tthis.#listeners.delete(subscriber);\n\t\t};\n\t}\n\n\thydrate(sequence: number, ops: readonly Op[], context: Context): void {\n\t\tlet next: T;\n\t\ttry {\n\t\t\tif (!isBase(ops)) throw new Error(\"Replicated state snapshot is not a base operation batch\");\n\t\t\tnext = this.#validator.validate(applyImmutable<T>(undefined, ops));\n\t\t} catch (error) {\n\t\t\tthis.clear();\n\t\t\tthrow error;\n\t\t}\n\t\tthis.#sequence = sequence;\n\t\tthis.#value = next;\n\t\tthis.#deliverAll(context, { kind: \"hydrate\", sequence });\n\t}\n\n\tupdate(sequence: number, ops: readonly Op[], context: Context): void {\n\t\tif (this.#sequence === undefined || this.#value === undefined) {\n\t\t\tthrow new Error(\"Replicated state received an update before hydration\");\n\t\t}\n\t\tif (sequence !== this.#sequence + 1) {\n\t\t\tthis.clear();\n\t\t\tthrow new Error(\"Replicated state update sequence has a gap\");\n\t\t}\n\t\tlet next: T;\n\t\ttry {\n\t\t\tnext = this.#validator.validate(applyImmutable(this.#value, ops));\n\t\t} catch (error) {\n\t\t\tthis.clear();\n\t\t\tthrow error;\n\t\t}\n\t\tthis.#sequence = sequence;\n\t\tthis.#value = next;\n\t\tthis.#deliverAll(context, { kind: \"update\", sequence });\n\t}\n\n\tclear(): void {\n\t\tthis.#value = undefined;\n\t\tthis.#sequence = undefined;\n\t\tfor (const subscriber of this.#listeners) subscriber.clear();\n\t}\n\n\t#deliverAll(context: Context, delivery: ReplicatedStateDelivery): void {\n\t\tif (this.#value === undefined) return;\n\t\tconst frame = { value: this.#value, context, delivery };\n\t\tconst subscribers = [...this.#listeners];\n\t\t// Enqueue for everyone before user code can publish another revision reentrantly.\n\t\tfor (const subscriber of subscribers) subscriber.push(frame);\n\t\tfor (const subscriber of subscribers) subscriber.drain();\n\t}\n}\n\n/** @internal Context for synthetic service deliveries without a caller. */\nexport function serviceDeliveryContext(): Context {\n\t// TODO: Add delivery-scoped cancellation or metadata if deliveries gain an owned lifecycle.\n\treturn BACKGROUND_CONTEXT;\n}\n\nfunction assertCursor(cursor: number, kind: \"snapshot\" | \"frame\"): void {\n\tif (!Number.isSafeInteger(cursor))\n\t\tthrow new TypeError(`Replicated state source ${kind} cursor must be a safe integer`);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n\treturn (\n\t\t((typeof value === \"object\" && value !== null) || typeof value === \"function\") &&\n\t\ttypeof (value as { then?: unknown }).then === \"function\"\n\t);\n}\n\nfunction throwCollectedErrors(errors: readonly unknown[], message: string): void {\n\tif (errors.length === 1) throw errors[0];\n\tif (errors.length > 1) throw new AggregateError(errors, message);\n}\n\nfunction reportErrorAsync(error: Error): void {\n\tqueueMicrotask(() => {\n\t\tthrow error;\n\t});\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n"]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type WireOp } from "../delta/index.ts";
|
|
2
|
+
import type { ServiceCall, ServiceCatalogueEntry, ServiceInstanceAddress, ServiceMode, ServiceProviderUpdate, ServiceSubscriptionSnapshot } from "../types.ts";
|
|
3
|
+
export type WireServiceMemberSnapshot = {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly kind: "method";
|
|
6
|
+
} | {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly kind: "state";
|
|
9
|
+
readonly sequence: number;
|
|
10
|
+
readonly ops: readonly WireOp[];
|
|
11
|
+
};
|
|
12
|
+
export type WireServiceInstanceSnapshot = {
|
|
13
|
+
readonly instance?: ServiceInstanceAddress;
|
|
14
|
+
readonly members: readonly WireServiceMemberSnapshot[];
|
|
15
|
+
};
|
|
16
|
+
export type WireServiceSubscriptionSnapshot = {
|
|
17
|
+
readonly serviceId: string;
|
|
18
|
+
readonly mode: ServiceMode;
|
|
19
|
+
readonly instances: readonly WireServiceInstanceSnapshot[];
|
|
20
|
+
};
|
|
21
|
+
export type WireServiceProviderUpdate = {
|
|
22
|
+
readonly type: "state";
|
|
23
|
+
readonly instance?: ServiceInstanceAddress;
|
|
24
|
+
readonly member: string;
|
|
25
|
+
readonly sequence: number;
|
|
26
|
+
readonly ops: readonly WireOp[];
|
|
27
|
+
} | {
|
|
28
|
+
readonly type: "reset";
|
|
29
|
+
readonly snapshot: WireServiceSubscriptionSnapshot;
|
|
30
|
+
} | {
|
|
31
|
+
readonly type: "unavailable";
|
|
32
|
+
} | {
|
|
33
|
+
readonly type: "replaced";
|
|
34
|
+
readonly snapshot: WireServiceInstanceSnapshot;
|
|
35
|
+
} | {
|
|
36
|
+
readonly type: "spawned";
|
|
37
|
+
readonly instance: WireServiceInstanceSnapshot;
|
|
38
|
+
} | {
|
|
39
|
+
readonly type: "closed";
|
|
40
|
+
readonly instance: ServiceInstanceAddress;
|
|
41
|
+
};
|
|
42
|
+
export type ServiceControlCall = {
|
|
43
|
+
readonly type: "catalogue";
|
|
44
|
+
} | {
|
|
45
|
+
readonly type: "subscribe";
|
|
46
|
+
readonly subscriptionId: string;
|
|
47
|
+
readonly serviceId: string;
|
|
48
|
+
readonly mode: ServiceMode;
|
|
49
|
+
} | {
|
|
50
|
+
readonly type: "unsubscribe";
|
|
51
|
+
readonly subscriptionId: string;
|
|
52
|
+
};
|
|
53
|
+
export declare function createServiceCatalogueCall(): ServiceCall;
|
|
54
|
+
export declare function createServiceSubscribeCall(subscriptionId: string, serviceId: string, mode: ServiceMode): ServiceCall;
|
|
55
|
+
export declare function createServiceUnsubscribeCall(subscriptionId: string): ServiceCall;
|
|
56
|
+
export declare function decodeServiceControlCall(call: ServiceCall): ServiceControlCall | undefined;
|
|
57
|
+
export declare function parseServiceCall(value: unknown): ServiceCall;
|
|
58
|
+
export declare function parseServiceCatalogue(value: unknown): readonly ServiceCatalogueEntry[];
|
|
59
|
+
export declare function parseServiceSubscriptionSnapshot(value: unknown): ServiceSubscriptionSnapshot;
|
|
60
|
+
export declare function parseWireServiceSubscriptionSnapshot(value: unknown): WireServiceSubscriptionSnapshot;
|
|
61
|
+
export declare function parseServiceProviderUpdate(value: unknown): ServiceProviderUpdate;
|
|
62
|
+
export declare function parseWireServiceProviderUpdate(value: unknown): WireServiceProviderUpdate;
|
|
63
|
+
//# sourceMappingURL=wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../src/services/wire.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { assertValidOp, assertValidWireOp } from "../delta/index.js";
|
|
2
|
+
const SERVICE_CONTROL_ID = "$chord.service";
|
|
3
|
+
const SERVICE_CATALOGUE_MEMBER = "catalogue";
|
|
4
|
+
const SERVICE_SUBSCRIBE_MEMBER = "subscribe";
|
|
5
|
+
const SERVICE_UNSUBSCRIBE_MEMBER = "unsubscribe";
|
|
6
|
+
export function createServiceCatalogueCall() {
|
|
7
|
+
return { serviceId: SERVICE_CONTROL_ID, member: SERVICE_CATALOGUE_MEMBER, args: [] };
|
|
8
|
+
}
|
|
9
|
+
export function createServiceSubscribeCall(subscriptionId, serviceId, mode) {
|
|
10
|
+
return { serviceId: SERVICE_CONTROL_ID, member: SERVICE_SUBSCRIBE_MEMBER, args: [subscriptionId, serviceId, mode] };
|
|
11
|
+
}
|
|
12
|
+
export function createServiceUnsubscribeCall(subscriptionId) {
|
|
13
|
+
return { serviceId: SERVICE_CONTROL_ID, member: SERVICE_UNSUBSCRIBE_MEMBER, args: [subscriptionId] };
|
|
14
|
+
}
|
|
15
|
+
export function decodeServiceControlCall(call) {
|
|
16
|
+
if (call.serviceId !== SERVICE_CONTROL_ID || call.instance !== undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
if (call.member === SERVICE_CATALOGUE_MEMBER && call.args.length === 0)
|
|
19
|
+
return { type: "catalogue" };
|
|
20
|
+
if (call.member === SERVICE_SUBSCRIBE_MEMBER &&
|
|
21
|
+
call.args.length === 3 &&
|
|
22
|
+
isId(call.args[0]) &&
|
|
23
|
+
isId(call.args[1]) &&
|
|
24
|
+
(call.args[2] === "singleton" || call.args[2] === "keyed")) {
|
|
25
|
+
return {
|
|
26
|
+
type: "subscribe",
|
|
27
|
+
subscriptionId: call.args[0],
|
|
28
|
+
serviceId: call.args[1],
|
|
29
|
+
mode: call.args[2],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (call.member === SERVICE_UNSUBSCRIBE_MEMBER && call.args.length === 1 && isId(call.args[0])) {
|
|
33
|
+
return { type: "unsubscribe", subscriptionId: call.args[0] };
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
export function parseServiceCall(value) {
|
|
38
|
+
const call = record(value, "service call");
|
|
39
|
+
assertKeys(call, ["serviceId", "member", "args"], ["instance"], "service call");
|
|
40
|
+
if (!isId(call.serviceId) || !isId(call.member) || !Array.isArray(call.args)) {
|
|
41
|
+
throw new TypeError("Invalid service call");
|
|
42
|
+
}
|
|
43
|
+
if (call.instance !== undefined)
|
|
44
|
+
assertAddress(call.instance);
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
export function parseServiceCatalogue(value) {
|
|
48
|
+
if (!Array.isArray(value))
|
|
49
|
+
throw new TypeError("Invalid service catalogue");
|
|
50
|
+
const ids = new Set();
|
|
51
|
+
for (const candidate of value) {
|
|
52
|
+
const entry = record(candidate, "service catalogue entry");
|
|
53
|
+
assertKeys(entry, ["serviceId", "mode"], [], "service catalogue entry");
|
|
54
|
+
if (!isId(entry.serviceId) || !isMode(entry.mode) || ids.has(entry.serviceId)) {
|
|
55
|
+
throw new TypeError("Invalid service catalogue");
|
|
56
|
+
}
|
|
57
|
+
ids.add(entry.serviceId);
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
export function parseServiceSubscriptionSnapshot(value) {
|
|
62
|
+
assertSubscriptionSnapshot(value, assertValidOp);
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
export function parseWireServiceSubscriptionSnapshot(value) {
|
|
66
|
+
assertSubscriptionSnapshot(value, assertValidWireOp);
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
export function parseServiceProviderUpdate(value) {
|
|
70
|
+
assertProviderUpdate(value, assertValidOp);
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
export function parseWireServiceProviderUpdate(value) {
|
|
74
|
+
assertProviderUpdate(value, assertValidWireOp);
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
function assertSubscriptionSnapshot(value, assertOp) {
|
|
78
|
+
const snapshot = record(value, "service subscription snapshot");
|
|
79
|
+
assertKeys(snapshot, ["serviceId", "mode", "instances"], [], "service subscription snapshot");
|
|
80
|
+
if (!isId(snapshot.serviceId) || !isMode(snapshot.mode) || !Array.isArray(snapshot.instances)) {
|
|
81
|
+
throw new TypeError("Invalid service subscription snapshot");
|
|
82
|
+
}
|
|
83
|
+
for (const instance of snapshot.instances)
|
|
84
|
+
assertInstance(instance, assertOp);
|
|
85
|
+
}
|
|
86
|
+
function assertProviderUpdate(value, assertOp) {
|
|
87
|
+
const update = record(value, "service provider update");
|
|
88
|
+
switch (update.type) {
|
|
89
|
+
case "state":
|
|
90
|
+
assertKeys(update, ["type", "member", "sequence", "ops"], ["instance"], "state update");
|
|
91
|
+
if (!isId(update.member) || !isInteger(update.sequence, 1) || !Array.isArray(update.ops)) {
|
|
92
|
+
throw new TypeError("Invalid service state update");
|
|
93
|
+
}
|
|
94
|
+
if (update.instance !== undefined)
|
|
95
|
+
assertAddress(update.instance);
|
|
96
|
+
for (const op of update.ops)
|
|
97
|
+
assertOp(op);
|
|
98
|
+
return;
|
|
99
|
+
case "reset": {
|
|
100
|
+
assertKeys(update, ["type", "snapshot"], [], "reset update");
|
|
101
|
+
assertSubscriptionSnapshot(update.snapshot, assertOp);
|
|
102
|
+
const snapshot = update.snapshot;
|
|
103
|
+
for (const instance of snapshot.instances) {
|
|
104
|
+
for (const member of instance.members) {
|
|
105
|
+
if (member.kind === "state" && (member.ops.length !== 1 || member.ops[0]?.[0] !== "r")) {
|
|
106
|
+
throw new TypeError("Service reset must contain full root replacements");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
case "unavailable":
|
|
113
|
+
assertKeys(update, ["type"], [], "unavailable update");
|
|
114
|
+
return;
|
|
115
|
+
case "replaced":
|
|
116
|
+
assertKeys(update, ["type", "snapshot"], [], "replacement update");
|
|
117
|
+
assertInstance(update.snapshot, assertOp);
|
|
118
|
+
return;
|
|
119
|
+
case "spawned":
|
|
120
|
+
assertKeys(update, ["type", "instance"], [], "spawn update");
|
|
121
|
+
assertInstance(update.instance, assertOp);
|
|
122
|
+
return;
|
|
123
|
+
case "closed":
|
|
124
|
+
assertKeys(update, ["type", "instance"], [], "close update");
|
|
125
|
+
assertAddress(update.instance);
|
|
126
|
+
return;
|
|
127
|
+
default:
|
|
128
|
+
throw new TypeError("Invalid service provider update");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function assertInstance(value, assertOp) {
|
|
132
|
+
const instance = record(value, "service instance snapshot");
|
|
133
|
+
assertKeys(instance, ["members"], ["instance"], "service instance snapshot");
|
|
134
|
+
if (instance.instance !== undefined)
|
|
135
|
+
assertAddress(instance.instance);
|
|
136
|
+
if (!Array.isArray(instance.members))
|
|
137
|
+
throw new TypeError("Invalid service instance snapshot");
|
|
138
|
+
for (const candidate of instance.members) {
|
|
139
|
+
const member = record(candidate, "service member snapshot");
|
|
140
|
+
if (member.kind === "method") {
|
|
141
|
+
assertKeys(member, ["name", "kind"], [], "service method snapshot");
|
|
142
|
+
if (!isId(member.name))
|
|
143
|
+
throw new TypeError("Invalid service method snapshot");
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (member.kind === "state") {
|
|
147
|
+
assertKeys(member, ["name", "kind", "sequence", "ops"], [], "service state snapshot");
|
|
148
|
+
if (!isId(member.name) || !isInteger(member.sequence, 0) || !Array.isArray(member.ops)) {
|
|
149
|
+
throw new TypeError("Invalid service state snapshot");
|
|
150
|
+
}
|
|
151
|
+
for (const op of member.ops)
|
|
152
|
+
assertOp(op);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
throw new TypeError("Invalid service member snapshot");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function assertAddress(value) {
|
|
159
|
+
const address = record(value, "service instance address");
|
|
160
|
+
assertKeys(address, ["key", "generation"], [], "service instance address");
|
|
161
|
+
if (!isId(address.key) || !isInteger(address.generation, 1)) {
|
|
162
|
+
throw new TypeError("Invalid service instance address");
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function record(value, description) {
|
|
166
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
167
|
+
throw new TypeError(`Invalid ${description}`);
|
|
168
|
+
}
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
function assertKeys(value, required, optional, description) {
|
|
172
|
+
const allowed = new Set([...required, ...optional]);
|
|
173
|
+
if (required.some((key) => !Object.hasOwn(value, key)) || Object.keys(value).some((key) => !allowed.has(key))) {
|
|
174
|
+
throw new TypeError(`Invalid ${description}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function isId(value) {
|
|
178
|
+
return typeof value === "string" && value.length > 0;
|
|
179
|
+
}
|
|
180
|
+
function isMode(value) {
|
|
181
|
+
return value === "singleton" || value === "keyed";
|
|
182
|
+
}
|
|
183
|
+
function isInteger(value, minimum) {
|
|
184
|
+
return typeof value === "number" && Number.isInteger(value) && value >= minimum;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=wire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.js","sourceRoot":"","sources":["../../src/services/wire.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertValidOp, assertValidWireOp, type WireOp } from \"../delta/index.ts\";\nimport type {\n\tServiceCall,\n\tServiceCatalogueEntry,\n\tServiceInstanceAddress,\n\tServiceMode,\n\tServiceProviderUpdate,\n\tServiceSubscriptionSnapshot,\n} from \"../types.ts\";\n\nexport type WireServiceMemberSnapshot =\n\t| { readonly name: string; readonly kind: \"method\" }\n\t| { readonly name: string; readonly kind: \"state\"; readonly sequence: number; readonly ops: readonly WireOp[] };\n\nexport type WireServiceInstanceSnapshot = {\n\treadonly instance?: ServiceInstanceAddress;\n\treadonly members: readonly WireServiceMemberSnapshot[];\n};\n\nexport type WireServiceSubscriptionSnapshot = {\n\treadonly serviceId: string;\n\treadonly mode: ServiceMode;\n\treadonly instances: readonly WireServiceInstanceSnapshot[];\n};\n\nexport type WireServiceProviderUpdate =\n\t| {\n\t\t\treadonly type: \"state\";\n\t\t\treadonly instance?: ServiceInstanceAddress;\n\t\t\treadonly member: string;\n\t\t\treadonly sequence: number;\n\t\t\treadonly ops: readonly WireOp[];\n\t }\n\t| { readonly type: \"reset\"; readonly snapshot: WireServiceSubscriptionSnapshot }\n\t| { readonly type: \"unavailable\" }\n\t| { readonly type: \"replaced\"; readonly snapshot: WireServiceInstanceSnapshot }\n\t| { readonly type: \"spawned\"; readonly instance: WireServiceInstanceSnapshot }\n\t| { readonly type: \"closed\"; readonly instance: ServiceInstanceAddress };\n\nconst SERVICE_CONTROL_ID = \"$chord.service\";\nconst SERVICE_CATALOGUE_MEMBER = \"catalogue\";\nconst SERVICE_SUBSCRIBE_MEMBER = \"subscribe\";\nconst SERVICE_UNSUBSCRIBE_MEMBER = \"unsubscribe\";\n\nexport type ServiceControlCall =\n\t| { readonly type: \"catalogue\" }\n\t| {\n\t\t\treadonly type: \"subscribe\";\n\t\t\treadonly subscriptionId: string;\n\t\t\treadonly serviceId: string;\n\t\t\treadonly mode: ServiceMode;\n\t }\n\t| { readonly type: \"unsubscribe\"; readonly subscriptionId: string };\n\nexport function createServiceCatalogueCall(): ServiceCall {\n\treturn { serviceId: SERVICE_CONTROL_ID, member: SERVICE_CATALOGUE_MEMBER, args: [] };\n}\n\nexport function createServiceSubscribeCall(subscriptionId: string, serviceId: string, mode: ServiceMode): ServiceCall {\n\treturn { serviceId: SERVICE_CONTROL_ID, member: SERVICE_SUBSCRIBE_MEMBER, args: [subscriptionId, serviceId, mode] };\n}\n\nexport function createServiceUnsubscribeCall(subscriptionId: string): ServiceCall {\n\treturn { serviceId: SERVICE_CONTROL_ID, member: SERVICE_UNSUBSCRIBE_MEMBER, args: [subscriptionId] };\n}\n\nexport function decodeServiceControlCall(call: ServiceCall): ServiceControlCall | undefined {\n\tif (call.serviceId !== SERVICE_CONTROL_ID || call.instance !== undefined) return undefined;\n\tif (call.member === SERVICE_CATALOGUE_MEMBER && call.args.length === 0) return { type: \"catalogue\" };\n\tif (\n\t\tcall.member === SERVICE_SUBSCRIBE_MEMBER &&\n\t\tcall.args.length === 3 &&\n\t\tisId(call.args[0]) &&\n\t\tisId(call.args[1]) &&\n\t\t(call.args[2] === \"singleton\" || call.args[2] === \"keyed\")\n\t) {\n\t\treturn {\n\t\t\ttype: \"subscribe\",\n\t\t\tsubscriptionId: call.args[0],\n\t\t\tserviceId: call.args[1],\n\t\t\tmode: call.args[2],\n\t\t};\n\t}\n\tif (call.member === SERVICE_UNSUBSCRIBE_MEMBER && call.args.length === 1 && isId(call.args[0])) {\n\t\treturn { type: \"unsubscribe\", subscriptionId: call.args[0] };\n\t}\n\treturn undefined;\n}\n\nexport function parseServiceCall(value: unknown): ServiceCall {\n\tconst call = record(value, \"service call\");\n\tassertKeys(call, [\"serviceId\", \"member\", \"args\"], [\"instance\"], \"service call\");\n\tif (!isId(call.serviceId) || !isId(call.member) || !Array.isArray(call.args)) {\n\t\tthrow new TypeError(\"Invalid service call\");\n\t}\n\tif (call.instance !== undefined) assertAddress(call.instance);\n\treturn value as ServiceCall;\n}\n\nexport function parseServiceCatalogue(value: unknown): readonly ServiceCatalogueEntry[] {\n\tif (!Array.isArray(value)) throw new TypeError(\"Invalid service catalogue\");\n\tconst ids = new Set<string>();\n\tfor (const candidate of value) {\n\t\tconst entry = record(candidate, \"service catalogue entry\");\n\t\tassertKeys(entry, [\"serviceId\", \"mode\"], [], \"service catalogue entry\");\n\t\tif (!isId(entry.serviceId) || !isMode(entry.mode) || ids.has(entry.serviceId)) {\n\t\t\tthrow new TypeError(\"Invalid service catalogue\");\n\t\t}\n\t\tids.add(entry.serviceId);\n\t}\n\treturn value as unknown as readonly ServiceCatalogueEntry[];\n}\n\nexport function parseServiceSubscriptionSnapshot(value: unknown): ServiceSubscriptionSnapshot {\n\tassertSubscriptionSnapshot(value, assertValidOp);\n\treturn value as ServiceSubscriptionSnapshot;\n}\n\nexport function parseWireServiceSubscriptionSnapshot(value: unknown): WireServiceSubscriptionSnapshot {\n\tassertSubscriptionSnapshot(value, assertValidWireOp);\n\treturn value as WireServiceSubscriptionSnapshot;\n}\n\nexport function parseServiceProviderUpdate(value: unknown): ServiceProviderUpdate {\n\tassertProviderUpdate(value, assertValidOp);\n\treturn value as ServiceProviderUpdate;\n}\n\nexport function parseWireServiceProviderUpdate(value: unknown): WireServiceProviderUpdate {\n\tassertProviderUpdate(value, assertValidWireOp);\n\treturn value as WireServiceProviderUpdate;\n}\n\nfunction assertSubscriptionSnapshot(value: unknown, assertOp: (value: unknown) => void): void {\n\tconst snapshot = record(value, \"service subscription snapshot\");\n\tassertKeys(snapshot, [\"serviceId\", \"mode\", \"instances\"], [], \"service subscription snapshot\");\n\tif (!isId(snapshot.serviceId) || !isMode(snapshot.mode) || !Array.isArray(snapshot.instances)) {\n\t\tthrow new TypeError(\"Invalid service subscription snapshot\");\n\t}\n\tfor (const instance of snapshot.instances) assertInstance(instance, assertOp);\n}\n\nfunction assertProviderUpdate(value: unknown, assertOp: (value: unknown) => void): void {\n\tconst update = record(value, \"service provider update\");\n\tswitch (update.type) {\n\t\tcase \"state\":\n\t\t\tassertKeys(update, [\"type\", \"member\", \"sequence\", \"ops\"], [\"instance\"], \"state update\");\n\t\t\tif (!isId(update.member) || !isInteger(update.sequence, 1) || !Array.isArray(update.ops)) {\n\t\t\t\tthrow new TypeError(\"Invalid service state update\");\n\t\t\t}\n\t\t\tif (update.instance !== undefined) assertAddress(update.instance);\n\t\t\tfor (const op of update.ops) assertOp(op);\n\t\t\treturn;\n\t\tcase \"reset\": {\n\t\t\tassertKeys(update, [\"type\", \"snapshot\"], [], \"reset update\");\n\t\t\tassertSubscriptionSnapshot(update.snapshot, assertOp);\n\t\t\tconst snapshot = update.snapshot as WireServiceSubscriptionSnapshot;\n\t\t\tfor (const instance of snapshot.instances) {\n\t\t\t\tfor (const member of instance.members) {\n\t\t\t\t\tif (member.kind === \"state\" && (member.ops.length !== 1 || member.ops[0]?.[0] !== \"r\")) {\n\t\t\t\t\t\tthrow new TypeError(\"Service reset must contain full root replacements\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tcase \"unavailable\":\n\t\t\tassertKeys(update, [\"type\"], [], \"unavailable update\");\n\t\t\treturn;\n\t\tcase \"replaced\":\n\t\t\tassertKeys(update, [\"type\", \"snapshot\"], [], \"replacement update\");\n\t\t\tassertInstance(update.snapshot, assertOp);\n\t\t\treturn;\n\t\tcase \"spawned\":\n\t\t\tassertKeys(update, [\"type\", \"instance\"], [], \"spawn update\");\n\t\t\tassertInstance(update.instance, assertOp);\n\t\t\treturn;\n\t\tcase \"closed\":\n\t\t\tassertKeys(update, [\"type\", \"instance\"], [], \"close update\");\n\t\t\tassertAddress(update.instance);\n\t\t\treturn;\n\t\tdefault:\n\t\t\tthrow new TypeError(\"Invalid service provider update\");\n\t}\n}\n\nfunction assertInstance(value: unknown, assertOp: (value: unknown) => void): void {\n\tconst instance = record(value, \"service instance snapshot\");\n\tassertKeys(instance, [\"members\"], [\"instance\"], \"service instance snapshot\");\n\tif (instance.instance !== undefined) assertAddress(instance.instance);\n\tif (!Array.isArray(instance.members)) throw new TypeError(\"Invalid service instance snapshot\");\n\tfor (const candidate of instance.members) {\n\t\tconst member = record(candidate, \"service member snapshot\");\n\t\tif (member.kind === \"method\") {\n\t\t\tassertKeys(member, [\"name\", \"kind\"], [], \"service method snapshot\");\n\t\t\tif (!isId(member.name)) throw new TypeError(\"Invalid service method snapshot\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (member.kind === \"state\") {\n\t\t\tassertKeys(member, [\"name\", \"kind\", \"sequence\", \"ops\"], [], \"service state snapshot\");\n\t\t\tif (!isId(member.name) || !isInteger(member.sequence, 0) || !Array.isArray(member.ops)) {\n\t\t\t\tthrow new TypeError(\"Invalid service state snapshot\");\n\t\t\t}\n\t\t\tfor (const op of member.ops) assertOp(op);\n\t\t\tcontinue;\n\t\t}\n\t\tthrow new TypeError(\"Invalid service member snapshot\");\n\t}\n}\n\nfunction assertAddress(value: unknown): asserts value is ServiceInstanceAddress {\n\tconst address = record(value, \"service instance address\");\n\tassertKeys(address, [\"key\", \"generation\"], [], \"service instance address\");\n\tif (!isId(address.key) || !isInteger(address.generation, 1)) {\n\t\tthrow new TypeError(\"Invalid service instance address\");\n\t}\n}\n\nfunction record(value: unknown, description: string): Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new TypeError(`Invalid ${description}`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction assertKeys(\n\tvalue: Record<string, unknown>,\n\trequired: readonly string[],\n\toptional: readonly string[],\n\tdescription: string,\n): void {\n\tconst allowed = new Set([...required, ...optional]);\n\tif (required.some((key) => !Object.hasOwn(value, key)) || Object.keys(value).some((key) => !allowed.has(key))) {\n\t\tthrow new TypeError(`Invalid ${description}`);\n\t}\n}\n\nfunction isId(value: unknown): value is string {\n\treturn typeof value === \"string\" && value.length > 0;\n}\n\nfunction isMode(value: unknown): value is ServiceMode {\n\treturn value === \"singleton\" || value === \"keyed\";\n}\n\nfunction isInteger(value: unknown, minimum: number): value is number {\n\treturn typeof value === \"number\" && Number.isInteger(value) && value >= minimum;\n}\n"]}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import type { Draft, Op } from "./delta/index.ts";
|
|
2
|
+
import type { RemoteServiceProvider } from "./services/provider.ts";
|
|
3
|
+
export type { RemoteServiceError } from "./services/errors.ts";
|
|
4
|
+
export type { RemoteServiceProvider } from "./services/provider.ts";
|
|
5
|
+
/** Typed identity for one value carried by a {@link Context}. */
|
|
6
|
+
export interface ContextKey<T> {
|
|
7
|
+
readonly token: symbol;
|
|
8
|
+
/** Type-only marker that prevents keys with different value types from being interchangeable. */
|
|
9
|
+
readonly valueType?: (value: T) => T;
|
|
10
|
+
}
|
|
11
|
+
/** Immutable invocation-scoped values passed explicitly through operations. */
|
|
12
|
+
export interface Context {
|
|
13
|
+
readonly abortSignal: AbortSignal | undefined;
|
|
14
|
+
value<T>(key: ContextKey<T>): T | undefined;
|
|
15
|
+
toString(): string;
|
|
16
|
+
}
|
|
17
|
+
export type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
18
|
+
[key: string]: JsonValue;
|
|
19
|
+
};
|
|
20
|
+
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
21
|
+
/** Strict-JSON representation of an application data type. Unknown payloads become JsonValue. */
|
|
22
|
+
export type JsonRepresentation<T> = IsAny<T> extends true ? JsonValue : unknown extends T ? JsonValue : T extends null | boolean | number | string ? T : T extends readonly (infer TItem)[] ? JsonRepresentation<TItem>[] : T extends object ? {
|
|
23
|
+
[TKey in keyof T]: JsonRepresentation<T[TKey]>;
|
|
24
|
+
} : never;
|
|
25
|
+
export interface ReplicatedStateDelivery {
|
|
26
|
+
readonly kind: "hydrate" | "update";
|
|
27
|
+
readonly sequence: number;
|
|
28
|
+
}
|
|
29
|
+
export interface ReplicatedState<T> {
|
|
30
|
+
/**
|
|
31
|
+
* Contract-immutable value, or undefined until hydration. It is not frozen and may share containers with an
|
|
32
|
+
* in-process provider; consumers must not mutate it. Later updates do not mutate previously returned values.
|
|
33
|
+
*/
|
|
34
|
+
readonly value: T | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Each subscription serializes callbacks, awaiting hydration before updates. Values are immutable and may
|
|
37
|
+
* share unchanged revision data. At most 100 deliveries wait behind the running callback; overflow keeps
|
|
38
|
+
* only the newest pending value/context/delivery, so update sequences may skip. Failures are reported in
|
|
39
|
+
* isolation and delivery continues. Unsubscribe discards pending work without aborting or joining a callback.
|
|
40
|
+
*/
|
|
41
|
+
subscribe(listener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => Promise<void>): () => void;
|
|
42
|
+
subscribe(listener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => void): () => void;
|
|
43
|
+
}
|
|
44
|
+
export interface MutableReplicatedState<T extends object> extends ReplicatedState<T> {
|
|
45
|
+
readonly value: T;
|
|
46
|
+
/**
|
|
47
|
+
* Atomically publish one synchronous overlay mutation. Draft handles are unusable after the callback returns.
|
|
48
|
+
* Values placed through the draft are cloned by value; assigning `undefined` to an object property deletes it.
|
|
49
|
+
*/
|
|
50
|
+
change(context: Context, mutate: (draft: Draft<T>) => void): void;
|
|
51
|
+
/**
|
|
52
|
+
* Atomically take immutable ownership of an alias-free strict-JSON replacement.
|
|
53
|
+
* The caller must not mutate the transferred root after this call.
|
|
54
|
+
*/
|
|
55
|
+
replace(context: Context, value: T): void;
|
|
56
|
+
}
|
|
57
|
+
/** One immutable authoritative revision committed after an attachment snapshot. */
|
|
58
|
+
export interface ReplicatedStateSourceFrame<T> {
|
|
59
|
+
/** Monotonic source cursor. The first frame after a snapshot must be `snapshot.cursor + 1`. */
|
|
60
|
+
readonly cursor: number;
|
|
61
|
+
/** The exact immutable value produced by this commit. */
|
|
62
|
+
readonly value: T;
|
|
63
|
+
/** The exact immutable operation batch that produced `value` from the preceding source revision. */
|
|
64
|
+
readonly ops: readonly Op[];
|
|
65
|
+
readonly context: Context;
|
|
66
|
+
}
|
|
67
|
+
export interface ReplicatedStateSourceAttachment<T> {
|
|
68
|
+
/** Fixed immutable snapshot captured at the atomic attachment boundary. */
|
|
69
|
+
readonly snapshot: {
|
|
70
|
+
readonly value: T;
|
|
71
|
+
readonly cursor: number;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Install the sole listener and synchronously drain every buffered frame in source commit order.
|
|
75
|
+
* This method is single-use. After it begins, every new committed frame must also be delivered in order
|
|
76
|
+
* until disposal, including commits made reentrantly while a prior frame is being delivered.
|
|
77
|
+
*/
|
|
78
|
+
activate(listener: (frame: ReplicatedStateSourceFrame<T>) => void): void;
|
|
79
|
+
/** Stop delivery and release source resources. Disposal must be idempotent. */
|
|
80
|
+
dispose(): void;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* An authoritative immutable revision source.
|
|
84
|
+
*
|
|
85
|
+
* `attach()` must synchronously and atomically capture one snapshot and register the returned attachment to buffer
|
|
86
|
+
* every later committed frame. The snapshot must include every commit before that boundary; buffered frames must
|
|
87
|
+
* include every commit after it, with no overlap or gap. Snapshot values, frame values, and operation batches are
|
|
88
|
+
* immutable and remain valid after delivery. Chord only publishes these references; it never applies or re-diffs them.
|
|
89
|
+
*/
|
|
90
|
+
export interface ReplicatedStateSource<T> {
|
|
91
|
+
attach(): ReplicatedStateSourceAttachment<T>;
|
|
92
|
+
}
|
|
93
|
+
export interface ReplicatedStateSourceOptions {
|
|
94
|
+
/** Receives source-contract and publication-listener failures without throwing them into the source. */
|
|
95
|
+
readonly onError?: (error: Error) => void;
|
|
96
|
+
}
|
|
97
|
+
/** A synchronously hydrated publication-only state backed by one source attachment. */
|
|
98
|
+
export interface AttachedReplicatedState<T> extends ReplicatedState<T> {
|
|
99
|
+
readonly value: T;
|
|
100
|
+
/** Idempotently release the source attachment. The last published value remains readable. */
|
|
101
|
+
dispose(): void;
|
|
102
|
+
}
|
|
103
|
+
declare const SERVICE_TYPE: unique symbol;
|
|
104
|
+
export type ServiceMode = "singleton" | "keyed";
|
|
105
|
+
/** Stable identity for one shared TypeScript service contract. */
|
|
106
|
+
export interface Service<T> {
|
|
107
|
+
readonly id: string;
|
|
108
|
+
/** Process-local services accept unrestricted object contracts and are never published remotely. */
|
|
109
|
+
readonly local: boolean;
|
|
110
|
+
readonly [SERVICE_TYPE]?: (value: T) => T;
|
|
111
|
+
}
|
|
112
|
+
/** JSON with readonly containers, such as other packages' recursive JSON types. */
|
|
113
|
+
type ReadonlyJsonValue = null | boolean | number | string | readonly ReadonlyJsonValue[] | {
|
|
114
|
+
readonly [key: string]: ReadonlyJsonValue;
|
|
115
|
+
};
|
|
116
|
+
type InvalidJsonPart<T> = IsAny<T> extends true ? T : unknown extends T ? never : [T] extends [ReadonlyJsonValue] ? never : InvalidJsonStructure<T>;
|
|
117
|
+
type InvalidJsonProperty<T> = [Exclude<T, undefined>] extends [never] ? T : InvalidJsonPart<Exclude<T, undefined>>;
|
|
118
|
+
type InvalidJsonStructure<T> = T extends null | boolean | number | string ? never : T extends readonly (infer TItem)[] ? InvalidJsonPart<TItem> : T extends (...args: never[]) => unknown ? T : T extends object ? {
|
|
119
|
+
[TKey in keyof T]-?: InvalidJsonProperty<T[TKey]>;
|
|
120
|
+
}[keyof T] : T;
|
|
121
|
+
type InvalidRemoteMember<T> = T extends ReplicatedState<infer TValue> ? InvalidJsonPart<TValue> extends never ? never : "state value is not JSON" : T extends (...args: [...infer TArgs, Context]) => Promise<infer TResult> ? InvalidJsonPart<TArgs[number]> extends never ? TResult extends void ? never : InvalidJsonPart<TResult> extends never ? never : "method result is not JSON or void" : "method argument is not JSON" : "member is not a remote method or ReplicatedState";
|
|
122
|
+
type InvalidRemoteMemberNames<T> = {
|
|
123
|
+
[TKey in keyof T]-?: InvalidRemoteMember<T[TKey]> extends never ? never : TKey;
|
|
124
|
+
}[keyof T];
|
|
125
|
+
export type RemoteServiceContract<T> = InvalidRemoteMemberNames<T> extends never ? T : never;
|
|
126
|
+
export interface ServiceSpawner<T> {
|
|
127
|
+
spawn(key: string, implementation: T): () => void;
|
|
128
|
+
}
|
|
129
|
+
export interface RemoteServices {
|
|
130
|
+
use<T>(service: Service<T>): T;
|
|
131
|
+
observe<T>(service: Service<T>, handler: (service: T, context: Context) => void | Promise<void>): () => void;
|
|
132
|
+
/** Wait until every currently acquired service has installed its initial snapshot. */
|
|
133
|
+
ready(context: Context): Promise<void>;
|
|
134
|
+
dispose(context: Context): Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
export type ServiceCatalogueEntry = {
|
|
137
|
+
readonly serviceId: string;
|
|
138
|
+
readonly mode: ServiceMode;
|
|
139
|
+
};
|
|
140
|
+
export type ServiceInstanceAddress = {
|
|
141
|
+
readonly key: string;
|
|
142
|
+
readonly generation: number;
|
|
143
|
+
};
|
|
144
|
+
export type ServiceMemberSnapshot = {
|
|
145
|
+
readonly name: string;
|
|
146
|
+
readonly kind: "method";
|
|
147
|
+
} | {
|
|
148
|
+
readonly name: string;
|
|
149
|
+
readonly kind: "state";
|
|
150
|
+
readonly sequence: number;
|
|
151
|
+
readonly ops: readonly Op[];
|
|
152
|
+
};
|
|
153
|
+
export type ServiceInstanceSnapshot = {
|
|
154
|
+
readonly instance?: ServiceInstanceAddress;
|
|
155
|
+
readonly members: readonly ServiceMemberSnapshot[];
|
|
156
|
+
};
|
|
157
|
+
export type ServiceSubscriptionSnapshot = {
|
|
158
|
+
readonly serviceId: string;
|
|
159
|
+
readonly mode: ServiceMode;
|
|
160
|
+
readonly instances: readonly ServiceInstanceSnapshot[];
|
|
161
|
+
};
|
|
162
|
+
export type ServiceProviderUpdate = {
|
|
163
|
+
readonly type: "state";
|
|
164
|
+
readonly instance?: ServiceInstanceAddress;
|
|
165
|
+
readonly member: string;
|
|
166
|
+
readonly sequence: number;
|
|
167
|
+
readonly ops: readonly Op[];
|
|
168
|
+
}
|
|
169
|
+
/** Full subscription rebaseline after overflow; every state is a root replacement at its new sequence. */
|
|
170
|
+
| {
|
|
171
|
+
readonly type: "reset";
|
|
172
|
+
readonly snapshot: ServiceSubscriptionSnapshot;
|
|
173
|
+
} | {
|
|
174
|
+
readonly type: "unavailable";
|
|
175
|
+
} | {
|
|
176
|
+
readonly type: "replaced";
|
|
177
|
+
readonly snapshot: ServiceInstanceSnapshot;
|
|
178
|
+
} | {
|
|
179
|
+
readonly type: "spawned";
|
|
180
|
+
readonly instance: ServiceInstanceSnapshot;
|
|
181
|
+
} | {
|
|
182
|
+
readonly type: "closed";
|
|
183
|
+
readonly instance: ServiceInstanceAddress;
|
|
184
|
+
};
|
|
185
|
+
export type ServiceCall = {
|
|
186
|
+
readonly serviceId: string;
|
|
187
|
+
readonly instance?: ServiceInstanceAddress;
|
|
188
|
+
readonly member: string;
|
|
189
|
+
/** Borrowed immutable values. Chord validates but does not clone them. */
|
|
190
|
+
readonly args: readonly JsonValue[];
|
|
191
|
+
};
|
|
192
|
+
export interface ServiceSubscription {
|
|
193
|
+
/** Atomic baseline. Later updates buffer until activation, with a full reset on pending delivery 101. */
|
|
194
|
+
readonly snapshot: ServiceSubscriptionSnapshot;
|
|
195
|
+
activate(): void;
|
|
196
|
+
close(context?: Context): void | Promise<void>;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Pluggable wire boundary consumed by a remote service binding.
|
|
200
|
+
*
|
|
201
|
+
* Implementations choose transport, framing, routing, and envelope encoding. Values crossing this
|
|
202
|
+
* boundary must remain strict JSON. Chord does not clone values or require a particular application wire protocol;
|
|
203
|
+
* adapters own serialization and any isolation copies they require.
|
|
204
|
+
*
|
|
205
|
+
*/
|
|
206
|
+
export interface RemoteServiceTransport {
|
|
207
|
+
invoke(call: ServiceCall, context: Context): Promise<JsonValue | undefined>;
|
|
208
|
+
subscribe(serviceId: string, mode: ServiceMode, listener: (update: ServiceProviderUpdate, context: Context) => void, context: Context): Promise<ServiceSubscription>;
|
|
209
|
+
}
|
|
210
|
+
export interface RemoteServiceBindingOptions {
|
|
211
|
+
readonly services: readonly {
|
|
212
|
+
readonly id: string;
|
|
213
|
+
}[];
|
|
214
|
+
readonly transport: RemoteServiceTransport;
|
|
215
|
+
readonly bound?: boolean;
|
|
216
|
+
readonly onError?: (error: Error) => void;
|
|
217
|
+
readonly assertAccess?: () => void;
|
|
218
|
+
}
|
|
219
|
+
export interface RemoteServiceBinding extends RemoteServices {
|
|
220
|
+
rebind(bound: boolean, context: Context): Promise<void>;
|
|
221
|
+
}
|
|
222
|
+
export interface FacetEnvironment {
|
|
223
|
+
/** Declare a hard dependency on one singleton service and return its stable handle. */
|
|
224
|
+
use<T>(service: Service<T>): T;
|
|
225
|
+
/** Declare a hard dependency on a keyed service and observe each live instance. */
|
|
226
|
+
observe<T>(service: Service<T>, handler: (service: T, context: Context) => void | Promise<void>): void;
|
|
227
|
+
/** Declare and install this facet's singleton implementation of a service. */
|
|
228
|
+
provide<T>(service: Service<T>, implementation: NoInfer<T>): void;
|
|
229
|
+
/** Declare ownership of a multi-instance service and return its deferred spawning capability. */
|
|
230
|
+
provideMany<T>(service: Service<T>): ServiceSpawner<T>;
|
|
231
|
+
/**
|
|
232
|
+
* Create initialized mutable state by taking immutable ownership of an alias-free strict-JSON root.
|
|
233
|
+
* The caller must not mutate `initial` after this call.
|
|
234
|
+
*/
|
|
235
|
+
replicatedState<T extends object>(initial: T): MutableReplicatedState<T>;
|
|
236
|
+
/** Give the facet ownership of a resource cleanup function. */
|
|
237
|
+
own(disposal: () => void | Promise<void>): void;
|
|
238
|
+
/** Register asynchronous initialization after dependencies are bound and ready. */
|
|
239
|
+
onActivate(callback: () => void | Promise<void>): void;
|
|
240
|
+
/** Register final facet teardown. */
|
|
241
|
+
onDeactivate(callback: () => void | Promise<void>): void;
|
|
242
|
+
}
|
|
243
|
+
export interface Facet {
|
|
244
|
+
readonly id: string;
|
|
245
|
+
setup(env: FacetEnvironment): void;
|
|
246
|
+
}
|
|
247
|
+
export interface RemoteServiceSource {
|
|
248
|
+
/** Whether this currently unavailable source may provisionally own absent requirements. */
|
|
249
|
+
readonly acceptsUnavailableServices: boolean;
|
|
250
|
+
catalogue(context: Context): Promise<readonly ServiceCatalogueEntry[]>;
|
|
251
|
+
open(options: {
|
|
252
|
+
readonly services: readonly {
|
|
253
|
+
readonly id: string;
|
|
254
|
+
}[];
|
|
255
|
+
assertAccess(): void;
|
|
256
|
+
onError(error: Error): void;
|
|
257
|
+
}): RemoteServices;
|
|
258
|
+
}
|
|
259
|
+
export interface FacetOptions {
|
|
260
|
+
readonly facets: readonly Facet[];
|
|
261
|
+
readonly serviceSources?: readonly RemoteServiceSource[];
|
|
262
|
+
readonly onError?: (error: Error) => void;
|
|
263
|
+
}
|
|
264
|
+
export interface FacetHost {
|
|
265
|
+
readonly services: RemoteServiceProvider;
|
|
266
|
+
/** Activate and replace facets with matching IDs without disconnecting consumer service handles. */
|
|
267
|
+
reload(facets: readonly Facet[]): Promise<void>;
|
|
268
|
+
dispose(): Promise<void>;
|
|
269
|
+
}
|
|
270
|
+
export interface LoadedFacets {
|
|
271
|
+
readonly facets: readonly Facet[];
|
|
272
|
+
dispose(): Promise<void>;
|
|
273
|
+
}
|
|
274
|
+
export interface FacetLoader {
|
|
275
|
+
load(): Promise<LoadedFacets>;
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=types.d.ts.map
|