@earendil-works/chord 0.0.0
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/README.md +205 -0
- package/dist/api.d.ts +15 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +72 -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/index.d.ts +119 -0
- package/dist/delta/index.d.ts.map +1 -0
- package/dist/delta/index.js +1213 -0
- package/dist/delta/index.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 +11 -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 +4 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +57 -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 +537 -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 +99 -0
- package/dist/services/handle.js.map +1 -0
- package/dist/services/instances.d.ts +25 -0
- package/dist/services/instances.d.ts.map +1 -0
- package/dist/services/instances.js +137 -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 +472 -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 +115 -0
- package/dist/services/state-codec.js.map +1 -0
- package/dist/services/state-internals.d.ts +11 -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 +23 -0
- package/dist/services/state.d.ts.map +1 -0
- package/dist/services/state.js +124 -0
- package/dist/services/state.js.map +1 -0
- package/dist/services/wire.d.ts +60 -0
- package/dist/services/wire.d.ts.map +1 -0
- package/dist/services/wire.js +173 -0
- package/dist/services/wire.js.map +1 -0
- package/dist/types.d.ts +203 -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 +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consumer.js","sourceRoot":"","sources":["../../src/services/consumer.ts"],"names":[],"mappings":"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","sourcesContent":["import { awaitWithContext, BACKGROUND_CONTEXT } from \"../context/index.ts\";\nimport type { Op } from \"../delta/index.ts\";\nimport type {\n\tContext,\n\tJsonValue,\n\tRemoteServiceBinding,\n\tRemoteServiceBindingOptions,\n\tRemoteServiceTransport,\n\tService,\n\tServiceInstanceAddress,\n\tServiceInstanceSnapshot,\n\tServiceMemberSnapshot,\n\tServiceProviderUpdate,\n\tServiceSubscription,\n} from \"../types.ts\";\nimport { RemoteServiceError } from \"./errors.ts\";\nimport { ServiceSlot } from \"./handle.ts\";\nimport { InstanceDirectory, type InstanceDirectoryEntry } from \"./instances.ts\";\nimport { ReplicatedStateReplica, serviceDeliveryContext } from \"./state.ts\";\n\ntype ErrorReporter = (error: Error) => void;\ntype ServiceMemberKind = ServiceMemberSnapshot[\"kind\"];\n\nclass MemberSlot {\n\treadonly #serviceId: string;\n\treadonly #member: string;\n\treadonly #invoke: (args: readonly JsonValue[], context: Context) => Promise<JsonValue | undefined>;\n\treadonly #state: ReplicatedStateReplica;\n\treadonly #isActive: () => boolean;\n\treadonly #assertAccess: () => void;\n\treadonly value: unknown;\n\t#kind: ServiceMemberKind | undefined;\n\t#expectedKind: ServiceMemberKind | undefined;\n\n\tconstructor(\n\t\tserviceId: string,\n\t\tmember: string,\n\t\tinvoke: (args: readonly JsonValue[], context: Context) => Promise<JsonValue | undefined>,\n\t\tisActive: () => boolean,\n\t\tassertAccess: () => void,\n\t\treportError: ErrorReporter,\n\t) {\n\t\tthis.#serviceId = serviceId;\n\t\tthis.#member = member;\n\t\tthis.#invoke = invoke;\n\t\tthis.#isActive = isActive;\n\t\tthis.#assertAccess = assertAccess;\n\t\tthis.#state = new ReplicatedStateReplica(reportError);\n\t\tconst callable = (): void => {};\n\t\tthis.value = new Proxy(callable, {\n\t\t\tapply: (_target, _thisArg, args) => this.#call(args),\n\t\t\tget: (_target, property) => {\n\t\t\t\tif (property === \"value\") {\n\t\t\t\t\tthis.#assertAccess();\n\t\t\t\t\tthis.#expect(\"state\");\n\t\t\t\t\treturn this.#state.value;\n\t\t\t\t}\n\t\t\t\tif (property === \"subscribe\") return this.#subscribe.bind(this);\n\t\t\t\tif (property === Symbol.toStringTag) return \"RemoteServiceMember\";\n\t\t\t\tif (property === \"then\") return undefined;\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t});\n\t}\n\n\tsetDescription(kind: ServiceMemberKind): void {\n\t\tif (this.#kind !== undefined && this.#kind !== kind) {\n\t\t\tthrow new Error(`Remote service member ${this.#serviceId}.${this.#member} changed kind`);\n\t\t}\n\t\tthis.#kind = kind;\n\t\tif (this.#expectedKind !== undefined && this.#expectedKind !== kind) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_member_mismatch\",\n\t\t\t\t`Remote service member ${this.#serviceId}.${this.#member} is ${kind}, not ${this.#expectedKind}`,\n\t\t\t);\n\t\t}\n\t}\n\n\thydrate(sequence: number, ops: readonly Op[], context: Context): void {\n\t\tthis.setDescription(\"state\");\n\t\tthis.#state.hydrate(sequence, ops, context);\n\t}\n\n\tupdate(sequence: number, ops: readonly Op[], context: Context): void {\n\t\tthis.setDescription(\"state\");\n\t\tthis.#state.update(sequence, ops, context);\n\t}\n\n\tclear(): void {\n\t\tthis.#state.clear();\n\t}\n\n\t#subscribe(listener: (value: JsonValue, context: Context) => void): () => void {\n\t\tthis.#assertAccess();\n\t\tif (typeof listener !== \"function\") {\n\t\t\tthrow new TypeError(\"Replicated state subscription listener must be a function\");\n\t\t}\n\t\tthis.#expect(\"state\");\n\t\treturn this.#state.subscribe(listener);\n\t}\n\n\t#expect(kind: ServiceMemberKind): void {\n\t\tif (this.#expectedKind !== undefined && this.#expectedKind !== kind) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_member_mismatch\",\n\t\t\t\t`Remote service member ${this.#serviceId}.${this.#member} was used as two different kinds`,\n\t\t\t);\n\t\t}\n\t\tthis.#expectedKind = kind;\n\t\tif (this.#kind !== undefined && this.#kind !== kind) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_member_mismatch\",\n\t\t\t\t`Remote service member ${this.#serviceId}.${this.#member} is ${this.#kind}, not ${kind}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t#call(args: unknown[]): Promise<JsonValue | undefined> {\n\t\tthis.#assertAccess();\n\t\tthis.#expect(\"method\");\n\t\tif (!this.#isActive()) {\n\t\t\treturn Promise.reject(\n\t\t\t\tnew RemoteServiceError(\"service_stale_instance\", `Remote service ${this.#serviceId} binding is closed`),\n\t\t\t);\n\t\t}\n\t\tconst context = args.at(-1);\n\t\tif (!isContext(context)) {\n\t\t\treturn Promise.reject(\n\t\t\t\tnew RemoteServiceError(\n\t\t\t\t\t\"service_invalid_value\",\n\t\t\t\t\t`Remote service method ${this.#serviceId}.${this.#member} requires a trailing Context`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tconst businessArgs = args.slice(0, -1) as JsonValue[];\n\t\treturn this.#invoke(businessArgs, context);\n\t}\n}\n\nclass ServiceFacade {\n\treadonly #serviceId: string;\n\treadonly #address: ServiceInstanceAddress | undefined;\n\treadonly #transport: RemoteServiceTransport;\n\treadonly #reportError: ErrorReporter;\n\treadonly #slots = new Map<string, MemberSlot>();\n\treadonly #descriptions = new Map<string, ServiceMemberKind>();\n\treadonly #isActive: () => boolean;\n\treadonly #assertAccess: () => void;\n\treadonly proxy: object;\n\n\tconstructor(\n\t\tserviceId: string,\n\t\taddress: ServiceInstanceAddress | undefined,\n\t\ttransport: RemoteServiceTransport,\n\t\tisActive: () => boolean,\n\t\tassertAccess: () => void,\n\t\treportError: ErrorReporter,\n\t) {\n\t\tthis.#serviceId = serviceId;\n\t\tthis.#address = address;\n\t\tthis.#transport = transport;\n\t\tthis.#isActive = isActive;\n\t\tthis.#assertAccess = assertAccess;\n\t\tthis.#reportError = reportError;\n\t\tthis.proxy = new Proxy(Object.create(null) as object, {\n\t\t\tget: (_target, property) => {\n\t\t\t\tif (typeof property !== \"string\") return undefined;\n\t\t\t\treturn this.#slot(property).value;\n\t\t\t},\n\t\t});\n\t}\n\n\tinstall(snapshot: ServiceInstanceSnapshot, context: Context): void {\n\t\tif (!sameAddress(snapshot.instance, this.#address))\n\t\t\tthrow new Error(\"Remote service snapshot has the wrong address\");\n\t\tconst members = validateMembers(snapshot.members);\n\t\tfor (const name of this.#slots.keys()) {\n\t\t\tif (!members.has(name)) {\n\t\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\t\"service_member_not_found\",\n\t\t\t\t\t`Unknown remote service member ${this.#serviceId}.${name}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthis.#descriptions.clear();\n\t\tfor (const [name, member] of members) this.#descriptions.set(name, member.kind);\n\t\tfor (const member of members.values()) {\n\t\t\tconst slot = this.#slots.get(member.name);\n\t\t\tif (member.kind === \"state\") {\n\t\t\t\t(slot ?? this.#slot(member.name)).hydrate(member.sequence, member.ops, context);\n\t\t\t} else {\n\t\t\t\tslot?.setDescription(member.kind);\n\t\t\t}\n\t\t}\n\t}\n\n\tupdate(member: string, sequence: number, ops: readonly Op[], context: Context): void {\n\t\tif (this.#descriptions.get(member) !== \"state\") {\n\t\t\tthrow new Error(`Remote service update targets non-state member ${this.#serviceId}.${member}`);\n\t\t}\n\t\tthis.#slot(member).update(sequence, ops, context);\n\t}\n\n\tclear(): void {\n\t\tfor (const slot of this.#slots.values()) slot.clear();\n\t}\n\n\t#slot(member: string): MemberSlot {\n\t\tlet slot = this.#slots.get(member);\n\t\tif (slot !== undefined) return slot;\n\t\tslot = new MemberSlot(\n\t\t\tthis.#serviceId,\n\t\t\tmember,\n\t\t\t(args, context) =>\n\t\t\t\tthis.#transport.invoke(\n\t\t\t\t\t{\n\t\t\t\t\t\tserviceId: this.#serviceId,\n\t\t\t\t\t\t...(this.#address === undefined ? {} : { instance: this.#address }),\n\t\t\t\t\t\tmember,\n\t\t\t\t\t\targs,\n\t\t\t\t\t},\n\t\t\t\t\tcontext,\n\t\t\t\t),\n\t\t\tthis.#isActive,\n\t\t\tthis.#assertAccess,\n\t\t\tthis.#reportError,\n\t\t);\n\t\tconst kind = this.#descriptions.get(member);\n\t\tif (kind !== undefined) slot.setDescription(kind);\n\t\tthis.#slots.set(member, slot);\n\t\treturn slot;\n\t}\n}\n\ninterface SingletonBinding {\n\tfacade: ServiceFacade;\n\tsubscription?: ServiceSubscription;\n\tstarting?: Promise<void>;\n\tactive: boolean;\n\trevision: number;\n}\n\ninterface KeyedInstance extends InstanceDirectoryEntry {\n\treadonly facade: ServiceFacade;\n}\n\nclass KeyedBinding<T> {\n\treadonly #service: Service<T>;\n\treadonly #transport: RemoteServiceTransport;\n\treadonly #reportError: ErrorReporter;\n\treadonly #assertAccess: () => void;\n\treadonly #onEmpty: () => void;\n\treadonly #instances: InstanceDirectory<KeyedInstance>;\n\t#subscription: ServiceSubscription | undefined;\n\t#starting: Promise<void> | undefined;\n\t#closed = false;\n\t#bound: boolean;\n\t#revision = 0;\n\n\tconstructor(\n\t\tservice: Service<T>,\n\t\ttransport: RemoteServiceTransport,\n\t\treportError: ErrorReporter,\n\t\tassertAccess: () => void,\n\t\tonEmpty: () => void,\n\t\tbound: boolean,\n\t) {\n\t\tthis.#service = service;\n\t\tthis.#transport = transport;\n\t\tthis.#reportError = reportError;\n\t\tthis.#assertAccess = assertAccess;\n\t\tthis.#onEmpty = onEmpty;\n\t\tthis.#bound = bound;\n\t\tthis.#instances = new InstanceDirectory({ ready: false, onError: reportError });\n\t}\n\n\tobserve(handler: (service: T, context: Context) => void | Promise<void>): () => void {\n\t\tif (this.#closed) throw new Error(\"Remote keyed service binding is closed\");\n\t\tlet stopped = false;\n\t\tconst stop = this.#instances.observe<T>((service, context) => {\n\t\t\tconst slot = new ServiceSlot(this.#service.id, true);\n\t\t\tvoid slot.bind(service as object);\n\t\t\treturn handler(\n\t\t\t\tslot.view<T>(() => {\n\t\t\t\t\tthis.#assertAccess();\n\t\t\t\t\tif (stopped || context.abortSignal?.aborted) {\n\t\t\t\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\t\t\t\"service_stale_instance\",\n\t\t\t\t\t\t\t`Remote service ${this.#service.id} observation is closed`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\tcontext,\n\t\t\t);\n\t\t});\n\t\tif (this.#bound && this.#starting === undefined) {\n\t\t\tconst revision = this.#revision;\n\t\t\tconst starting = this.#start(revision);\n\t\t\tthis.#starting = starting;\n\t\t\tvoid starting.catch((error: unknown) => {\n\t\t\t\tif (!this.#closed && this.#revision === revision && this.#bound) this.#reportError(toError(error));\n\t\t\t});\n\t\t}\n\t\treturn () => {\n\t\t\tif (stopped) return;\n\t\t\tstopped = true;\n\t\t\tstop();\n\t\t\tif (this.#instances.observerCount === 0) this.#onEmpty();\n\t\t};\n\t}\n\n\tasync rebind(bound: boolean, context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#bound = bound;\n\t\tconst revision = ++this.#revision;\n\t\tawait this.#reset(context, false);\n\t\tif (this.#closed || this.#revision !== revision || this.#bound !== bound) return;\n\t\tif (bound && this.#instances.observerCount > 0) {\n\t\t\tconst starting = this.#start(revision);\n\t\t\tthis.#starting = starting;\n\t\t\tawait starting;\n\t\t}\n\t}\n\n\tready(): Promise<void> {\n\t\treturn this.#starting ?? Promise.resolve();\n\t}\n\n\tasync close(context: Context): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#revision += 1;\n\t\tawait this.#reset(context, true);\n\t\tthis.#instances.dispose();\n\t}\n\n\tasync #reset(context: Context, waitForStarting: boolean): Promise<void> {\n\t\tthis.#instances.reset();\n\t\tconst starting = this.#starting;\n\t\tthis.#starting = undefined;\n\t\tconst subscription = this.#subscription;\n\t\tthis.#subscription = undefined;\n\t\tawait Promise.all([\n\t\t\twaitForStarting ? starting?.catch(() => {}) : undefined,\n\t\t\tsubscription === undefined ? undefined : subscription.close(context),\n\t\t]);\n\t}\n\n\tasync #start(revision: number): Promise<void> {\n\t\tconst subscription = await this.#transport.subscribe(\n\t\t\tthis.#service.id,\n\t\t\t\"keyed\",\n\t\t\t(update, context) => {\n\t\t\t\tif (this.#revision === revision) this.#update(update, context);\n\t\t\t},\n\t\t\tBACKGROUND_CONTEXT,\n\t\t);\n\t\tif (this.#closed || !this.#bound || this.#revision !== revision) {\n\t\t\tawait subscription.close(BACKGROUND_CONTEXT);\n\t\t\treturn;\n\t\t}\n\t\tthis.#subscription = subscription;\n\t\tif (subscription.snapshot.mode !== \"keyed\" || subscription.snapshot.serviceId !== this.#service.id) {\n\t\t\tthrow new Error(`Remote service ${this.#service.id} returned the wrong keyed snapshot`);\n\t\t}\n\t\tfor (const snapshot of subscription.snapshot.instances) this.#spawn(snapshot, serviceDeliveryContext());\n\t\tsubscription.activate();\n\t\tthis.#instances.ready();\n\t}\n\n\t#update(update: ServiceProviderUpdate, context: Context): void {\n\t\tif (this.#closed) return;\n\t\ttry {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase \"unavailable\":\n\t\t\t\tcase \"replaced\":\n\t\t\t\t\tthrow new Error(\"Keyed service received a singleton lifecycle update\");\n\t\t\t\tcase \"spawned\":\n\t\t\t\t\tthis.#spawn(update.instance, context);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"closed\": {\n\t\t\t\t\tconst instance = this.#instances.get(update.instance.key);\n\t\t\t\t\tif (instance?.generation === update.instance.generation) this.#instances.remove(instance);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"state\": {\n\t\t\t\t\tif (update.instance === undefined) throw new Error(\"Keyed state update has no instance address\");\n\t\t\t\t\tconst instance = this.#instances.get(update.instance.key);\n\t\t\t\t\tif (instance?.generation !== update.instance.generation) return;\n\t\t\t\t\tinstance.facade.update(update.member, update.sequence, update.ops, context);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.#reportError(toError(error));\n\t\t}\n\t}\n\n\t#spawn(snapshot: ServiceInstanceSnapshot, context: Context): void {\n\t\tconst address = snapshot.instance;\n\t\tif (address === undefined) throw new Error(\"Keyed service instance snapshot has no address\");\n\t\tlet active = true;\n\t\tconst facade = new ServiceFacade(\n\t\t\tthis.#service.id,\n\t\t\taddress,\n\t\t\tthis.#transport,\n\t\t\t() => active && !this.#closed,\n\t\t\tthis.#assertAccess,\n\t\t\tthis.#reportError,\n\t\t);\n\t\tfacade.install(snapshot, context);\n\t\tthis.#instances.replace({\n\t\t\tkey: address.key,\n\t\t\tgeneration: address.generation,\n\t\t\tservice: facade.proxy,\n\t\t\tfacade,\n\t\t\tdeactivate: () => {\n\t\t\t\tactive = false;\n\t\t\t\tfacade.clear();\n\t\t\t},\n\t\t});\n\t}\n}\n\nexport class RemoteServiceBindingImpl implements RemoteServiceBinding {\n\treadonly #transport: RemoteServiceTransport;\n\treadonly #allowlist = new Set<string>();\n\treadonly #reportError: ErrorReporter;\n\treadonly #modes = new Map<string, \"singleton\" | \"keyed\">();\n\treadonly #assertAccess: () => void;\n\treadonly #singletons = new Map<string, SingletonBinding>();\n\treadonly #keyed = new Map<string, KeyedBinding<unknown>>();\n\t#bound: boolean;\n\t#readinessRevision = 0;\n\t#bindingTransition = Promise.resolve();\n\t#disposed = false;\n\n\tconstructor(options: RemoteServiceBindingOptions) {\n\t\tthis.#transport = options.transport;\n\t\tconst ids = options.services.map(({ id }) => id);\n\t\tif (new Set(ids).size !== ids.length) throw new TypeError(\"Remote service binding has duplicate service IDs\");\n\t\tfor (const id of ids) this.#allowlist.add(id);\n\t\tthis.#reportError = options.onError ?? (() => {});\n\t\tthis.#assertAccess = options.assertAccess ?? (() => {});\n\t\tthis.#bound = options.bound ?? true;\n\t}\n\n\tuse<T>(service: Service<T>): T {\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAvailable(service.id, \"singleton\");\n\t\tlet binding = this.#singletons.get(service.id);\n\t\tif (binding !== undefined) return binding.facade.proxy as T;\n\t\tbinding = { facade: undefined as unknown as ServiceFacade, active: true, revision: 0 };\n\t\tbinding.facade = new ServiceFacade(\n\t\t\tservice.id,\n\t\t\tundefined,\n\t\t\tthis.#transport,\n\t\t\t() => binding!.active && !this.#disposed && this.#bound,\n\t\t\t() => this.#assertHandleAccess(),\n\t\t\tthis.#reportError,\n\t\t);\n\t\tthis.#singletons.set(service.id, binding);\n\t\tthis.#readinessRevision += 1;\n\t\tif (this.#bound) {\n\t\t\tconst revision = binding.revision;\n\t\t\tconst starting = this.#startSingleton(service.id, binding, revision);\n\t\t\tbinding.starting = starting;\n\t\t\tvoid starting.catch((error: unknown) => {\n\t\t\t\tif (binding.active && binding.revision === revision && !this.#disposed && this.#bound) {\n\t\t\t\t\tthis.#reportError(toError(error));\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn binding.facade.proxy as T;\n\t}\n\n\tobserve<T>(service: Service<T>, handler: (service: T, context: Context) => void | Promise<void>): () => void {\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAvailable(service.id, \"keyed\");\n\t\tlet binding = this.#keyed.get(service.id) as KeyedBinding<T> | undefined;\n\t\tif (binding === undefined) {\n\t\t\tbinding = new KeyedBinding(\n\t\t\t\tservice,\n\t\t\t\tthis.#transport,\n\t\t\t\tthis.#reportError,\n\t\t\t\t() => this.#assertHandleAccess(),\n\t\t\t\t() => {\n\t\t\t\t\tif (this.#keyed.get(service.id) !== binding) return;\n\t\t\t\t\tthis.#keyed.delete(service.id);\n\t\t\t\t\tthis.#readinessRevision += 1;\n\t\t\t\t\tvoid binding!.close(BACKGROUND_CONTEXT).catch(this.#reportError);\n\t\t\t\t},\n\t\t\t\tthis.#bound,\n\t\t\t);\n\t\t\tthis.#keyed.set(service.id, binding as KeyedBinding<unknown>);\n\t\t\tthis.#readinessRevision += 1;\n\t\t}\n\t\treturn binding.observe(handler);\n\t}\n\n\tasync ready(context: Context): Promise<void> {\n\t\tif (this.#disposed) throw new Error(\"Remote service binding is disposed\");\n\t\twhile (true) {\n\t\t\tconst revision = this.#readinessRevision;\n\t\t\tconst starts = [\n\t\t\t\tthis.#bindingTransition,\n\t\t\t\t...[...this.#singletons.values()].flatMap((binding) =>\n\t\t\t\t\tbinding.starting === undefined ? [] : [binding.starting],\n\t\t\t\t),\n\t\t\t\t...[...this.#keyed.values()].map((binding) => binding.ready()),\n\t\t\t];\n\t\t\tawait awaitWithContext(\n\t\t\t\tPromise.all(starts).then(() => undefined),\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tif (this.#disposed) throw new Error(\"Remote service binding is disposed\");\n\t\t\tif (revision === this.#readinessRevision) return;\n\t\t}\n\t}\n\n\tasync rebind(bound: boolean, context: Context): Promise<void> {\n\t\tif (this.#disposed) throw new Error(\"Remote service binding is disposed\");\n\t\tthis.#bound = bound;\n\t\tthis.#readinessRevision += 1;\n\t\tconst transitions: Promise<void>[] = [];\n\t\tfor (const [serviceId, binding] of this.#singletons) {\n\t\t\tbinding.revision += 1;\n\t\t\tbinding.facade.clear();\n\t\t\tconst subscription = binding.subscription;\n\t\t\tdelete binding.subscription;\n\t\t\tconst revision = binding.revision;\n\t\t\tconst starting = (async () => {\n\t\t\t\tawait subscription?.close(context);\n\t\t\t\tif (bound) await this.#startSingleton(serviceId, binding, revision);\n\t\t\t})();\n\t\t\tbinding.starting = starting;\n\t\t\ttransitions.push(starting);\n\t\t}\n\t\tfor (const binding of this.#keyed.values()) transitions.push(binding.rebind(bound, context));\n\t\tconst completion = (async () => {\n\t\t\tconst results = await Promise.allSettled(transitions);\n\t\t\tconst errors = results.filter((result): result is PromiseRejectedResult => result.status === \"rejected\");\n\t\t\tif (errors.length > 0)\n\t\t\t\tthrow new AggregateError(\n\t\t\t\t\terrors.map(({ reason }) => reason),\n\t\t\t\t\t\"Failed to rebind services\",\n\t\t\t\t);\n\t\t})();\n\t\tthis.#bindingTransition = completion;\n\t\tawait completion;\n\t}\n\n\tasync dispose(context: Context): Promise<void> {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tconst closes: Promise<void>[] = [];\n\t\tfor (const binding of this.#singletons.values()) {\n\t\t\tbinding.active = false;\n\t\t\tbinding.facade.clear();\n\t\t\tif (binding.starting) closes.push(binding.starting.catch(() => {}));\n\t\t\tif (binding.subscription) closes.push(Promise.resolve(binding.subscription.close(context)));\n\t\t}\n\t\tfor (const binding of this.#keyed.values()) closes.push(binding.close(context));\n\t\tthis.#singletons.clear();\n\t\tthis.#keyed.clear();\n\t\tconst results = await Promise.allSettled(closes);\n\t\tconst errors = results.filter((result): result is PromiseRejectedResult => result.status === \"rejected\");\n\t\tif (errors.length > 0)\n\t\t\tthrow new AggregateError(\n\t\t\t\terrors.map(({ reason }) => reason),\n\t\t\t\t\"Failed to dispose services\",\n\t\t\t);\n\t}\n\n\tasync #startSingleton(serviceId: string, binding: SingletonBinding, revision: number): Promise<void> {\n\t\tconst subscription = await this.#transport.subscribe(\n\t\t\tserviceId,\n\t\t\t\"singleton\",\n\t\t\t(update, context) => {\n\t\t\t\tif (!binding.active || binding.revision !== revision) return;\n\t\t\t\ttry {\n\t\t\t\t\tif (update.type === \"unavailable\") {\n\t\t\t\t\t\tbinding.facade.clear();\n\t\t\t\t\t} else if (update.type === \"replaced\") {\n\t\t\t\t\t\tif (update.snapshot.instance !== undefined) {\n\t\t\t\t\t\t\tthrow new Error(\"Singleton replacement has an instance address\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbinding.facade.install(update.snapshot, context);\n\t\t\t\t\t} else if (update.type === \"state\" && update.instance === undefined) {\n\t\t\t\t\t\tbinding.facade.update(update.member, update.sequence, update.ops, context);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.#reportError(toError(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\tBACKGROUND_CONTEXT,\n\t\t);\n\t\tif (!binding.active || this.#disposed || !this.#bound || binding.revision !== revision) {\n\t\t\tawait subscription.close(BACKGROUND_CONTEXT);\n\t\t\treturn;\n\t\t}\n\t\tbinding.subscription = subscription;\n\t\tconst snapshot = subscription.snapshot;\n\t\tif (snapshot.mode !== \"singleton\" || snapshot.serviceId !== serviceId || snapshot.instances.length !== 1) {\n\t\t\tthrow new Error(`Remote service ${serviceId} returned an invalid singleton snapshot`);\n\t\t}\n\t\tbinding.facade.install(snapshot.instances[0]!, serviceDeliveryContext());\n\t\tsubscription.activate();\n\t}\n\n\t#assertHandleAccess(): void {\n\t\tif (this.#disposed) throw new Error(\"Remote service binding is disposed\");\n\t\tthis.#assertAccess();\n\t}\n\n\t#assertRemotable(service: { readonly id: string; readonly local: boolean }): void {\n\t\tif (service.local) throw new RemoteServiceError(\"service_not_allowed\", `Service ${service.id} is process-local`);\n\t}\n\n\t#assertAvailable(serviceId: string, mode: \"singleton\" | \"keyed\"): void {\n\t\tif (this.#disposed) throw new Error(\"Remote service binding is disposed\");\n\t\tif (!this.#allowlist.has(serviceId)) {\n\t\t\tthrow new RemoteServiceError(\"service_not_allowed\", `Remote service ${serviceId} is not allowlisted`);\n\t\t}\n\t\tconst existing = this.#modes.get(serviceId);\n\t\tif (existing !== undefined && existing !== mode) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_mode_mismatch\",\n\t\t\t\t`Remote service ${serviceId} is already used as ${existing}`,\n\t\t\t);\n\t\t}\n\t\tthis.#modes.set(serviceId, mode);\n\t}\n}\n\nfunction validateMembers(members: readonly ServiceMemberSnapshot[]): ReadonlyMap<string, ServiceMemberSnapshot> {\n\tconst result = new Map<string, ServiceMemberSnapshot>();\n\tfor (const member of members) {\n\t\tif (member.name.length === 0 || result.has(member.name)) {\n\t\t\tthrow new Error(\"Remote service has invalid member descriptions\");\n\t\t}\n\t\tresult.set(member.name, member);\n\t}\n\treturn result;\n}\n\nfunction sameAddress(left: ServiceInstanceAddress | undefined, right: ServiceInstanceAddress | undefined): boolean {\n\tif (left === undefined || right === undefined) return left === right;\n\treturn left.key === right.key && left.generation === right.generation;\n}\n\nfunction isContext(value: unknown): value is Context {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst candidate = value as Partial<Context>;\n\treturn typeof candidate.value === \"function\" && typeof candidate.toString === \"function\";\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const REMOTE_SERVICE_ERROR_CODES: readonly ["service_not_allowed", "service_not_found", "service_mode_mismatch", "service_member_not_found", "service_member_mismatch", "service_instance_not_found", "service_stale_instance", "service_invalid_value"];
|
|
2
|
+
export type RemoteServiceErrorCode = (typeof REMOTE_SERVICE_ERROR_CODES)[number];
|
|
3
|
+
export declare function isRemoteServiceErrorCode(value: unknown): value is RemoteServiceErrorCode;
|
|
4
|
+
export declare class RemoteServiceError extends Error {
|
|
5
|
+
readonly code: RemoteServiceErrorCode;
|
|
6
|
+
constructor(code: RemoteServiceErrorCode, message: string);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/services/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B,wNAS7B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAExF;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IAEtC,YAAY,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,EAIxD;CACD","sourcesContent":["export const REMOTE_SERVICE_ERROR_CODES = [\n\t\"service_not_allowed\",\n\t\"service_not_found\",\n\t\"service_mode_mismatch\",\n\t\"service_member_not_found\",\n\t\"service_member_mismatch\",\n\t\"service_instance_not_found\",\n\t\"service_stale_instance\",\n\t\"service_invalid_value\",\n] as const;\n\nexport type RemoteServiceErrorCode = (typeof REMOTE_SERVICE_ERROR_CODES)[number];\n\nexport function isRemoteServiceErrorCode(value: unknown): value is RemoteServiceErrorCode {\n\treturn typeof value === \"string\" && REMOTE_SERVICE_ERROR_CODES.includes(value as RemoteServiceErrorCode);\n}\n\nexport class RemoteServiceError extends Error {\n\treadonly code: RemoteServiceErrorCode;\n\n\tconstructor(code: RemoteServiceErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"RemoteServiceError\";\n\t\tthis.code = code;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const REMOTE_SERVICE_ERROR_CODES = [
|
|
2
|
+
"service_not_allowed",
|
|
3
|
+
"service_not_found",
|
|
4
|
+
"service_mode_mismatch",
|
|
5
|
+
"service_member_not_found",
|
|
6
|
+
"service_member_mismatch",
|
|
7
|
+
"service_instance_not_found",
|
|
8
|
+
"service_stale_instance",
|
|
9
|
+
"service_invalid_value",
|
|
10
|
+
];
|
|
11
|
+
export function isRemoteServiceErrorCode(value) {
|
|
12
|
+
return typeof value === "string" && REMOTE_SERVICE_ERROR_CODES.includes(value);
|
|
13
|
+
}
|
|
14
|
+
export class RemoteServiceError extends Error {
|
|
15
|
+
code;
|
|
16
|
+
constructor(code, message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = "RemoteServiceError";
|
|
19
|
+
this.code = code;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/services/errors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACzC,qBAAqB;IACrB,mBAAmB;IACnB,uBAAuB;IACvB,0BAA0B;IAC1B,yBAAyB;IACzB,4BAA4B;IAC5B,wBAAwB;IACxB,uBAAuB;CACd,CAAC;AAIX,MAAM,UAAU,wBAAwB,CAAC,KAAc,EAAmC;IACzF,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,0BAA0B,CAAC,QAAQ,CAAC,KAA+B,CAAC,CAAC;AAAA,CACzG;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACnC,IAAI,CAAyB;IAEtC,YAAY,IAA4B,EAAE,OAAe,EAAE;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAAA,CACjB;CACD","sourcesContent":["export const REMOTE_SERVICE_ERROR_CODES = [\n\t\"service_not_allowed\",\n\t\"service_not_found\",\n\t\"service_mode_mismatch\",\n\t\"service_member_not_found\",\n\t\"service_member_mismatch\",\n\t\"service_instance_not_found\",\n\t\"service_stale_instance\",\n\t\"service_invalid_value\",\n] as const;\n\nexport type RemoteServiceErrorCode = (typeof REMOTE_SERVICE_ERROR_CODES)[number];\n\nexport function isRemoteServiceErrorCode(value: unknown): value is RemoteServiceErrorCode {\n\treturn typeof value === \"string\" && REMOTE_SERVICE_ERROR_CODES.includes(value as RemoteServiceErrorCode);\n}\n\nexport class RemoteServiceError extends Error {\n\treadonly code: RemoteServiceErrorCode;\n\n\tconstructor(code: RemoteServiceErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"RemoteServiceError\";\n\t\tthis.code = code;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface ResolvedValue {
|
|
2
|
+
readonly value: unknown;
|
|
3
|
+
readonly receiver: object;
|
|
4
|
+
}
|
|
5
|
+
/** Host-owned mutable target with consumer-owned guarded views. */
|
|
6
|
+
export declare class ServiceSlot {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(serviceId: string, wrapObjects: boolean);
|
|
9
|
+
view<T>(assertAccess: () => void): T;
|
|
10
|
+
bind(implementation: object): void;
|
|
11
|
+
unbind(): void;
|
|
12
|
+
resolve(property: PropertyKey, assertAccess: () => void): ResolvedValue;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=handle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle.d.ts","sourceRoot":"","sources":["../../src/services/handle.ts"],"names":[],"mappings":"AAAA,UAAU,aAAa;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAID,mEAAmE;AACnE,qBAAa,WAAW;;IAKvB,YAAY,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAGlD;IAED,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,IAAI,GAAG,CAAC,CAEnC;IAED,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAEjC;IAED,MAAM,IAAI,IAAI,CAEb;IAED,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,IAAI,GAAG,aAAa,CAQtE;CACD","sourcesContent":["interface ResolvedValue {\n\treadonly value: unknown;\n\treadonly receiver: object;\n}\n\ntype ValueResolver = () => ResolvedValue;\n\n/** Host-owned mutable target with consumer-owned guarded views. */\nexport class ServiceSlot {\n\treadonly #serviceId: string;\n\treadonly #wrapObjects: boolean;\n\t#implementation: object | undefined;\n\n\tconstructor(serviceId: string, wrapObjects: boolean) {\n\t\tthis.#serviceId = serviceId;\n\t\tthis.#wrapObjects = wrapObjects;\n\t}\n\n\tview<T>(assertAccess: () => void): T {\n\t\treturn new ServiceView(this, assertAccess, this.#wrapObjects).proxy as T;\n\t}\n\n\tbind(implementation: object): void {\n\t\tthis.#implementation = implementation;\n\t}\n\n\tunbind(): void {\n\t\tthis.#implementation = undefined;\n\t}\n\n\tresolve(property: PropertyKey, assertAccess: () => void): ResolvedValue {\n\t\tassertAccess();\n\t\tconst implementation = this.#implementation;\n\t\tif (implementation === undefined) throw new Error(`Service ${this.#serviceId} is disconnected`);\n\t\treturn {\n\t\t\tvalue: Reflect.get(implementation, property, implementation),\n\t\t\treceiver: implementation,\n\t\t};\n\t}\n}\n\nclass ServiceView {\n\treadonly #slot: ServiceSlot;\n\treadonly #assertAccess: () => void;\n\treadonly #wrapObjects: boolean;\n\treadonly #members = new Map<PropertyKey, ValueView>();\n\treadonly proxy: object;\n\n\tconstructor(slot: ServiceSlot, assertAccess: () => void, wrapObjects: boolean) {\n\t\tthis.#slot = slot;\n\t\tthis.#assertAccess = assertAccess;\n\t\tthis.#wrapObjects = wrapObjects;\n\t\tthis.proxy = new Proxy(Object.create(null) as object, {\n\t\t\tget: (_target, property) => this.#getMember(property),\n\t\t});\n\t}\n\n\t#getMember(property: PropertyKey): unknown {\n\t\tconst resolve = (): ResolvedValue => this.#slot.resolve(property, this.#assertAccess);\n\t\tconst current = resolve().value;\n\t\tif (!isObject(current) || (typeof current !== \"function\" && !this.#wrapObjects)) return current;\n\t\tlet member = this.#members.get(property);\n\t\tif (member === undefined) {\n\t\t\tmember = new ValueView(resolve, typeof current === \"function\");\n\t\t\tthis.#members.set(property, member);\n\t\t}\n\t\treturn member.proxy;\n\t}\n}\n\nclass ValueView {\n\treadonly #resolve: ValueResolver;\n\treadonly #children = new Map<PropertyKey, ValueView>();\n\treadonly proxy: object;\n\n\tconstructor(resolve: ValueResolver, callable: boolean) {\n\t\tthis.#resolve = resolve;\n\t\tconst target: object = callable ? () => undefined : Object.create(null);\n\t\tthis.proxy = new Proxy(target, {\n\t\t\tapply: (_target, _thisArg, args) => this.#invoke(args),\n\t\t\tget: (_target, property) => this.#get(property),\n\t\t});\n\t}\n\n\t#invoke(args: unknown[]): unknown {\n\t\tconst { value, receiver } = this.#resolve();\n\t\tif (typeof value !== \"function\") throw new TypeError(\"Service member is not callable\");\n\t\treturn Reflect.apply(value, receiver, args);\n\t}\n\n\t#get(property: PropertyKey): unknown {\n\t\tconst resolve = (): ResolvedValue => {\n\t\t\tconst parent = this.#resolve();\n\t\t\tif (!isObject(parent.value)) throw new TypeError(\"Service member does not have properties\");\n\t\t\treturn {\n\t\t\t\tvalue: Reflect.get(parent.value, property, parent.value),\n\t\t\t\treceiver: parent.value,\n\t\t\t};\n\t\t};\n\t\tconst current = resolve().value;\n\t\tif (typeof current !== \"function\") return current;\n\t\tlet child = this.#children.get(property);\n\t\tif (child === undefined) {\n\t\t\tchild = new ValueView(resolve, true);\n\t\t\tthis.#children.set(property, child);\n\t\t}\n\t\treturn child.proxy;\n\t}\n}\n\nfunction isObject(value: unknown): value is object {\n\treturn (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n}\n"]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/** Host-owned mutable target with consumer-owned guarded views. */
|
|
2
|
+
export class ServiceSlot {
|
|
3
|
+
#serviceId;
|
|
4
|
+
#wrapObjects;
|
|
5
|
+
#implementation;
|
|
6
|
+
constructor(serviceId, wrapObjects) {
|
|
7
|
+
this.#serviceId = serviceId;
|
|
8
|
+
this.#wrapObjects = wrapObjects;
|
|
9
|
+
}
|
|
10
|
+
view(assertAccess) {
|
|
11
|
+
return new ServiceView(this, assertAccess, this.#wrapObjects).proxy;
|
|
12
|
+
}
|
|
13
|
+
bind(implementation) {
|
|
14
|
+
this.#implementation = implementation;
|
|
15
|
+
}
|
|
16
|
+
unbind() {
|
|
17
|
+
this.#implementation = undefined;
|
|
18
|
+
}
|
|
19
|
+
resolve(property, assertAccess) {
|
|
20
|
+
assertAccess();
|
|
21
|
+
const implementation = this.#implementation;
|
|
22
|
+
if (implementation === undefined)
|
|
23
|
+
throw new Error(`Service ${this.#serviceId} is disconnected`);
|
|
24
|
+
return {
|
|
25
|
+
value: Reflect.get(implementation, property, implementation),
|
|
26
|
+
receiver: implementation,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
class ServiceView {
|
|
31
|
+
#slot;
|
|
32
|
+
#assertAccess;
|
|
33
|
+
#wrapObjects;
|
|
34
|
+
#members = new Map();
|
|
35
|
+
proxy;
|
|
36
|
+
constructor(slot, assertAccess, wrapObjects) {
|
|
37
|
+
this.#slot = slot;
|
|
38
|
+
this.#assertAccess = assertAccess;
|
|
39
|
+
this.#wrapObjects = wrapObjects;
|
|
40
|
+
this.proxy = new Proxy(Object.create(null), {
|
|
41
|
+
get: (_target, property) => this.#getMember(property),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
#getMember(property) {
|
|
45
|
+
const resolve = () => this.#slot.resolve(property, this.#assertAccess);
|
|
46
|
+
const current = resolve().value;
|
|
47
|
+
if (!isObject(current) || (typeof current !== "function" && !this.#wrapObjects))
|
|
48
|
+
return current;
|
|
49
|
+
let member = this.#members.get(property);
|
|
50
|
+
if (member === undefined) {
|
|
51
|
+
member = new ValueView(resolve, typeof current === "function");
|
|
52
|
+
this.#members.set(property, member);
|
|
53
|
+
}
|
|
54
|
+
return member.proxy;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
class ValueView {
|
|
58
|
+
#resolve;
|
|
59
|
+
#children = new Map();
|
|
60
|
+
proxy;
|
|
61
|
+
constructor(resolve, callable) {
|
|
62
|
+
this.#resolve = resolve;
|
|
63
|
+
const target = callable ? () => undefined : Object.create(null);
|
|
64
|
+
this.proxy = new Proxy(target, {
|
|
65
|
+
apply: (_target, _thisArg, args) => this.#invoke(args),
|
|
66
|
+
get: (_target, property) => this.#get(property),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
#invoke(args) {
|
|
70
|
+
const { value, receiver } = this.#resolve();
|
|
71
|
+
if (typeof value !== "function")
|
|
72
|
+
throw new TypeError("Service member is not callable");
|
|
73
|
+
return Reflect.apply(value, receiver, args);
|
|
74
|
+
}
|
|
75
|
+
#get(property) {
|
|
76
|
+
const resolve = () => {
|
|
77
|
+
const parent = this.#resolve();
|
|
78
|
+
if (!isObject(parent.value))
|
|
79
|
+
throw new TypeError("Service member does not have properties");
|
|
80
|
+
return {
|
|
81
|
+
value: Reflect.get(parent.value, property, parent.value),
|
|
82
|
+
receiver: parent.value,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
const current = resolve().value;
|
|
86
|
+
if (typeof current !== "function")
|
|
87
|
+
return current;
|
|
88
|
+
let child = this.#children.get(property);
|
|
89
|
+
if (child === undefined) {
|
|
90
|
+
child = new ValueView(resolve, true);
|
|
91
|
+
this.#children.set(property, child);
|
|
92
|
+
}
|
|
93
|
+
return child.proxy;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function isObject(value) {
|
|
97
|
+
return (typeof value === "object" && value !== null) || typeof value === "function";
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=handle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle.js","sourceRoot":"","sources":["../../src/services/handle.ts"],"names":[],"mappings":"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","sourcesContent":["interface ResolvedValue {\n\treadonly value: unknown;\n\treadonly receiver: object;\n}\n\ntype ValueResolver = () => ResolvedValue;\n\n/** Host-owned mutable target with consumer-owned guarded views. */\nexport class ServiceSlot {\n\treadonly #serviceId: string;\n\treadonly #wrapObjects: boolean;\n\t#implementation: object | undefined;\n\n\tconstructor(serviceId: string, wrapObjects: boolean) {\n\t\tthis.#serviceId = serviceId;\n\t\tthis.#wrapObjects = wrapObjects;\n\t}\n\n\tview<T>(assertAccess: () => void): T {\n\t\treturn new ServiceView(this, assertAccess, this.#wrapObjects).proxy as T;\n\t}\n\n\tbind(implementation: object): void {\n\t\tthis.#implementation = implementation;\n\t}\n\n\tunbind(): void {\n\t\tthis.#implementation = undefined;\n\t}\n\n\tresolve(property: PropertyKey, assertAccess: () => void): ResolvedValue {\n\t\tassertAccess();\n\t\tconst implementation = this.#implementation;\n\t\tif (implementation === undefined) throw new Error(`Service ${this.#serviceId} is disconnected`);\n\t\treturn {\n\t\t\tvalue: Reflect.get(implementation, property, implementation),\n\t\t\treceiver: implementation,\n\t\t};\n\t}\n}\n\nclass ServiceView {\n\treadonly #slot: ServiceSlot;\n\treadonly #assertAccess: () => void;\n\treadonly #wrapObjects: boolean;\n\treadonly #members = new Map<PropertyKey, ValueView>();\n\treadonly proxy: object;\n\n\tconstructor(slot: ServiceSlot, assertAccess: () => void, wrapObjects: boolean) {\n\t\tthis.#slot = slot;\n\t\tthis.#assertAccess = assertAccess;\n\t\tthis.#wrapObjects = wrapObjects;\n\t\tthis.proxy = new Proxy(Object.create(null) as object, {\n\t\t\tget: (_target, property) => this.#getMember(property),\n\t\t});\n\t}\n\n\t#getMember(property: PropertyKey): unknown {\n\t\tconst resolve = (): ResolvedValue => this.#slot.resolve(property, this.#assertAccess);\n\t\tconst current = resolve().value;\n\t\tif (!isObject(current) || (typeof current !== \"function\" && !this.#wrapObjects)) return current;\n\t\tlet member = this.#members.get(property);\n\t\tif (member === undefined) {\n\t\t\tmember = new ValueView(resolve, typeof current === \"function\");\n\t\t\tthis.#members.set(property, member);\n\t\t}\n\t\treturn member.proxy;\n\t}\n}\n\nclass ValueView {\n\treadonly #resolve: ValueResolver;\n\treadonly #children = new Map<PropertyKey, ValueView>();\n\treadonly proxy: object;\n\n\tconstructor(resolve: ValueResolver, callable: boolean) {\n\t\tthis.#resolve = resolve;\n\t\tconst target: object = callable ? () => undefined : Object.create(null);\n\t\tthis.proxy = new Proxy(target, {\n\t\t\tapply: (_target, _thisArg, args) => this.#invoke(args),\n\t\t\tget: (_target, property) => this.#get(property),\n\t\t});\n\t}\n\n\t#invoke(args: unknown[]): unknown {\n\t\tconst { value, receiver } = this.#resolve();\n\t\tif (typeof value !== \"function\") throw new TypeError(\"Service member is not callable\");\n\t\treturn Reflect.apply(value, receiver, args);\n\t}\n\n\t#get(property: PropertyKey): unknown {\n\t\tconst resolve = (): ResolvedValue => {\n\t\t\tconst parent = this.#resolve();\n\t\t\tif (!isObject(parent.value)) throw new TypeError(\"Service member does not have properties\");\n\t\t\treturn {\n\t\t\t\tvalue: Reflect.get(parent.value, property, parent.value),\n\t\t\t\treceiver: parent.value,\n\t\t\t};\n\t\t};\n\t\tconst current = resolve().value;\n\t\tif (typeof current !== \"function\") return current;\n\t\tlet child = this.#children.get(property);\n\t\tif (child === undefined) {\n\t\t\tchild = new ValueView(resolve, true);\n\t\t\tthis.#children.set(property, child);\n\t\t}\n\t\treturn child.proxy;\n\t}\n}\n\nfunction isObject(value: unknown): value is object {\n\treturn (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Context } from "../types.ts";
|
|
2
|
+
export interface InstanceDirectoryEntry {
|
|
3
|
+
readonly key: string;
|
|
4
|
+
readonly generation: number;
|
|
5
|
+
readonly service: object;
|
|
6
|
+
deactivate(): void;
|
|
7
|
+
}
|
|
8
|
+
/** Owns keyed instance lifetime and the cancellable tasks observing those instances. */
|
|
9
|
+
export declare class InstanceDirectory<TEntry extends InstanceDirectoryEntry> {
|
|
10
|
+
#private;
|
|
11
|
+
constructor(options: {
|
|
12
|
+
readonly ready: boolean;
|
|
13
|
+
readonly onError: (error: Error) => void;
|
|
14
|
+
});
|
|
15
|
+
get observerCount(): number;
|
|
16
|
+
get(key: string): TEntry | undefined;
|
|
17
|
+
insert(entry: TEntry): void;
|
|
18
|
+
replace(entry: TEntry): void;
|
|
19
|
+
remove(entry: TEntry): void;
|
|
20
|
+
ready(): void;
|
|
21
|
+
reset(): void;
|
|
22
|
+
observe<T>(handler: (service: T, context: Context) => void | Promise<void>): () => void;
|
|
23
|
+
dispose(): void;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=instances.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instances.d.ts","sourceRoot":"","sources":["../../src/services/instances.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,UAAU,IAAI,IAAI,CAAC;CACnB;AAQD,wFAAwF;AACxF,qBAAa,iBAAiB,CAAC,MAAM,SAAS,sBAAsB;;IAOnE,YAAY,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;KAAE,EAGzF;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnC;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAO1B;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAW3B;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG1B;IAED,KAAK,IAAI,IAAI,CAKZ;IAED,KAAK,IAAI,IAAI,CAIZ;IAED,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAkBtF;IAED,OAAO,IAAI,IAAI,CAad;CAgCD","sourcesContent":["import { BACKGROUND_CONTEXT, withCancel } from \"../context/index.ts\";\nimport type { Context } from \"../types.ts\";\n\nexport interface InstanceDirectoryEntry {\n\treadonly key: string;\n\treadonly generation: number;\n\treadonly service: object;\n\tdeactivate(): void;\n}\n\ninterface Observer {\n\treadonly handler: (service: object, context: Context) => void | Promise<void>;\n\treadonly tasks: Map<InstanceDirectoryEntry, { readonly cancel: (reason?: unknown) => void }>;\n\tclosed: boolean;\n}\n\n/** Owns keyed instance lifetime and the cancellable tasks observing those instances. */\nexport class InstanceDirectory<TEntry extends InstanceDirectoryEntry> {\n\treadonly #entries = new Map<string, TEntry>();\n\treadonly #observers = new Set<Observer>();\n\treadonly #reportError: (error: Error) => void;\n\t#ready: boolean;\n\t#disposed = false;\n\n\tconstructor(options: { readonly ready: boolean; readonly onError: (error: Error) => void }) {\n\t\tthis.#ready = options.ready;\n\t\tthis.#reportError = options.onError;\n\t}\n\n\tget observerCount(): number {\n\t\treturn this.#observers.size;\n\t}\n\n\tget(key: string): TEntry | undefined {\n\t\treturn this.#entries.get(key);\n\t}\n\n\tinsert(entry: TEntry): void {\n\t\tthis.#assertActive();\n\t\tif (this.#entries.has(entry.key)) {\n\t\t\tthrow new Error(`Keyed service already has a live instance with key ${entry.key}`);\n\t\t}\n\t\tthis.#entries.set(entry.key, entry);\n\t\tif (this.#ready) this.#startAll(entry);\n\t}\n\n\treplace(entry: TEntry): void {\n\t\tthis.#assertActive();\n\t\tconst previous = this.#entries.get(entry.key);\n\t\tif (previous !== undefined) {\n\t\t\tif (previous.generation === entry.generation) {\n\t\t\t\tthrow new Error(\"Keyed service repeated a live generation\");\n\t\t\t}\n\t\t\tthis.#remove(previous);\n\t\t}\n\t\tthis.#entries.set(entry.key, entry);\n\t\tif (this.#ready) this.#startAll(entry);\n\t}\n\n\tremove(entry: TEntry): void {\n\t\tif (this.#entries.get(entry.key) !== entry) return;\n\t\tthis.#remove(entry);\n\t}\n\n\tready(): void {\n\t\tthis.#assertActive();\n\t\tif (this.#ready) return;\n\t\tthis.#ready = true;\n\t\tfor (const entry of this.#entries.values()) this.#startAll(entry);\n\t}\n\n\treset(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#ready = false;\n\t\tfor (const entry of [...this.#entries.values()]) this.#remove(entry);\n\t}\n\n\tobserve<T>(handler: (service: T, context: Context) => void | Promise<void>): () => void {\n\t\tthis.#assertActive();\n\t\tconst observer: Observer = {\n\t\t\thandler: handler as Observer[\"handler\"],\n\t\t\ttasks: new Map(),\n\t\t\tclosed: false,\n\t\t};\n\t\tthis.#observers.add(observer);\n\t\tif (this.#ready) {\n\t\t\tfor (const entry of this.#entries.values()) this.#start(observer, entry);\n\t\t}\n\t\treturn () => {\n\t\t\tif (observer.closed) return;\n\t\t\tobserver.closed = true;\n\t\t\tfor (const task of observer.tasks.values()) task.cancel();\n\t\t\tobserver.tasks.clear();\n\t\t\tthis.#observers.delete(observer);\n\t\t};\n\t}\n\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tfor (const observer of this.#observers) {\n\t\t\tobserver.closed = true;\n\t\t\tfor (const task of observer.tasks.values()) task.cancel();\n\t\t\tobserver.tasks.clear();\n\t\t}\n\t\tthis.#observers.clear();\n\t\tfor (const entry of [...this.#entries.values()]) {\n\t\t\tentry.deactivate();\n\t\t}\n\t\tthis.#entries.clear();\n\t}\n\n\t#remove(entry: TEntry): void {\n\t\tif (this.#entries.get(entry.key) !== entry) return;\n\t\tthis.#entries.delete(entry.key);\n\t\tentry.deactivate();\n\t\tfor (const observer of this.#observers) {\n\t\t\tobserver.tasks.get(entry)?.cancel();\n\t\t\tobserver.tasks.delete(entry);\n\t\t}\n\t}\n\n\t#startAll(entry: TEntry): void {\n\t\tfor (const observer of this.#observers) this.#start(observer, entry);\n\t}\n\n\t#start(observer: Observer, entry: TEntry): void {\n\t\tif (observer.closed || observer.tasks.has(entry)) return;\n\t\tconst { context, cancel } = withCancel(BACKGROUND_CONTEXT);\n\t\tobserver.tasks.set(entry, { cancel });\n\t\ttry {\n\t\t\tvoid Promise.resolve(observer.handler(entry.service, context)).catch((error: unknown) => {\n\t\t\t\tif (!context.abortSignal?.aborted) this.#reportError(toError(error));\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (!context.abortSignal?.aborted) this.#reportError(toError(error));\n\t\t}\n\t}\n\n\t#assertActive(): void {\n\t\tif (this.#disposed) throw new Error(\"Keyed service directory is disposed\");\n\t}\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n"]}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { BACKGROUND_CONTEXT, withCancel } from "../context/index.js";
|
|
2
|
+
/** Owns keyed instance lifetime and the cancellable tasks observing those instances. */
|
|
3
|
+
export class InstanceDirectory {
|
|
4
|
+
#entries = new Map();
|
|
5
|
+
#observers = new Set();
|
|
6
|
+
#reportError;
|
|
7
|
+
#ready;
|
|
8
|
+
#disposed = false;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.#ready = options.ready;
|
|
11
|
+
this.#reportError = options.onError;
|
|
12
|
+
}
|
|
13
|
+
get observerCount() {
|
|
14
|
+
return this.#observers.size;
|
|
15
|
+
}
|
|
16
|
+
get(key) {
|
|
17
|
+
return this.#entries.get(key);
|
|
18
|
+
}
|
|
19
|
+
insert(entry) {
|
|
20
|
+
this.#assertActive();
|
|
21
|
+
if (this.#entries.has(entry.key)) {
|
|
22
|
+
throw new Error(`Keyed service already has a live instance with key ${entry.key}`);
|
|
23
|
+
}
|
|
24
|
+
this.#entries.set(entry.key, entry);
|
|
25
|
+
if (this.#ready)
|
|
26
|
+
this.#startAll(entry);
|
|
27
|
+
}
|
|
28
|
+
replace(entry) {
|
|
29
|
+
this.#assertActive();
|
|
30
|
+
const previous = this.#entries.get(entry.key);
|
|
31
|
+
if (previous !== undefined) {
|
|
32
|
+
if (previous.generation === entry.generation) {
|
|
33
|
+
throw new Error("Keyed service repeated a live generation");
|
|
34
|
+
}
|
|
35
|
+
this.#remove(previous);
|
|
36
|
+
}
|
|
37
|
+
this.#entries.set(entry.key, entry);
|
|
38
|
+
if (this.#ready)
|
|
39
|
+
this.#startAll(entry);
|
|
40
|
+
}
|
|
41
|
+
remove(entry) {
|
|
42
|
+
if (this.#entries.get(entry.key) !== entry)
|
|
43
|
+
return;
|
|
44
|
+
this.#remove(entry);
|
|
45
|
+
}
|
|
46
|
+
ready() {
|
|
47
|
+
this.#assertActive();
|
|
48
|
+
if (this.#ready)
|
|
49
|
+
return;
|
|
50
|
+
this.#ready = true;
|
|
51
|
+
for (const entry of this.#entries.values())
|
|
52
|
+
this.#startAll(entry);
|
|
53
|
+
}
|
|
54
|
+
reset() {
|
|
55
|
+
if (this.#disposed)
|
|
56
|
+
return;
|
|
57
|
+
this.#ready = false;
|
|
58
|
+
for (const entry of [...this.#entries.values()])
|
|
59
|
+
this.#remove(entry);
|
|
60
|
+
}
|
|
61
|
+
observe(handler) {
|
|
62
|
+
this.#assertActive();
|
|
63
|
+
const observer = {
|
|
64
|
+
handler: handler,
|
|
65
|
+
tasks: new Map(),
|
|
66
|
+
closed: false,
|
|
67
|
+
};
|
|
68
|
+
this.#observers.add(observer);
|
|
69
|
+
if (this.#ready) {
|
|
70
|
+
for (const entry of this.#entries.values())
|
|
71
|
+
this.#start(observer, entry);
|
|
72
|
+
}
|
|
73
|
+
return () => {
|
|
74
|
+
if (observer.closed)
|
|
75
|
+
return;
|
|
76
|
+
observer.closed = true;
|
|
77
|
+
for (const task of observer.tasks.values())
|
|
78
|
+
task.cancel();
|
|
79
|
+
observer.tasks.clear();
|
|
80
|
+
this.#observers.delete(observer);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
dispose() {
|
|
84
|
+
if (this.#disposed)
|
|
85
|
+
return;
|
|
86
|
+
this.#disposed = true;
|
|
87
|
+
for (const observer of this.#observers) {
|
|
88
|
+
observer.closed = true;
|
|
89
|
+
for (const task of observer.tasks.values())
|
|
90
|
+
task.cancel();
|
|
91
|
+
observer.tasks.clear();
|
|
92
|
+
}
|
|
93
|
+
this.#observers.clear();
|
|
94
|
+
for (const entry of [...this.#entries.values()]) {
|
|
95
|
+
entry.deactivate();
|
|
96
|
+
}
|
|
97
|
+
this.#entries.clear();
|
|
98
|
+
}
|
|
99
|
+
#remove(entry) {
|
|
100
|
+
if (this.#entries.get(entry.key) !== entry)
|
|
101
|
+
return;
|
|
102
|
+
this.#entries.delete(entry.key);
|
|
103
|
+
entry.deactivate();
|
|
104
|
+
for (const observer of this.#observers) {
|
|
105
|
+
observer.tasks.get(entry)?.cancel();
|
|
106
|
+
observer.tasks.delete(entry);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
#startAll(entry) {
|
|
110
|
+
for (const observer of this.#observers)
|
|
111
|
+
this.#start(observer, entry);
|
|
112
|
+
}
|
|
113
|
+
#start(observer, entry) {
|
|
114
|
+
if (observer.closed || observer.tasks.has(entry))
|
|
115
|
+
return;
|
|
116
|
+
const { context, cancel } = withCancel(BACKGROUND_CONTEXT);
|
|
117
|
+
observer.tasks.set(entry, { cancel });
|
|
118
|
+
try {
|
|
119
|
+
void Promise.resolve(observer.handler(entry.service, context)).catch((error) => {
|
|
120
|
+
if (!context.abortSignal?.aborted)
|
|
121
|
+
this.#reportError(toError(error));
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (!context.abortSignal?.aborted)
|
|
126
|
+
this.#reportError(toError(error));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
#assertActive() {
|
|
130
|
+
if (this.#disposed)
|
|
131
|
+
throw new Error("Keyed service directory is disposed");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function toError(error) {
|
|
135
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=instances.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instances.js","sourceRoot":"","sources":["../../src/services/instances.ts"],"names":[],"mappings":"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","sourcesContent":["import { BACKGROUND_CONTEXT, withCancel } from \"../context/index.ts\";\nimport type { Context } from \"../types.ts\";\n\nexport interface InstanceDirectoryEntry {\n\treadonly key: string;\n\treadonly generation: number;\n\treadonly service: object;\n\tdeactivate(): void;\n}\n\ninterface Observer {\n\treadonly handler: (service: object, context: Context) => void | Promise<void>;\n\treadonly tasks: Map<InstanceDirectoryEntry, { readonly cancel: (reason?: unknown) => void }>;\n\tclosed: boolean;\n}\n\n/** Owns keyed instance lifetime and the cancellable tasks observing those instances. */\nexport class InstanceDirectory<TEntry extends InstanceDirectoryEntry> {\n\treadonly #entries = new Map<string, TEntry>();\n\treadonly #observers = new Set<Observer>();\n\treadonly #reportError: (error: Error) => void;\n\t#ready: boolean;\n\t#disposed = false;\n\n\tconstructor(options: { readonly ready: boolean; readonly onError: (error: Error) => void }) {\n\t\tthis.#ready = options.ready;\n\t\tthis.#reportError = options.onError;\n\t}\n\n\tget observerCount(): number {\n\t\treturn this.#observers.size;\n\t}\n\n\tget(key: string): TEntry | undefined {\n\t\treturn this.#entries.get(key);\n\t}\n\n\tinsert(entry: TEntry): void {\n\t\tthis.#assertActive();\n\t\tif (this.#entries.has(entry.key)) {\n\t\t\tthrow new Error(`Keyed service already has a live instance with key ${entry.key}`);\n\t\t}\n\t\tthis.#entries.set(entry.key, entry);\n\t\tif (this.#ready) this.#startAll(entry);\n\t}\n\n\treplace(entry: TEntry): void {\n\t\tthis.#assertActive();\n\t\tconst previous = this.#entries.get(entry.key);\n\t\tif (previous !== undefined) {\n\t\t\tif (previous.generation === entry.generation) {\n\t\t\t\tthrow new Error(\"Keyed service repeated a live generation\");\n\t\t\t}\n\t\t\tthis.#remove(previous);\n\t\t}\n\t\tthis.#entries.set(entry.key, entry);\n\t\tif (this.#ready) this.#startAll(entry);\n\t}\n\n\tremove(entry: TEntry): void {\n\t\tif (this.#entries.get(entry.key) !== entry) return;\n\t\tthis.#remove(entry);\n\t}\n\n\tready(): void {\n\t\tthis.#assertActive();\n\t\tif (this.#ready) return;\n\t\tthis.#ready = true;\n\t\tfor (const entry of this.#entries.values()) this.#startAll(entry);\n\t}\n\n\treset(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#ready = false;\n\t\tfor (const entry of [...this.#entries.values()]) this.#remove(entry);\n\t}\n\n\tobserve<T>(handler: (service: T, context: Context) => void | Promise<void>): () => void {\n\t\tthis.#assertActive();\n\t\tconst observer: Observer = {\n\t\t\thandler: handler as Observer[\"handler\"],\n\t\t\ttasks: new Map(),\n\t\t\tclosed: false,\n\t\t};\n\t\tthis.#observers.add(observer);\n\t\tif (this.#ready) {\n\t\t\tfor (const entry of this.#entries.values()) this.#start(observer, entry);\n\t\t}\n\t\treturn () => {\n\t\t\tif (observer.closed) return;\n\t\t\tobserver.closed = true;\n\t\t\tfor (const task of observer.tasks.values()) task.cancel();\n\t\t\tobserver.tasks.clear();\n\t\t\tthis.#observers.delete(observer);\n\t\t};\n\t}\n\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tfor (const observer of this.#observers) {\n\t\t\tobserver.closed = true;\n\t\t\tfor (const task of observer.tasks.values()) task.cancel();\n\t\t\tobserver.tasks.clear();\n\t\t}\n\t\tthis.#observers.clear();\n\t\tfor (const entry of [...this.#entries.values()]) {\n\t\t\tentry.deactivate();\n\t\t}\n\t\tthis.#entries.clear();\n\t}\n\n\t#remove(entry: TEntry): void {\n\t\tif (this.#entries.get(entry.key) !== entry) return;\n\t\tthis.#entries.delete(entry.key);\n\t\tentry.deactivate();\n\t\tfor (const observer of this.#observers) {\n\t\t\tobserver.tasks.get(entry)?.cancel();\n\t\t\tobserver.tasks.delete(entry);\n\t\t}\n\t}\n\n\t#startAll(entry: TEntry): void {\n\t\tfor (const observer of this.#observers) this.#start(observer, entry);\n\t}\n\n\t#start(observer: Observer, entry: TEntry): void {\n\t\tif (observer.closed || observer.tasks.has(entry)) return;\n\t\tconst { context, cancel } = withCancel(BACKGROUND_CONTEXT);\n\t\tobserver.tasks.set(entry, { cancel });\n\t\ttry {\n\t\t\tvoid Promise.resolve(observer.handler(entry.service, context)).catch((error: unknown) => {\n\t\t\t\tif (!context.abortSignal?.aborted) this.#reportError(toError(error));\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (!context.abortSignal?.aborted) this.#reportError(toError(error));\n\t\t}\n\t}\n\n\t#assertActive(): void {\n\t\tif (this.#disposed) throw new Error(\"Keyed service directory is disposed\");\n\t}\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { RemoteServiceTransport } from "../types.ts";
|
|
2
|
+
import type { RemoteServiceProvider } from "./provider.ts";
|
|
3
|
+
/** Connects a provider to a binding without changing remote service semantics. */
|
|
4
|
+
export declare function createLoopbackServiceTransport(provider: RemoteServiceProvider): RemoteServiceTransport;
|
|
5
|
+
//# sourceMappingURL=loopback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loopback.d.ts","sourceRoot":"","sources":["../../src/services/loopback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,kFAAkF;AAClF,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,qBAAqB,GAAG,sBAAsB,CAYtG","sourcesContent":["import type { RemoteServiceTransport } from \"../types.ts\";\nimport type { RemoteServiceProvider } from \"./provider.ts\";\n\n/** Connects a provider to a binding without changing remote service semantics. */\nexport function createLoopbackServiceTransport(provider: RemoteServiceProvider): RemoteServiceTransport {\n\treturn {\n\t\tinvoke: (call, context) => provider.invoke(call, context),\n\t\tsubscribe: async (serviceId, mode, listener) => {\n\t\t\tconst subscription = provider.subscribe(serviceId, mode, listener);\n\t\t\treturn {\n\t\t\t\tsnapshot: subscription.snapshot,\n\t\t\t\tactivate: () => subscription.activate(),\n\t\t\t\tclose: () => subscription.close(),\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Connects a provider to a binding without changing remote service semantics. */
|
|
2
|
+
export function createLoopbackServiceTransport(provider) {
|
|
3
|
+
return {
|
|
4
|
+
invoke: (call, context) => provider.invoke(call, context),
|
|
5
|
+
subscribe: async (serviceId, mode, listener) => {
|
|
6
|
+
const subscription = provider.subscribe(serviceId, mode, listener);
|
|
7
|
+
return {
|
|
8
|
+
snapshot: subscription.snapshot,
|
|
9
|
+
activate: () => subscription.activate(),
|
|
10
|
+
close: () => subscription.close(),
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=loopback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loopback.js","sourceRoot":"","sources":["../../src/services/loopback.ts"],"names":[],"mappings":"AAGA,kFAAkF;AAClF,MAAM,UAAU,8BAA8B,CAAC,QAA+B,EAA0B;IACvG,OAAO;QACN,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;QACzD,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;YAC/C,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;YACnE,OAAO;gBACN,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE;gBACvC,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE;aACjC,CAAC;QAAA,CACF;KACD,CAAC;AAAA,CACF","sourcesContent":["import type { RemoteServiceTransport } from \"../types.ts\";\nimport type { RemoteServiceProvider } from \"./provider.ts\";\n\n/** Connects a provider to a binding without changing remote service semantics. */\nexport function createLoopbackServiceTransport(provider: RemoteServiceProvider): RemoteServiceTransport {\n\treturn {\n\t\tinvoke: (call, context) => provider.invoke(call, context),\n\t\tsubscribe: async (serviceId, mode, listener) => {\n\t\t\tconst subscription = provider.subscribe(serviceId, mode, listener);\n\t\t\treturn {\n\t\t\t\tsnapshot: subscription.snapshot,\n\t\t\t\tactivate: () => subscription.activate(),\n\t\t\t\tclose: () => subscription.close(),\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Context, JsonValue, RemoteServiceContract, Service, ServiceCall, ServiceCatalogueEntry, ServiceMode, ServiceProviderUpdate, ServiceSubscription } from "../types.ts";
|
|
2
|
+
interface ServiceProviderDefinition {
|
|
3
|
+
readonly service: {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly local?: boolean;
|
|
6
|
+
};
|
|
7
|
+
readonly mode: ServiceMode;
|
|
8
|
+
}
|
|
9
|
+
export type ServiceUpdatePublisher = (subscriptionId: string, update: ServiceProviderUpdate, context: Context) => void | Promise<void>;
|
|
10
|
+
/** Hosts one provider for one remote consumer and owns that consumer's subscriptions. */
|
|
11
|
+
export interface RemoteServiceEndpoint {
|
|
12
|
+
invoke(call: ServiceCall, publish: ServiceUpdatePublisher, context: Context): Promise<JsonValue | undefined>;
|
|
13
|
+
dispose(): void;
|
|
14
|
+
}
|
|
15
|
+
export declare class RemoteServiceProvider {
|
|
16
|
+
#private;
|
|
17
|
+
constructor(entries: readonly (ServiceProviderDefinition | {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
})[]);
|
|
20
|
+
get catalogue(): readonly ServiceCatalogueEntry[];
|
|
21
|
+
provide<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void;
|
|
22
|
+
/** Disconnect one singleton while preserving active subscriptions and remote facades. */
|
|
23
|
+
withdraw<T>(service: Service<T>): void;
|
|
24
|
+
/** Check a singleton replacement without changing the active provider. */
|
|
25
|
+
validateReplacement<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void;
|
|
26
|
+
/** Replace one singleton without making its stable remote facade unavailable. */
|
|
27
|
+
replace<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void;
|
|
28
|
+
use<T>(service: Service<T>): T;
|
|
29
|
+
spawn<T>(service: Service<T>, key: string, implementation: NoInfer<RemoteServiceContract<T>>): () => void;
|
|
30
|
+
invoke(call: ServiceCall, context: Context): Promise<JsonValue | undefined>;
|
|
31
|
+
subscribe(serviceId: string, mode: ServiceMode, listener: (update: ServiceProviderUpdate, context: Context) => void): ServiceSubscription;
|
|
32
|
+
dispose(): void;
|
|
33
|
+
}
|
|
34
|
+
export declare function createRemoteServiceEndpoint(provider: RemoteServiceProvider): RemoteServiceEndpoint;
|
|
35
|
+
export declare function validateRemoteServiceImplementation(serviceId: string, implementation: unknown): void;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=provider.d.ts.map
|