@opetope/runtime 0.1.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/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +345 -0
- package/README.ru.md +344 -0
- package/dist/application-compiler-edges.d.ts +3 -0
- package/dist/application-compiler-edges.js +2 -0
- package/dist/application-compiler-edges.js.map +1 -0
- package/dist/application-compiler-graph.d.ts +8 -0
- package/dist/application-compiler-graph.js +2 -0
- package/dist/application-compiler-graph.js.map +1 -0
- package/dist/application-compiler.d.ts +116 -0
- package/dist/application-compiler.js +2 -0
- package/dist/application-compiler.js.map +1 -0
- package/dist/application-conditions.d.ts +18 -0
- package/dist/application-conditions.js +2 -0
- package/dist/application-conditions.js.map +1 -0
- package/dist/application-definition.d.ts +30 -0
- package/dist/application-definition.js +2 -0
- package/dist/application-definition.js.map +1 -0
- package/dist/application-error.d.ts +10 -0
- package/dist/application-error.js +2 -0
- package/dist/application-error.js.map +1 -0
- package/dist/application-execution.d.ts +43 -0
- package/dist/application-execution.js +2 -0
- package/dist/application-execution.js.map +1 -0
- package/dist/application-feature-bindings.d.ts +11 -0
- package/dist/application-feature-bindings.js +2 -0
- package/dist/application-feature-bindings.js.map +1 -0
- package/dist/application-feature-instance.d.ts +5 -0
- package/dist/application-feature-instance.js +2 -0
- package/dist/application-feature-instance.js.map +1 -0
- package/dist/application-group-order.d.ts +29 -0
- package/dist/application-group-order.js +2 -0
- package/dist/application-group-order.js.map +1 -0
- package/dist/application-instance-retirement.d.ts +36 -0
- package/dist/application-instance-retirement.js +2 -0
- package/dist/application-instance-retirement.js.map +1 -0
- package/dist/application-open-options.d.ts +29 -0
- package/dist/application-open-options.js +2 -0
- package/dist/application-open-options.js.map +1 -0
- package/dist/application-port-compiler.d.ts +28 -0
- package/dist/application-port-compiler.js +2 -0
- package/dist/application-port-compiler.js.map +1 -0
- package/dist/attachment-call-declaration.d.ts +43 -0
- package/dist/attachment-call-declaration.js +2 -0
- package/dist/attachment-call-declaration.js.map +1 -0
- package/dist/attachment-declaration.d.ts +68 -0
- package/dist/attachment-declaration.js +2 -0
- package/dist/attachment-declaration.js.map +1 -0
- package/dist/attachment-execution.d.ts +9 -0
- package/dist/attachment-execution.js +2 -0
- package/dist/attachment-execution.js.map +1 -0
- package/dist/attachment-retirement-scheduler.d.ts +14 -0
- package/dist/attachment-retirement-scheduler.js +2 -0
- package/dist/attachment-retirement-scheduler.js.map +1 -0
- package/dist/call-option-snapshot.d.ts +20 -0
- package/dist/call-option-snapshot.js +2 -0
- package/dist/call-option-snapshot.js.map +1 -0
- package/dist/compile-call-target-bindings.d.ts +14 -0
- package/dist/compile-call-target-bindings.js +2 -0
- package/dist/compile-call-target-bindings.js.map +1 -0
- package/dist/compile-module-template.d.ts +38 -0
- package/dist/compile-module-template.js +2 -0
- package/dist/compile-module-template.js.map +1 -0
- package/dist/condition-group-execution.d.ts +44 -0
- package/dist/condition-group-execution.js +2 -0
- package/dist/condition-group-execution.js.map +1 -0
- package/dist/condition-override.d.ts +28 -0
- package/dist/condition-override.js +2 -0
- package/dist/condition-override.js.map +1 -0
- package/dist/condition-source.d.ts +10 -0
- package/dist/condition-source.js +2 -0
- package/dist/condition-source.js.map +1 -0
- package/dist/condition-types.d.ts +14 -0
- package/dist/condition.d.ts +28 -0
- package/dist/condition.js +2 -0
- package/dist/condition.js.map +1 -0
- package/dist/control-registry.d.ts +56 -0
- package/dist/control-registry.js +2 -0
- package/dist/control-registry.js.map +1 -0
- package/dist/dynamic-scope-child.d.ts +23 -0
- package/dist/dynamic-scope-child.js +2 -0
- package/dist/dynamic-scope-child.js.map +1 -0
- package/dist/dynamic-scope-controller.d.ts +16 -0
- package/dist/dynamic-scope-controller.js +2 -0
- package/dist/dynamic-scope-controller.js.map +1 -0
- package/dist/feature-attachment-authoring-types.d.ts +51 -0
- package/dist/feature-attachment-lowering.d.ts +18 -0
- package/dist/feature-attachment-lowering.js +2 -0
- package/dist/feature-attachment-lowering.js.map +1 -0
- package/dist/feature-attachment.d.ts +45 -0
- package/dist/feature-attachment.js +2 -0
- package/dist/feature-attachment.js.map +1 -0
- package/dist/feature-authoring-types.d.ts +196 -0
- package/dist/feature-authoring.d.ts +15 -0
- package/dist/feature-authoring.js +2 -0
- package/dist/feature-authoring.js.map +1 -0
- package/dist/feature-body.d.ts +53 -0
- package/dist/feature-body.js +2 -0
- package/dist/feature-body.js.map +1 -0
- package/dist/feature-call-authority.d.ts +8 -0
- package/dist/feature-call-authority.js +2 -0
- package/dist/feature-call-authority.js.map +1 -0
- package/dist/feature-call-types.d.ts +39 -0
- package/dist/feature-call.d.ts +18 -0
- package/dist/feature-call.js +2 -0
- package/dist/feature-call.js.map +1 -0
- package/dist/feature-calls.d.ts +6 -0
- package/dist/feature-calls.js +2 -0
- package/dist/feature-calls.js.map +1 -0
- package/dist/feature-contract.d.ts +70 -0
- package/dist/feature-contract.js +2 -0
- package/dist/feature-contract.js.map +1 -0
- package/dist/feature-contribution-model.d.ts +38 -0
- package/dist/feature-contribution-model.js +2 -0
- package/dist/feature-contribution-model.js.map +1 -0
- package/dist/feature-contribution.d.ts +126 -0
- package/dist/feature-contribution.js +2 -0
- package/dist/feature-contribution.js.map +1 -0
- package/dist/feature-definition-api.d.ts +53 -0
- package/dist/feature-definition-support.d.ts +21 -0
- package/dist/feature-definition-support.js +2 -0
- package/dist/feature-definition-support.js.map +1 -0
- package/dist/feature-effect.d.ts +26 -0
- package/dist/feature-effect.js +2 -0
- package/dist/feature-effect.js.map +1 -0
- package/dist/feature-event.d.ts +32 -0
- package/dist/feature-event.js +2 -0
- package/dist/feature-event.js.map +1 -0
- package/dist/feature-generation.d.ts +34 -0
- package/dist/feature-generation.js +2 -0
- package/dist/feature-generation.js.map +1 -0
- package/dist/feature-lazy-generation.d.ts +6 -0
- package/dist/feature-lazy-generation.js +2 -0
- package/dist/feature-lazy-generation.js.map +1 -0
- package/dist/feature-lazy.d.ts +44 -0
- package/dist/feature-lazy.js +2 -0
- package/dist/feature-lazy.js.map +1 -0
- package/dist/feature-materialization-binding.d.ts +31 -0
- package/dist/feature-materialization-binding.js +2 -0
- package/dist/feature-materialization-binding.js.map +1 -0
- package/dist/feature-materialization-types.d.ts +45 -0
- package/dist/feature-model-dependencies.d.ts +23 -0
- package/dist/feature-model-dependencies.js +2 -0
- package/dist/feature-model-dependencies.js.map +1 -0
- package/dist/feature-model.d.ts +60 -0
- package/dist/feature-model.js +2 -0
- package/dist/feature-model.js.map +1 -0
- package/dist/feature-optional.d.ts +15 -0
- package/dist/feature-optional.js +2 -0
- package/dist/feature-optional.js.map +1 -0
- package/dist/feature-own-lowering.d.ts +22 -0
- package/dist/feature-own-lowering.js +2 -0
- package/dist/feature-own-lowering.js.map +1 -0
- package/dist/feature-port-binding.d.ts +6 -0
- package/dist/feature-port-binding.js +2 -0
- package/dist/feature-port-binding.js.map +1 -0
- package/dist/feature-port.d.ts +66 -0
- package/dist/feature-port.js +2 -0
- package/dist/feature-port.js.map +1 -0
- package/dist/feature-record.d.ts +6 -0
- package/dist/feature-record.js +2 -0
- package/dist/feature-record.js.map +1 -0
- package/dist/feature-resource.d.ts +29 -0
- package/dist/feature-resource.js +2 -0
- package/dist/feature-resource.js.map +1 -0
- package/dist/feature-scope-types.d.ts +35 -0
- package/dist/feature-scope.d.ts +29 -0
- package/dist/feature-scope.js +2 -0
- package/dist/feature-scope.js.map +1 -0
- package/dist/feature-stream.d.ts +37 -0
- package/dist/feature-stream.js +2 -0
- package/dist/feature-stream.js.map +1 -0
- package/dist/feature-timers.d.ts +14 -0
- package/dist/feature-timers.js +2 -0
- package/dist/feature-timers.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/inspection-activity-protocol.d.ts +63 -0
- package/dist/inspection-activity.d.ts +54 -0
- package/dist/inspection-activity.js +2 -0
- package/dist/inspection-activity.js.map +1 -0
- package/dist/inspection-diff.d.ts +10 -0
- package/dist/inspection-diff.js +2 -0
- package/dist/inspection-diff.js.map +1 -0
- package/dist/inspection-module-activity.d.ts +4 -0
- package/dist/inspection-module-activity.js +2 -0
- package/dist/inspection-module-activity.js.map +1 -0
- package/dist/inspection-observer.d.ts +38 -0
- package/dist/inspection-observer.js +2 -0
- package/dist/inspection-observer.js.map +1 -0
- package/dist/inspection-plan.d.ts +33 -0
- package/dist/inspection-plan.js +2 -0
- package/dist/inspection-plan.js.map +1 -0
- package/dist/inspection-protocol.d.ts +333 -0
- package/dist/inspection-protocol.js +2 -0
- package/dist/inspection-protocol.js.map +1 -0
- package/dist/inspection-registry.d.ts +41 -0
- package/dist/inspection-registry.js +2 -0
- package/dist/inspection-registry.js.map +1 -0
- package/dist/inspection-session.d.ts +92 -0
- package/dist/inspection-session.js +2 -0
- package/dist/inspection-session.js.map +1 -0
- package/dist/inspection-snapshot.d.ts +4 -0
- package/dist/inspection-snapshot.js +2 -0
- package/dist/inspection-snapshot.js.map +1 -0
- package/dist/inspection-state.d.ts +91 -0
- package/dist/inspection-state.js +2 -0
- package/dist/inspection-state.js.map +1 -0
- package/dist/instance-demand.d.ts +31 -0
- package/dist/instance-demand.js +2 -0
- package/dist/instance-demand.js.map +1 -0
- package/dist/internal.d.ts +41 -0
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -0
- package/dist/keyed-scope-controller.d.ts +11 -0
- package/dist/keyed-scope-controller.js +2 -0
- package/dist/keyed-scope-controller.js.map +1 -0
- package/dist/model-kernel.d.ts +18 -0
- package/dist/model-kernel.js +2 -0
- package/dist/model-kernel.js.map +1 -0
- package/dist/module-call-context.d.ts +7 -0
- package/dist/module-call-context.js +2 -0
- package/dist/module-call-context.js.map +1 -0
- package/dist/module-call-runtime.d.ts +21 -0
- package/dist/module-call-runtime.js +2 -0
- package/dist/module-call-runtime.js.map +1 -0
- package/dist/module-generation.d.ts +57 -0
- package/dist/module-generation.js +2 -0
- package/dist/module-generation.js.map +1 -0
- package/dist/module-instance-types.d.ts +156 -0
- package/dist/module-instance.d.ts +19 -0
- package/dist/module-instance.js +2 -0
- package/dist/module-instance.js.map +1 -0
- package/dist/module-runtime-identity.d.ts +4 -0
- package/dist/module-runtime-identity.js +2 -0
- package/dist/module-runtime-identity.js.map +1 -0
- package/dist/module-scope-open.d.ts +4 -0
- package/dist/module-scope-open.js +2 -0
- package/dist/module-scope-open.js.map +1 -0
- package/dist/module-scope-retirement.d.ts +3 -0
- package/dist/module-scope-retirement.js +2 -0
- package/dist/module-scope-retirement.js.map +1 -0
- package/dist/module-template-ir.d.ts +59 -0
- package/dist/owner-generation-retirement.d.ts +6 -0
- package/dist/owner-generation-retirement.js +2 -0
- package/dist/owner-generation-retirement.js.map +1 -0
- package/dist/owner-generation-state.d.ts +123 -0
- package/dist/owner-generation-state.js +2 -0
- package/dist/owner-generation-state.js.map +1 -0
- package/dist/owner-generation.d.ts +16 -0
- package/dist/owner-generation.js +2 -0
- package/dist/owner-generation.js.map +1 -0
- package/dist/public-module-definition.d.ts +9 -0
- package/dist/public-module-definition.js +2 -0
- package/dist/public-module-definition.js.map +1 -0
- package/dist/public-module-instance.d.ts +6 -0
- package/dist/public-module-instance.js +2 -0
- package/dist/public-module-instance.js.map +1 -0
- package/dist/public-module-retirement-diagnostics.d.ts +5 -0
- package/dist/public-module-retirement-diagnostics.js +2 -0
- package/dist/public-module-retirement-diagnostics.js.map +1 -0
- package/dist/public-module-retirement.d.ts +3 -0
- package/dist/public-module-retirement.js +2 -0
- package/dist/public-module-retirement.js.map +1 -0
- package/dist/public-module-scope.d.ts +5 -0
- package/dist/public-module-scope.js +2 -0
- package/dist/public-module-scope.js.map +1 -0
- package/dist/public-module-state.d.ts +28 -0
- package/dist/public-module-state.js +2 -0
- package/dist/public-module-state.js.map +1 -0
- package/dist/public-module-types.d.ts +295 -0
- package/dist/public-module.d.ts +4 -0
- package/dist/resource-cache.d.ts +12 -0
- package/dist/resource-cache.js +2 -0
- package/dist/resource-cache.js.map +1 -0
- package/dist/resource-controller.d.ts +29 -0
- package/dist/resource-controller.js +2 -0
- package/dist/resource-controller.js.map +1 -0
- package/dist/resource-policy.d.ts +16 -0
- package/dist/resource-policy.js +2 -0
- package/dist/resource-policy.js.map +1 -0
- package/dist/resource-snapshot.d.ts +12 -0
- package/dist/resource-snapshot.js +2 -0
- package/dist/resource-snapshot.js.map +1 -0
- package/dist/resource-types.d.ts +3 -0
- package/dist/runtime-error-reporting.d.ts +4 -0
- package/dist/runtime-error-reporting.js +2 -0
- package/dist/runtime-error-reporting.js.map +1 -0
- package/dist/stream-backpressure.d.ts +18 -0
- package/dist/stream-backpressure.js +2 -0
- package/dist/stream-backpressure.js.map +1 -0
- package/dist/stream-cleanup.d.ts +17 -0
- package/dist/stream-cleanup.js +2 -0
- package/dist/stream-cleanup.js.map +1 -0
- package/dist/stream-controller-types.d.ts +51 -0
- package/dist/stream-controller.d.ts +5 -0
- package/dist/stream-controller.js +2 -0
- package/dist/stream-controller.js.map +1 -0
- package/docs/agent-guide.md +214 -0
- package/docs/agent-guide.ru.md +208 -0
- package/docs/cookbook.md +734 -0
- package/docs/cookbook.ru.md +729 -0
- package/docs/decisions.md +1437 -0
- package/docs/devtools.md +423 -0
- package/docs/devtools.ru.md +419 -0
- package/docs/how-it-works.md +521 -0
- package/docs/how-it-works.ru.md +495 -0
- package/docs/releases.md +78 -0
- package/docs/releases.ru.md +78 -0
- package/docs/spec.md +874 -0
- package/docs/spec.ru.md +884 -0
- package/package.json +72 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FeatureError } from '@opetope/core';
|
|
2
|
+
import type { ModuleInstanceRecord as LocalModuleInstanceRecord, LocalScopeRetirement } from './module-instance.js';
|
|
3
|
+
import type { CleanupFailurePolicy, ErrorReporter, ModuleDefinitionRecord, ModuleInstanceRecord, ModuleScopeRetirement } from './public-module-types.js';
|
|
4
|
+
declare const closedModuleDrainOutcome: Readonly<{
|
|
5
|
+
kind: "closed";
|
|
6
|
+
}>;
|
|
7
|
+
declare const closedModuleScopeDrainOutcome: Readonly<{
|
|
8
|
+
kind: "closed";
|
|
9
|
+
}>;
|
|
10
|
+
declare const readyModuleScopeOpenOutcome: Readonly<{
|
|
11
|
+
kind: "ready";
|
|
12
|
+
}>;
|
|
13
|
+
declare const closedModuleScopeRetirement: ModuleScopeRetirement;
|
|
14
|
+
declare const scopeRetirements: WeakMap<LocalScopeRetirement, ModuleScopeRetirement>;
|
|
15
|
+
declare const moduleDefinitions: WeakMap<object, ModuleDefinitionRecord>;
|
|
16
|
+
declare const moduleInstances: WeakMap<object, ModuleInstanceRecord>;
|
|
17
|
+
declare function assertPlainModuleOptions(value: unknown): asserts value is object;
|
|
18
|
+
declare function reportModuleCleanupFailure(error: FeatureError, reporter: ErrorReporter | undefined): void;
|
|
19
|
+
declare function snapshotModuleInstanceOptions(value: unknown): {
|
|
20
|
+
readonly cleanupFailure: CleanupFailurePolicy;
|
|
21
|
+
readonly reporter: ErrorReporter | undefined;
|
|
22
|
+
};
|
|
23
|
+
declare function requireModuleDefinition(definition: object): ModuleDefinitionRecord;
|
|
24
|
+
declare function requireModuleInstance(instance: object): ModuleInstanceRecord;
|
|
25
|
+
declare function assertInstanceCanOpen(record: ModuleInstanceRecord): void;
|
|
26
|
+
declare function requireActiveDefinition(record: ModuleInstanceRecord): ModuleDefinitionRecord;
|
|
27
|
+
declare function requireActiveLocal(record: ModuleInstanceRecord): LocalModuleInstanceRecord;
|
|
28
|
+
export { assertInstanceCanOpen, assertPlainModuleOptions, closedModuleDrainOutcome, closedModuleScopeDrainOutcome, closedModuleScopeRetirement, moduleDefinitions, moduleInstances, readyModuleScopeOpenOutcome, reportModuleCleanupFailure, requireActiveDefinition, requireActiveLocal, requireModuleDefinition, requireModuleInstance, scopeRetirements, snapshotModuleInstanceOptions, };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{hasOwn as r,reportDetachedError as o}from"@opetope/core/internal";const p=Object.freeze({kind:"closed"}),i=Object.freeze({kind:"closed"}),f=Object.freeze({kind:"ready"}),l=Object.freeze({drain:()=>Promise.resolve(i),retry:()=>Promise.resolve(i)}),w=new WeakMap,u=new WeakMap,c=new WeakMap,y=new Set(["id","runtime"]),m=new Set(["cleanupFailure","reporter"]),M={cleanupFailure:"report",reporter:void 0};function a(e,n,t){for(const s of Reflect.ownKeys(e))if(!n.has(s))throw new TypeError(`Unknown ${t} option ${String(s)}.`)}function d(e,n){if(typeof e!="object"||e===null)throw new TypeError(`${n} options must be a plain object.`);const t=Object.getPrototypeOf(e);if(t!==Object.prototype&&t!==null)throw new TypeError(`${n} options must be a plain object.`)}function h(e){if(d(e,"defineModule"),a(e,y,"defineModule"),!r(e,"id")||!r(e,"runtime"))throw new TypeError("defineModule requires own id and runtime fields.")}function O(e,n){if(n===void 0){o(e);return}try{const t=n(e);t!==void 0&&Promise.resolve(t).catch(()=>o(e))}catch{o(e)}}function F(e){const n=r(e,"cleanupFailure")?Reflect.get(e,"cleanupFailure"):"report";if(n!=="quarantine"&&n!=="report")throw new TypeError('instantiateModule cleanupFailure must be "report" or "quarantine".');return n}function b(e){const n=r(e,"reporter")?Reflect.get(e,"reporter"):void 0;if(n!==void 0&&typeof n!="function")throw new TypeError("instantiateModule reporter must be a function.");return n}function E(e){return e===void 0?M:(d(e,"instantiateModule"),a(e,m,"instantiateModule"),{cleanupFailure:F(e),reporter:b(e)})}function T(e){const n=u.get(e);if(n===void 0)throw new TypeError("Feature definition is not authentic.");return n}function g(e){const n=c.get(e);if(n===void 0)throw new TypeError("Feature instance is not authentic.");return n}function j(e){if(e.operation!==void 0||e.state==="retired"||e.state==="retiring")throw new TypeError("Feature instance is retiring or retired.");e.state==="assembly"&&(e.state="active")}function k(e){const n=e.definition;if(n===void 0)throw new TypeError("Feature instance is retired.");return n}function q(e){const n=e.local;if(n===void 0)throw new TypeError("Feature instance is retired.");return n}export{j as assertInstanceCanOpen,h as assertPlainModuleOptions,p as closedModuleDrainOutcome,i as closedModuleScopeDrainOutcome,l as closedModuleScopeRetirement,u as moduleDefinitions,c as moduleInstances,f as readyModuleScopeOpenOutcome,O as reportModuleCleanupFailure,k as requireActiveDefinition,q as requireActiveLocal,T as requireModuleDefinition,g as requireModuleInstance,w as scopeRetirements,E as snapshotModuleInstanceOptions};
|
|
2
|
+
//# sourceMappingURL=public-module-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-module-state.js","sources":["../src/public-module-state.ts"],"sourcesContent":["import type { FeatureError } from '@opetope/core';\nimport { hasOwn, reportDetachedError } from '@opetope/core/internal';\n\nimport type { ModuleInstanceRecord as LocalModuleInstanceRecord, LocalScopeRetirement } from './module-instance';\nimport type {\n CleanupFailurePolicy,\n ErrorReporter,\n ModuleDefinitionRecord,\n ModuleInstanceRecord,\n ModuleScopeRetirement,\n} from './public-module-types';\n\nconst closedModuleDrainOutcome = Object.freeze({ kind: 'closed' as const });\nconst closedModuleScopeDrainOutcome = Object.freeze({ kind: 'closed' as const });\nconst readyModuleScopeOpenOutcome = Object.freeze({ kind: 'ready' as const });\nconst closedModuleScopeRetirement: ModuleScopeRetirement = Object.freeze({\n drain: () => Promise.resolve(closedModuleScopeDrainOutcome),\n retry: () => Promise.resolve(closedModuleScopeDrainOutcome),\n});\nconst scopeRetirements = new WeakMap<LocalScopeRetirement, ModuleScopeRetirement>();\nconst moduleDefinitions = new WeakMap<object, ModuleDefinitionRecord>();\nconst moduleInstances = new WeakMap<object, ModuleInstanceRecord>();\nconst moduleDefinitionOptionKeys = new Set<PropertyKey>(['id', 'runtime']);\nconst moduleInstanceOptionKeys = new Set<PropertyKey>(['cleanupFailure', 'reporter']);\nconst defaultModuleInstanceOptions = { cleanupFailure: 'report' as const, reporter: undefined };\n\nfunction assertKnownOptionKeys(value: object, keys: ReadonlySet<PropertyKey>, subject: string): void {\n for (const propertyKey of Reflect.ownKeys(value)) {\n if (!keys.has(propertyKey)) {\n throw new TypeError(`Unknown ${subject} option ${String(propertyKey)}.`);\n }\n }\n}\n\nfunction assertPlainOptions(value: unknown, subject: string): asserts value is object {\n if (typeof value !== 'object' || value === null) throw new TypeError(`${subject} options must be a plain object.`);\n\n const prototype: unknown = Object.getPrototypeOf(value);\n\n if (prototype !== Object.prototype && prototype !== null) {\n throw new TypeError(`${subject} options must be a plain object.`);\n }\n}\n\nfunction assertPlainModuleOptions(value: unknown): asserts value is object {\n assertPlainOptions(value, 'defineModule');\n assertKnownOptionKeys(value, moduleDefinitionOptionKeys, 'defineModule');\n\n if (!hasOwn(value, 'id') || !hasOwn(value, 'runtime')) {\n throw new TypeError('defineModule requires own id and runtime fields.');\n }\n}\n\nfunction reportModuleCleanupFailure(error: FeatureError, reporter: ErrorReporter | undefined): void {\n if (reporter === undefined) {\n reportDetachedError(error);\n\n return;\n }\n\n try {\n const result = reporter(error);\n\n if (result !== undefined) void Promise.resolve(result).catch(() => reportDetachedError(error));\n } catch {\n reportDetachedError(error);\n }\n}\n\nfunction snapshotModuleCleanupFailure(value: object): CleanupFailurePolicy {\n const cleanupFailure: unknown = hasOwn(value, 'cleanupFailure') ? Reflect.get(value, 'cleanupFailure') : 'report';\n\n if (cleanupFailure !== 'quarantine' && cleanupFailure !== 'report') {\n throw new TypeError('instantiateModule cleanupFailure must be \"report\" or \"quarantine\".');\n }\n\n return cleanupFailure;\n}\n\nfunction snapshotModuleErrorReporter(value: object): ErrorReporter | undefined {\n const reporter: unknown = hasOwn(value, 'reporter') ? Reflect.get(value, 'reporter') : undefined;\n\n if (reporter !== undefined && typeof reporter !== 'function') {\n throw new TypeError('instantiateModule reporter must be a function.');\n }\n\n return reporter as ErrorReporter | undefined;\n}\n\nfunction snapshotModuleInstanceOptions(value: unknown): {\n readonly cleanupFailure: CleanupFailurePolicy;\n readonly reporter: ErrorReporter | undefined;\n} {\n if (value === undefined) return defaultModuleInstanceOptions;\n\n assertPlainOptions(value, 'instantiateModule');\n assertKnownOptionKeys(value, moduleInstanceOptionKeys, 'instantiateModule');\n\n return {\n cleanupFailure: snapshotModuleCleanupFailure(value),\n reporter: snapshotModuleErrorReporter(value),\n };\n}\n\nfunction requireModuleDefinition(definition: object): ModuleDefinitionRecord {\n const record = moduleDefinitions.get(definition);\n\n if (record === undefined) throw new TypeError('Feature definition is not authentic.');\n\n return record;\n}\n\nfunction requireModuleInstance(instance: object): ModuleInstanceRecord {\n const record = moduleInstances.get(instance);\n\n if (record === undefined) throw new TypeError('Feature instance is not authentic.');\n\n return record;\n}\n\nfunction assertInstanceCanOpen(record: ModuleInstanceRecord): void {\n if (record.operation !== undefined || record.state === 'retired' || record.state === 'retiring') {\n throw new TypeError('Feature instance is retiring or retired.');\n }\n\n if (record.state === 'assembly') record.state = 'active';\n}\n\nfunction requireActiveDefinition(record: ModuleInstanceRecord): ModuleDefinitionRecord {\n const definition = record.definition;\n\n if (definition === undefined) throw new TypeError('Feature instance is retired.');\n\n return definition;\n}\n\nfunction requireActiveLocal(record: ModuleInstanceRecord): LocalModuleInstanceRecord {\n const local = record.local;\n\n if (local === undefined) throw new TypeError('Feature instance is retired.');\n\n return local;\n}\n\nexport {\n assertInstanceCanOpen,\n assertPlainModuleOptions,\n closedModuleDrainOutcome,\n closedModuleScopeDrainOutcome,\n closedModuleScopeRetirement,\n moduleDefinitions,\n moduleInstances,\n readyModuleScopeOpenOutcome,\n reportModuleCleanupFailure,\n requireActiveDefinition,\n requireActiveLocal,\n requireModuleDefinition,\n requireModuleInstance,\n scopeRetirements,\n snapshotModuleInstanceOptions,\n};\n"],"names":["closedModuleDrainOutcome","closedModuleScopeDrainOutcome","readyModuleScopeOpenOutcome","closedModuleScopeRetirement","scopeRetirements","moduleDefinitions","moduleInstances","moduleDefinitionOptionKeys","moduleInstanceOptionKeys","defaultModuleInstanceOptions","assertKnownOptionKeys","value","keys","subject","propertyKey","assertPlainOptions","prototype","assertPlainModuleOptions","hasOwn","reportModuleCleanupFailure","error","reporter","reportDetachedError","result","snapshotModuleCleanupFailure","cleanupFailure","snapshotModuleErrorReporter","snapshotModuleInstanceOptions","requireModuleDefinition","definition","record","requireModuleInstance","instance","assertInstanceCanOpen","requireActiveDefinition","requireActiveLocal","local"],"mappings":"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"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import type { Call, DeclarationId } from '@opetope/core';
|
|
2
|
+
import type { Awaitable, ExactInput, ExactVoidResult, IsAny } from '@opetope/core/internal';
|
|
3
|
+
import type { AttachmentCallRefIdentity } from './attachment-call-declaration.js';
|
|
4
|
+
import type { LifetimeAttachmentRefIdentity, ScopeBlueprintIdentity } from './attachment-declaration.js';
|
|
5
|
+
import type { ModuleInstanceRecord as LocalModuleInstanceRecord, LocalScopeDrainOutcome, LocalScopeInstance, LocalScopeRetirement } from './module-instance.js';
|
|
6
|
+
import type { CompiledModuleTemplateIR } from './module-template-ir.js';
|
|
7
|
+
declare const moduleDefinitionBrand: unique symbol;
|
|
8
|
+
declare const moduleInstanceBrand: unique symbol;
|
|
9
|
+
declare const moduleAttachmentRefBrand: unique symbol;
|
|
10
|
+
declare const moduleAttachmentValueBrand: unique symbol;
|
|
11
|
+
declare const moduleCallRefBrand: unique symbol;
|
|
12
|
+
declare const moduleCallSignatureBrand: unique symbol;
|
|
13
|
+
declare const moduleOwnerBrand: unique symbol;
|
|
14
|
+
declare const moduleRetirementBrand: unique symbol;
|
|
15
|
+
declare const moduleRuntimeRefBrand: unique symbol;
|
|
16
|
+
declare const moduleScopeRefBrand: unique symbol;
|
|
17
|
+
declare const moduleScopeValueBrand: unique symbol;
|
|
18
|
+
type CleanupFailurePolicy = 'quarantine' | 'report';
|
|
19
|
+
type ErrorReporter = (error: unknown) => PromiseLike<void> | void;
|
|
20
|
+
type LiteralStepKey<Key extends string> = Key extends '' ? never : string extends Key ? never : Key;
|
|
21
|
+
interface ModuleRuntimeRefIdentity<Owner extends string = string> {
|
|
22
|
+
readonly [moduleOwnerBrand]: (owner: Owner) => Owner;
|
|
23
|
+
readonly [moduleRuntimeRefBrand]: true;
|
|
24
|
+
}
|
|
25
|
+
interface ModuleAttachmentRefIdentity<Owner extends string = string> extends ModuleRuntimeRefIdentity<Owner> {
|
|
26
|
+
readonly [moduleAttachmentRefBrand]: true;
|
|
27
|
+
}
|
|
28
|
+
interface ModuleCallRefIdentity<Owner extends string = string> extends ModuleRuntimeRefIdentity<Owner> {
|
|
29
|
+
readonly [moduleCallRefBrand]: true;
|
|
30
|
+
}
|
|
31
|
+
interface ModuleScopeRefIdentity<Owner extends string = string> extends ModuleRuntimeRefIdentity<Owner> {
|
|
32
|
+
readonly [moduleScopeRefBrand]: true;
|
|
33
|
+
}
|
|
34
|
+
type ModuleRuntimeRef<Owner extends string = string> = ModuleAttachmentRefIdentity<Owner> | ModuleCallRefIdentity<Owner> | ModuleScopeRefIdentity<Owner>;
|
|
35
|
+
type ModuleRuntimeRecord<Owner extends string = string> = Readonly<Record<string, ModuleRuntimeRef<Owner>>>;
|
|
36
|
+
type IsUnion<Value, Whole = Value> = IsAny<Value> extends true ? false : Value extends Whole ? ([Whole] extends [Value] ? false : true) : never;
|
|
37
|
+
type ExactNonUnionRuntime<Runtime> = IsAny<Runtime> extends true ? {
|
|
38
|
+
readonly __moduleRuntimeMustNotBeAny: never;
|
|
39
|
+
} : true extends IsUnion<Runtime> ? {
|
|
40
|
+
readonly __moduleRuntimeMustBeOneExactRecord: never;
|
|
41
|
+
} : unknown;
|
|
42
|
+
interface ModuleAttachmentRef<Value, Owner extends string = string> extends ModuleAttachmentRefIdentity<Owner> {
|
|
43
|
+
readonly [moduleAttachmentValueBrand]: (_value: Value) => Value;
|
|
44
|
+
}
|
|
45
|
+
interface ModuleCallRef<Input, Output, Owner extends string = string> extends ModuleCallRefIdentity<Owner> {
|
|
46
|
+
readonly [moduleCallSignatureBrand]: (input: Input) => Output;
|
|
47
|
+
}
|
|
48
|
+
type ModuleCallContext<Value> = {
|
|
49
|
+
readonly signal: AbortSignal;
|
|
50
|
+
readonly source: Value;
|
|
51
|
+
readonly throwIfAborted: () => void;
|
|
52
|
+
};
|
|
53
|
+
interface ModuleAttachmentExecutionContext {
|
|
54
|
+
readonly invoke: <Input, Output>(target: Call<Input, Output>, input: Input) => Promise<Output>;
|
|
55
|
+
readonly signal: AbortSignal;
|
|
56
|
+
readonly throwIfAborted: () => void;
|
|
57
|
+
}
|
|
58
|
+
interface ModuleAttachmentOwnedStep<Key extends string, Result, CleanupResult> {
|
|
59
|
+
readonly cleanup: (input: {
|
|
60
|
+
readonly context: ModuleAttachmentExecutionContext;
|
|
61
|
+
}) => CleanupResult;
|
|
62
|
+
readonly key: Key & LiteralStepKey<Key>;
|
|
63
|
+
readonly run: (input: {
|
|
64
|
+
readonly context: ModuleAttachmentExecutionContext;
|
|
65
|
+
}) => Awaitable<Result>;
|
|
66
|
+
}
|
|
67
|
+
interface ModuleAttachmentOwner {
|
|
68
|
+
readonly step: <const Key extends string, Result, CleanupResult extends Awaitable<void>, const Definition extends ModuleAttachmentOwnedStep<Key, Result, CleanupResult>>(definition: ExactInput<Definition, ModuleAttachmentOwnedStep<Key, Result, CleanupResult>> & ExactVoidResult<CleanupResult>) => Promise<Result>;
|
|
69
|
+
}
|
|
70
|
+
interface ModuleAttachmentOpenContext<Value> {
|
|
71
|
+
readonly source: Value;
|
|
72
|
+
/** Owned step: the word `own` names the section, so the attachment context spells the member itself (D94). */
|
|
73
|
+
readonly step: ModuleAttachmentOwner['step'];
|
|
74
|
+
}
|
|
75
|
+
type ModuleAttachmentCloseContext<Value> = {
|
|
76
|
+
readonly context: ModuleAttachmentExecutionContext;
|
|
77
|
+
readonly source: Value;
|
|
78
|
+
};
|
|
79
|
+
interface ModuleAttachmentOptions<Value, OpenResult extends Awaitable<void> = Awaitable<void>, CloseResult extends Awaitable<void> = Awaitable<void>> {
|
|
80
|
+
readonly close: (input: ModuleAttachmentCloseContext<Value>) => CloseResult;
|
|
81
|
+
readonly open: (input: ModuleAttachmentOpenContext<Value>) => OpenResult;
|
|
82
|
+
}
|
|
83
|
+
interface ModuleScopeRef<Value, Owner extends string = string> extends ModuleScopeRefIdentity<Owner> {
|
|
84
|
+
readonly attach: <OpenResult extends Awaitable<void>, CloseResult extends Awaitable<void>, const Options extends ModuleAttachmentOptions<Value, OpenResult, CloseResult>>(options: ExactInput<Options, ModuleAttachmentOptions<Value, OpenResult, CloseResult>> & ExactVoidResult<CloseResult> & ExactVoidResult<OpenResult>) => ModuleAttachmentRef<Value, Owner>;
|
|
85
|
+
readonly [moduleScopeValueBrand]: (_value: Value) => Value;
|
|
86
|
+
}
|
|
87
|
+
interface ModuleScopeClosedOutcome {
|
|
88
|
+
readonly kind: 'closed';
|
|
89
|
+
}
|
|
90
|
+
interface ModuleAttachmentRetirementFailure {
|
|
91
|
+
readonly attachmentId: DeclarationId;
|
|
92
|
+
readonly errors: readonly unknown[];
|
|
93
|
+
readonly phase: 'close' | 'retry' | 'rollback';
|
|
94
|
+
}
|
|
95
|
+
interface ModuleScopeQuarantinedOutcome {
|
|
96
|
+
readonly failures: readonly ModuleAttachmentRetirementFailure[];
|
|
97
|
+
readonly kind: 'quarantined';
|
|
98
|
+
}
|
|
99
|
+
type ModuleScopeDrainOutcome = ModuleScopeClosedOutcome | ModuleScopeQuarantinedOutcome;
|
|
100
|
+
interface ModuleScopeRetirement {
|
|
101
|
+
readonly drain: () => Promise<ModuleScopeDrainOutcome>;
|
|
102
|
+
readonly retry: () => Promise<ModuleScopeDrainOutcome>;
|
|
103
|
+
}
|
|
104
|
+
interface ModuleScopeReadyOutcome {
|
|
105
|
+
readonly kind: 'ready';
|
|
106
|
+
}
|
|
107
|
+
interface ModuleScopeNotReadyOutcome {
|
|
108
|
+
readonly attachmentId: DeclarationId;
|
|
109
|
+
readonly cause: unknown;
|
|
110
|
+
readonly drain: ModuleScopeDrainOutcome;
|
|
111
|
+
readonly kind: 'not-ready';
|
|
112
|
+
readonly reason: 'cancelled' | 'closed' | 'failed' | 'quarantined' | 'superseded';
|
|
113
|
+
readonly retirement: ModuleScopeRetirement;
|
|
114
|
+
}
|
|
115
|
+
interface ModuleScopeRetiredOutcome {
|
|
116
|
+
readonly drain: ModuleScopeDrainOutcome;
|
|
117
|
+
readonly kind: 'retired';
|
|
118
|
+
readonly retirement: ModuleScopeRetirement;
|
|
119
|
+
}
|
|
120
|
+
type ModuleScopeOpenOutcome = ModuleScopeNotReadyOutcome | ModuleScopeReadyOutcome | ModuleScopeRetiredOutcome;
|
|
121
|
+
type ModuleAttachmentValue<Within> = Within extends ModuleAttachmentRef<infer Value, infer _Owner> ? Value : never;
|
|
122
|
+
interface ModuleCallOptions<Input, Output, Within> {
|
|
123
|
+
readonly run: (input: Input, context: ModuleCallContext<ModuleAttachmentValue<Within>>) => Output | PromiseLike<Output>;
|
|
124
|
+
readonly within: Within;
|
|
125
|
+
}
|
|
126
|
+
type ModuleCallBuilder<Owner extends string> = <Input, Output, Within extends ModuleAttachmentRefIdentity<Owner>, const Options extends ModuleCallOptions<Input, Output, Within>>(options: ExactInput<Options, ModuleCallOptions<Input, Output, Within>>) => ModuleCallRef<Input, Output, Owner>;
|
|
127
|
+
type ModuleScopeBuilder<Owner extends string> = <Value>() => ModuleScopeRef<Value, Owner>;
|
|
128
|
+
interface ModuleRuntimeBuilder<Owner extends string = string> {
|
|
129
|
+
readonly call: ModuleCallBuilder<Owner>;
|
|
130
|
+
readonly scope: ModuleScopeBuilder<Owner>;
|
|
131
|
+
}
|
|
132
|
+
interface ModuleDefinitionOptions<Owner extends string, Runtime extends ModuleRuntimeRecord<Owner>> {
|
|
133
|
+
readonly id: Owner;
|
|
134
|
+
readonly runtime: ((builder: ModuleRuntimeBuilder<Owner>) => Runtime) & ExactNonUnionRuntime<Runtime>;
|
|
135
|
+
}
|
|
136
|
+
interface ModuleDefinition<Owner extends string = string, Runtime extends ModuleRuntimeRecord<Owner> = ModuleRuntimeRecord<Owner>> {
|
|
137
|
+
readonly id: DeclarationId;
|
|
138
|
+
readonly [moduleDefinitionBrand]: true;
|
|
139
|
+
readonly [moduleOwnerBrand]: (owner: Owner) => Owner;
|
|
140
|
+
readonly runtime: Runtime;
|
|
141
|
+
}
|
|
142
|
+
interface ModuleScopeInstance<Value> {
|
|
143
|
+
readonly open: (value: Value) => Promise<ModuleScopeOpenOutcome>;
|
|
144
|
+
readonly retire: () => ModuleScopeRetirement;
|
|
145
|
+
}
|
|
146
|
+
interface ModuleRetirementClosedOutcome {
|
|
147
|
+
readonly kind: 'closed';
|
|
148
|
+
}
|
|
149
|
+
interface ModuleScopeRetirementFailure {
|
|
150
|
+
readonly kind: 'scope';
|
|
151
|
+
readonly outcome: Extract<ModuleScopeDrainOutcome, {
|
|
152
|
+
readonly kind: 'quarantined';
|
|
153
|
+
}>;
|
|
154
|
+
readonly scope: ModuleScopeRefIdentity;
|
|
155
|
+
}
|
|
156
|
+
interface ModuleScopeFenceFailure {
|
|
157
|
+
readonly error: unknown;
|
|
158
|
+
readonly kind: 'scope-fence';
|
|
159
|
+
readonly scope: ModuleScopeRefIdentity;
|
|
160
|
+
}
|
|
161
|
+
interface ModuleParticipantRetirementFailure {
|
|
162
|
+
readonly error: unknown;
|
|
163
|
+
readonly kind: 'participant';
|
|
164
|
+
readonly phase: 'drain' | 'fence' | 'retry';
|
|
165
|
+
readonly slot: number;
|
|
166
|
+
}
|
|
167
|
+
type ModuleRetirementFailure = ModuleParticipantRetirementFailure | ModuleScopeFenceFailure | ModuleScopeRetirementFailure;
|
|
168
|
+
interface ModuleRetirementQuarantinedOutcome {
|
|
169
|
+
readonly failures: readonly ModuleRetirementFailure[];
|
|
170
|
+
readonly kind: 'quarantined';
|
|
171
|
+
}
|
|
172
|
+
type ModuleDrainOutcome = ModuleRetirementClosedOutcome | ModuleRetirementQuarantinedOutcome;
|
|
173
|
+
interface ModuleCleanupErrorDiagnostic {
|
|
174
|
+
readonly message: string;
|
|
175
|
+
readonly name: string;
|
|
176
|
+
readonly stack?: string;
|
|
177
|
+
}
|
|
178
|
+
interface ModuleAttachmentCleanupFailureDiagnostic {
|
|
179
|
+
readonly attachmentId: DeclarationId;
|
|
180
|
+
readonly errors: readonly ModuleCleanupErrorDiagnostic[];
|
|
181
|
+
readonly phase: ModuleAttachmentRetirementFailure['phase'];
|
|
182
|
+
}
|
|
183
|
+
type ModuleCleanupFailureDiagnostic = {
|
|
184
|
+
readonly error: ModuleCleanupErrorDiagnostic;
|
|
185
|
+
readonly kind: 'participant';
|
|
186
|
+
readonly phase: 'drain' | 'fence' | 'retry';
|
|
187
|
+
readonly slot: number;
|
|
188
|
+
} | {
|
|
189
|
+
readonly error: ModuleCleanupErrorDiagnostic;
|
|
190
|
+
readonly kind: 'scope-fence';
|
|
191
|
+
readonly scope: string;
|
|
192
|
+
} | {
|
|
193
|
+
readonly failures: readonly ModuleAttachmentCleanupFailureDiagnostic[];
|
|
194
|
+
readonly kind: 'scope';
|
|
195
|
+
readonly scope: string;
|
|
196
|
+
};
|
|
197
|
+
interface ModuleRetirement {
|
|
198
|
+
readonly drain: () => Promise<ModuleDrainOutcome>;
|
|
199
|
+
readonly [moduleRetirementBrand]: true;
|
|
200
|
+
readonly retry: () => Promise<ModuleDrainOutcome>;
|
|
201
|
+
}
|
|
202
|
+
interface ModuleInstanceOptions {
|
|
203
|
+
readonly cleanupFailure?: CleanupFailurePolicy;
|
|
204
|
+
readonly reporter?: ErrorReporter;
|
|
205
|
+
}
|
|
206
|
+
interface ModuleInstanceRef<Owner extends string = string> {
|
|
207
|
+
readonly [moduleInstanceBrand]: true;
|
|
208
|
+
readonly [moduleOwnerBrand]: (owner: Owner) => Owner;
|
|
209
|
+
}
|
|
210
|
+
interface ModuleInstance<Owner extends string = string> extends ModuleInstanceRef<Owner> {
|
|
211
|
+
readonly retire: () => ModuleRetirement;
|
|
212
|
+
scope<Value>(scope: ModuleScopeRef<Value, Owner>): ModuleScopeInstance<Value>;
|
|
213
|
+
}
|
|
214
|
+
interface ModuleRetirementParticipantHandle {
|
|
215
|
+
readonly drain: () => Awaitable<void>;
|
|
216
|
+
readonly retry: () => Awaitable<void>;
|
|
217
|
+
}
|
|
218
|
+
interface ModuleRetirementParticipant {
|
|
219
|
+
readonly fence: () => ModuleRetirementParticipantHandle | void;
|
|
220
|
+
}
|
|
221
|
+
type ModuleDefinitionRecord = {
|
|
222
|
+
readonly plan: CompiledModuleTemplateIR;
|
|
223
|
+
readonly runtime: InternalModuleRuntimeRecord;
|
|
224
|
+
readonly scopeEntries: readonly ModuleScopeDefinitionEntry[];
|
|
225
|
+
};
|
|
226
|
+
type ModuleScopeDefinitionEntry = {
|
|
227
|
+
readonly key: string;
|
|
228
|
+
readonly scope: ScopeBlueprintIdentity;
|
|
229
|
+
};
|
|
230
|
+
type InternalModuleRuntimeRef = AttachmentCallRefIdentity | LifetimeAttachmentRefIdentity | ScopeBlueprintIdentity;
|
|
231
|
+
type InternalModuleRuntimeRecord = Readonly<Record<string, InternalModuleRuntimeRef>>;
|
|
232
|
+
type RegisteredParticipant = {
|
|
233
|
+
readonly fence: () => ModuleRetirementParticipantHandle | void;
|
|
234
|
+
readonly slot: number;
|
|
235
|
+
};
|
|
236
|
+
type ScopeFrontier = {
|
|
237
|
+
handle: LocalScopeRetirement;
|
|
238
|
+
readonly kind: 'scope';
|
|
239
|
+
outcome: Extract<LocalScopeDrainOutcome, {
|
|
240
|
+
readonly kind: 'quarantined';
|
|
241
|
+
}> | undefined;
|
|
242
|
+
readonly scope: ScopeBlueprintIdentity;
|
|
243
|
+
};
|
|
244
|
+
type ScopeFenceFrontier = {
|
|
245
|
+
error: unknown;
|
|
246
|
+
readonly kind: 'scope-fence';
|
|
247
|
+
readonly scope: ScopeBlueprintIdentity;
|
|
248
|
+
};
|
|
249
|
+
type ParticipantFenceFrontier = {
|
|
250
|
+
error: unknown;
|
|
251
|
+
readonly kind: 'participant-fence';
|
|
252
|
+
readonly participant: RegisteredParticipant;
|
|
253
|
+
};
|
|
254
|
+
type ParticipantHandleFrontier = {
|
|
255
|
+
error: unknown;
|
|
256
|
+
readonly handle: ModuleRetirementParticipantHandle;
|
|
257
|
+
readonly kind: 'participant-handle';
|
|
258
|
+
phase: 'drain' | 'retry';
|
|
259
|
+
readonly slot: number;
|
|
260
|
+
};
|
|
261
|
+
type RetirementFrontier = ParticipantFenceFrontier | ParticipantHandleFrontier | ScopeFenceFrontier | ScopeFrontier;
|
|
262
|
+
type ModuleRetirementRecord = {
|
|
263
|
+
activeCallbackOperations: number;
|
|
264
|
+
drained: boolean;
|
|
265
|
+
drainPromise: Promise<ModuleDrainOutcome> | undefined;
|
|
266
|
+
frontiers: RetirementFrontier[];
|
|
267
|
+
readonly handleState: ModuleRetirementHandleState;
|
|
268
|
+
outcome: ModuleDrainOutcome | undefined;
|
|
269
|
+
retryPromise: Promise<ModuleDrainOutcome> | undefined;
|
|
270
|
+
readonly runtime: ModuleRetirement;
|
|
271
|
+
};
|
|
272
|
+
type ModuleRetirementHandleState = {
|
|
273
|
+
instanceRecord: ModuleInstanceRecord | undefined;
|
|
274
|
+
outcome: ModuleDrainOutcome | undefined;
|
|
275
|
+
retirement: ModuleRetirementRecord | undefined;
|
|
276
|
+
};
|
|
277
|
+
type ModuleInstanceRecord = {
|
|
278
|
+
readonly cleanupFailure: CleanupFailurePolicy;
|
|
279
|
+
definition: ModuleDefinitionRecord | undefined;
|
|
280
|
+
local: LocalModuleInstanceRecord | undefined;
|
|
281
|
+
nextParticipantSlot: number;
|
|
282
|
+
operation: 'registering' | 'retiring' | undefined;
|
|
283
|
+
readonly participants: RegisteredParticipant[];
|
|
284
|
+
reporter: ErrorReporter | undefined;
|
|
285
|
+
retirement: ModuleRetirementRecord | undefined;
|
|
286
|
+
readonly scopeHandles: Map<ScopeBlueprintIdentity, ModuleScopeHandleState<unknown>>;
|
|
287
|
+
state: 'active' | 'assembly' | 'retired' | 'retiring';
|
|
288
|
+
};
|
|
289
|
+
/** One record per scope handle: the live halves the retirement clears plus the facade the caller keeps (D166). */
|
|
290
|
+
type ModuleScopeHandleState<Value> = {
|
|
291
|
+
local: LocalScopeInstance<Value> | undefined;
|
|
292
|
+
record: ModuleInstanceRecord | undefined;
|
|
293
|
+
readonly runtime: ModuleScopeInstance<Value>;
|
|
294
|
+
};
|
|
295
|
+
export type { Awaitable, CleanupFailurePolicy, ErrorReporter, ExactInput, ExactNonUnionRuntime, InternalModuleRuntimeRecord, InternalModuleRuntimeRef, ModuleAttachmentCleanupFailureDiagnostic, ModuleAttachmentCloseContext, ModuleAttachmentOpenContext, ModuleAttachmentOptions, ModuleAttachmentRef, ModuleAttachmentRefIdentity, ModuleAttachmentRetirementFailure, ModuleCallBuilder, ModuleCallContext, ModuleCallOptions, ModuleCallRef, ModuleCallRefIdentity, ModuleCleanupErrorDiagnostic, ModuleCleanupFailureDiagnostic, ModuleDefinition, ModuleDefinitionOptions, ModuleDefinitionRecord, ModuleDrainOutcome, ModuleInstance, ModuleInstanceOptions, ModuleInstanceRecord, ModuleInstanceRef, ModuleParticipantRetirementFailure, ModuleRetirement, ModuleRetirementFailure, ModuleRetirementHandleState, ModuleRetirementParticipant, ModuleRetirementParticipantHandle, ModuleRetirementQuarantinedOutcome, ModuleRetirementRecord, ModuleRuntimeBuilder, ModuleRuntimeRecord, ModuleRuntimeRef, ModuleRuntimeRefIdentity, ModuleScopeBuilder, ModuleScopeDefinitionEntry, ModuleScopeDrainOutcome, ModuleScopeHandleState, ModuleScopeInstance, ModuleScopeNotReadyOutcome, ModuleScopeOpenOutcome, ModuleScopeRef, ModuleScopeRefIdentity, ModuleScopeRetirement, ModuleScopeRetirementFailure, ParticipantFenceFrontier, ParticipantHandleFrontier, RegisteredParticipant, RetirementFrontier, ScopeFenceFrontier, ScopeFrontier, };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { defineModule, getModuleScopeEntries, getModuleTemplateIR } from './public-module-definition.js';
|
|
2
|
+
export { instantiateModule, registerModuleRetirementParticipant, resolveModuleCallTarget, } from './public-module-instance.js';
|
|
3
|
+
export { projectModuleCleanupFailures } from './public-module-retirement-diagnostics.js';
|
|
4
|
+
export type { CleanupFailurePolicy, ErrorReporter, ExactNonUnionRuntime, ModuleAttachmentCleanupFailureDiagnostic, ModuleAttachmentCloseContext, ModuleAttachmentOpenContext, ModuleAttachmentOptions, ModuleAttachmentRef, ModuleAttachmentRefIdentity, ModuleCallContext, ModuleCallRef, ModuleCallRefIdentity, ModuleCleanupErrorDiagnostic, ModuleCleanupFailureDiagnostic, ModuleDefinition, ModuleDefinitionOptions, ModuleDrainOutcome, ModuleInstance, ModuleInstanceOptions, ModuleInstanceRef, ModuleParticipantRetirementFailure, ModuleRetirement, ModuleRetirementFailure, ModuleRetirementParticipant, ModuleRetirementParticipantHandle, ModuleRetirementQuarantinedOutcome, ModuleRuntimeBuilder, ModuleRuntimeRecord, ModuleRuntimeRef, ModuleRuntimeRefIdentity, ModuleScopeDrainOutcome, ModuleScopeInstance, ModuleScopeOpenOutcome, ModuleScopeRef, ModuleScopeRetirement, ModuleScopeRetirementFailure, } from './public-module-types.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ResourceRequestKey, ResourceRetention } from './resource-types.js';
|
|
2
|
+
type ResourceCacheEntry<Data> = {
|
|
3
|
+
readonly data: Data;
|
|
4
|
+
};
|
|
5
|
+
interface ResourceCache<Data, Key extends ResourceRequestKey> {
|
|
6
|
+
readonly clear: () => void;
|
|
7
|
+
readonly get: (key: Key) => ResourceCacheEntry<Data> | undefined;
|
|
8
|
+
readonly set: (key: Key, data: Data) => void;
|
|
9
|
+
}
|
|
10
|
+
declare function createRetainedResourceCache<Data, Key extends ResourceRequestKey>(retention: ResourceRetention): ResourceCache<Data, Key> | undefined;
|
|
11
|
+
export { createRetainedResourceCache };
|
|
12
|
+
export type { ResourceCache };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function d(r){const e=new Map;return{clear(){e.clear()},get(t){const n=e.get(t);if(n!==void 0)return e.delete(t),e.set(t,n),n},set(t,n){for(e.delete(t),e.set(t,{data:n});e.size>r;){const c=e.keys().next().value;if(c===void 0)break;e.delete(c)}}}}function i(r){return r.kind==="scope"?d(r.capacity):void 0}export{i as createRetainedResourceCache};
|
|
2
|
+
//# sourceMappingURL=resource-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-cache.js","sources":["../src/resource-cache.ts"],"sourcesContent":["import type { ResourceRequestKey, ResourceRetention } from './resource-types';\n\ntype ResourceCacheEntry<Data> = { readonly data: Data };\n\ninterface ResourceCache<Data, Key extends ResourceRequestKey> {\n readonly clear: () => void;\n readonly get: (key: Key) => ResourceCacheEntry<Data> | undefined;\n readonly set: (key: Key, data: Data) => void;\n}\n\nfunction createResourceCache<Data, Key extends ResourceRequestKey>(capacity: number): ResourceCache<Data, Key> {\n const entries = new Map<Key, ResourceCacheEntry<Data>>();\n\n return {\n clear(): void {\n entries.clear();\n },\n get(key: Key): ResourceCacheEntry<Data> | undefined {\n const entry = entries.get(key);\n\n if (entry === undefined) return undefined;\n\n entries.delete(key);\n entries.set(key, entry);\n\n return entry;\n },\n set(key: Key, data: Data): void {\n entries.delete(key);\n entries.set(key, { data });\n\n while (entries.size > capacity) {\n const oldest = entries.keys().next().value;\n\n if (oldest === undefined) break;\n\n entries.delete(oldest);\n }\n },\n };\n}\n\nfunction createRetainedResourceCache<Data, Key extends ResourceRequestKey>(\n retention: ResourceRetention,\n): ResourceCache<Data, Key> | undefined {\n return retention.kind === 'scope' ? createResourceCache(retention.capacity) : undefined;\n}\n\nexport { createRetainedResourceCache };\nexport type { ResourceCache };\n"],"names":["createResourceCache","capacity","entries","key","entry","data","oldest","createRetainedResourceCache","retention"],"mappings":"AAUA,SAASA,EAA0DC,EAAgB,CACjF,MAAMC,EAAU,IAAI,IAEpB,MAAO,CACL,OAAK,CACHA,EAAQ,MAAK,CACf,EACA,IAAIC,EAAQ,CACV,MAAMC,EAAQF,EAAQ,IAAIC,CAAG,EAE7B,GAAIC,IAAU,OAEd,OAAAF,EAAQ,OAAOC,CAAG,EAClBD,EAAQ,IAAIC,EAAKC,CAAK,EAEfA,CACT,EACA,IAAID,EAAUE,EAAU,CAItB,IAHAH,EAAQ,OAAOC,CAAG,EAClBD,EAAQ,IAAIC,EAAK,CAAE,KAAAE,CAAI,CAAE,EAElBH,EAAQ,KAAOD,GAAU,CAC9B,MAAMK,EAASJ,EAAQ,KAAI,EAAG,KAAI,EAAG,MAErC,GAAII,IAAW,OAAW,MAE1BJ,EAAQ,OAAOI,CAAM,CACvB,CACF,EAEJ,CAEA,SAASC,EACPC,EAA4B,CAE5B,OAAOA,EAAU,OAAS,QAAUR,EAAoBQ,EAAU,QAAQ,EAAI,MAChF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Readable } from '@opetope/core';
|
|
2
|
+
import type { Awaitable, CallObservationSlot } from '@opetope/core/internal';
|
|
3
|
+
import type { ResourceInspection } from './inspection-activity.js';
|
|
4
|
+
import type { Resource, ResourceRequestKey, ResourceRetention, ResourceRetry } from './resource-types.js';
|
|
5
|
+
import type { RuntimeErrorReporter } from './runtime-error-reporting.js';
|
|
6
|
+
type ResourceLoadContext<Source> = {
|
|
7
|
+
readonly signal: AbortSignal;
|
|
8
|
+
readonly source: Source;
|
|
9
|
+
};
|
|
10
|
+
type ResourceControllerOptions<Source, Target, Data, Key extends ResourceRequestKey> = {
|
|
11
|
+
readonly allocateGeneration?: () => number;
|
|
12
|
+
readonly key: (target: Target) => Key;
|
|
13
|
+
readonly load: (target: Target, context: ResourceLoadContext<Source>) => Awaitable<Data>;
|
|
14
|
+
readonly reporter?: RuntimeErrorReporter;
|
|
15
|
+
readonly retention: ResourceRetention;
|
|
16
|
+
readonly retry?: ResourceRetry;
|
|
17
|
+
readonly source: Source;
|
|
18
|
+
/** The public selector may answer `T | null | undefined`; both nullish answers mean «no target» (D194). */
|
|
19
|
+
readonly target: Readable<Target | null | undefined>;
|
|
20
|
+
};
|
|
21
|
+
interface ManagedResourceRef<Data, Key extends ResourceRequestKey> extends Resource<Data, Key> {
|
|
22
|
+
readonly close: () => Promise<void>;
|
|
23
|
+
readonly fence: () => void;
|
|
24
|
+
readonly inspect: (capacity: number) => ResourceInspection;
|
|
25
|
+
readonly observe: (slot: CallObservationSlot) => void;
|
|
26
|
+
}
|
|
27
|
+
declare function createResourceController<Source, Target, Data, Key extends ResourceRequestKey>(options: ResourceControllerOptions<Source, Target, Data, Key>, register?: (controller: ManagedResourceRef<Data, Key>) => void): ManagedResourceRef<Data, Key>;
|
|
28
|
+
export { createResourceController };
|
|
29
|
+
export type { ManagedResourceRef, ResourceControllerOptions, ResourceLoadContext };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createRetainedResourceCache as ce}from"./resource-cache.js";import{idleSnapshot as K,pendingSnapshot as de,readResourceData as L}from"./resource-snapshot.js";import{reportRuntimeFailure as fe}from"./runtime-error-reporting.js";let le=0;function be(r,z){var W,X;const M=new Set,w=new Map;let g;const a=ce(r.retention),Y=((W=r.retry)==null?void 0:W.attempts)??1,Z=((X=r.retry)==null?void 0:X.delayMs)??0;let s=!1,E,o=!1,O=0,j=0,m,l=0,h=0,T,u,c,k=0,d=K,p;const A=()=>{var e;return k+=1,l=((e=r.allocateGeneration)==null?void 0:e.call(r))??l+1,l},C=e=>s&&!o&&l===e,B=e=>s&&!o&&k===e,D=e=>m===e&&!e.abort.signal.aborted&&C(e.generation),v=e=>fe(e,r.reporter),b=()=>{var e;return(e=g==null?void 0:g.changed)==null?void 0:e.call(g)},_=()=>{b();for(const e of[...M])try{e()}catch(t){v(t)}},R=e=>{d=Object.freeze(e),_()},$=()=>{T!==void 0&&(clearTimeout(T),T=void 0)},x=()=>{$();const e=m;m=void 0,e==null||e.abort.abort()},G=(e,t,n,i)=>{const y=L(d);R({attempt:t,data:y.present?y.data:void 0,error:e,generation:n,key:i,retryable:!0,stale:y.present,status:"error"}),v(e)},P=(e,t,n,i,y=L(d))=>{if(!C(t)||(x(),!C(t)))return;const S=new AbortController,f={abort:S,attempt:e,generation:t,identity:++le,started:!1};m=f;const F=Promise.resolve().then(async()=>{if(!D(f))return;f.started=!0,b();let I;try{I=await r.load(i,Object.freeze({signal:S.signal,source:r.source}))}catch(oe){if(!D(f))return;if(m=void 0,e<Y){T=setTimeout(()=>{T=void 0,P(e+1,t,n,i)},Z);return}G(oe,e,t,n);return}D(f)&&(m=void 0,a==null||a.set(n,I),R({attempt:e,data:I,error:void 0,generation:t,key:n,stale:!1,status:"ready"}))});w.set(F,f),R(de(e,t,n,y)),b(),F.finally(()=>{w.delete(F),b()})},q=(e,t,n,i)=>{const y=i?L(d):{present:!1},S=A();if(x(),!C(S))return;const f=n?a==null?void 0:a.get(t):void 0;if(f!==void 0){R({attempt:1,data:f.data,error:void 0,generation:S,key:t,stale:!1,status:"ready"});return}P(1,S,t,e,y)},ee=()=>{if(u===void 0&&c===void 0&&d.status==="idle")return;u=void 0,c=void 0;const e=A();x(),C(e)&&R({...K,generation:e})},te=(e,t)=>{let n;try{n=r.key(e)}catch(i){v(i);return}if(B(t)){if(u!==void 0&&Object.is(u,n)){c=e;return}u=n,c=e,q(e,n,!0,!1)}},H=()=>{if(!s||o)return;const e=++k;let t;try{t=r.target.getSnapshot()}catch(n){v(n);return}if(B(e)){if(t==null){ee();return}te(t,e)}},J=e=>{try{e==null||e()}catch(t){v(t)}},N=e=>{s=!1,O+=1,j+=1,e&&(o=!0,h=0,a==null||a.clear());const t=p;p=void 0,u=void 0,c=void 0;const n=A();x(),J(t),!(!e&&(s||o||l!==n))&&R({...K,generation:n})},Q=()=>{if(s||o)return;s=!0;const e=O+=1;try{const t=r.target.subscribe(H);if(o||!s||O!==e){J(t);return}p=t,H()}catch(t){s=!1,p=void 0,v(t)}},ne=()=>{!s||r.retention.kind==="scope"||h!==0||N(!1)},re=()=>{const e=++j;queueMicrotask(()=>{e===j&&ne()})},ie=()=>{!s||u===void 0||c===void 0||q(c,u,!1,!0)},se=()=>{!s||d.status!=="error"||u===void 0||c===void 0||P(d.attempt+1,l,u,c)},ae=()=>{a==null||a.clear(),!(!s||u===void 0||c===void 0)&&q(c,u,!1,!1)},ue=()=>{if(o)return()=>{};h+=1,j+=1,Q(),b();let e=!0;return()=>{e&&(e=!1,h-=1,b(),h===0&&r.retention.kind==="observer"&&re())}},U=()=>{o||N(!0)},V=Object.freeze({close:()=>(E!==void 0||(U(),E=(async()=>{for(;w.size!==0;)await Promise.all([...w.keys()])})()),E),fence:U,getSnapshot:()=>d,inspect(e){const t=[];let n=!1;for(const i of w.values()){if(t.length>=e){n=!0;break}t.push({attempt:i.attempt,generation:i.generation,id:String(i.identity),state:i.abort.signal.aborted?"draining":i.started?"running":"scheduled"})}return{generation:l,loads:t,retainers:o?0:h,retention:r.retention.kind,state:o?"fenced":d.status,truncated:n}},invalidate:ae,observe(e){g=e,b()},refresh:ie,retain:ue,retry:se,subscribe(e){if(typeof e!="function")throw new TypeError("Resource listener must be a function.");M.add(e);let t=!0;return()=>{t&&(t=!1,M.delete(e))}}});return z==null||z(V),r.retention.kind==="scope"&&Q(),V}export{be as createResourceController};
|
|
2
|
+
//# sourceMappingURL=resource-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-controller.js","sources":["../src/resource-controller.ts"],"sourcesContent":["import type { Readable } from '@opetope/core';\nimport type { Awaitable, CallObservationSlot } from '@opetope/core/internal';\n\nimport type { ResourceInspection } from './inspection-activity';\nimport type { ResourceLoadActivity } from './inspection-activity-protocol';\nimport { createRetainedResourceCache } from './resource-cache';\nimport type { ResourceCache } from './resource-cache';\nimport { idleSnapshot, pendingSnapshot, readResourceData } from './resource-snapshot';\nimport type { ResourceData } from './resource-snapshot';\nimport type {\n Resource,\n ResourceRequestKey,\n ResourceRetention,\n ResourceRetry,\n ResourceSnapshot,\n} from './resource-types';\nimport { reportRuntimeFailure } from './runtime-error-reporting';\nimport type { RuntimeErrorReporter } from './runtime-error-reporting';\n\ntype ResourceLoadContext<Source> = {\n readonly signal: AbortSignal;\n readonly source: Source;\n};\n\ntype ResourceControllerOptions<Source, Target, Data, Key extends ResourceRequestKey> = {\n readonly allocateGeneration?: () => number;\n readonly key: (target: Target) => Key;\n readonly load: (target: Target, context: ResourceLoadContext<Source>) => Awaitable<Data>;\n readonly reporter?: RuntimeErrorReporter;\n readonly retention: ResourceRetention;\n readonly retry?: ResourceRetry;\n readonly source: Source;\n /** The public selector may answer `T | null | undefined`; both nullish answers mean «no target» (D194). */\n readonly target: Readable<Target | null | undefined>;\n};\n\ninterface ManagedResourceRef<Data, Key extends ResourceRequestKey> extends Resource<Data, Key> {\n readonly close: () => Promise<void>;\n readonly fence: () => void;\n readonly inspect: (capacity: number) => ResourceInspection;\n readonly observe: (slot: CallObservationSlot) => void;\n}\n\ntype ResourceExecution = {\n readonly abort: AbortController;\n readonly attempt: number;\n readonly generation: number;\n readonly identity: number;\n started: boolean;\n};\n\nlet nextLoadIdentity = 0;\n\nfunction createResourceController<Source, Target, Data, Key extends ResourceRequestKey>(\n options: ResourceControllerOptions<Source, Target, Data, Key>,\n register?: (controller: ManagedResourceRef<Data, Key>) => void,\n): ManagedResourceRef<Data, Key> {\n const listeners = new Set<() => void>();\n const draining = new Map<Promise<void>, ResourceExecution>();\n let observation: CallObservationSlot | undefined;\n const cache: ResourceCache<Data, Key> | undefined = createRetainedResourceCache(options.retention);\n const maximumAttempts = options.retry?.attempts ?? 1;\n const retryDelayMs = options.retry?.delayMs ?? 0;\n let active = false;\n let closePromise: Promise<void> | undefined;\n let closed = false;\n /** Which activation owns the target subscription; a retain that only cancels a grace period never changes it. */\n let activation = 0;\n /** The pending deactivation of an observer retention: any retain cancels it without touching the activation. */\n let graceRevision = 0;\n let execution: ResourceExecution | undefined;\n let generation = 0;\n let retainers = 0;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n let selectedKey: Key | undefined;\n let selectedTarget: Target | undefined;\n let selectionRevision = 0;\n let snapshot = idleSnapshot as ResourceSnapshot<Data, Key>;\n let unsubscribeTarget: (() => void) | undefined;\n\n const allocateGeneration = (): number => {\n selectionRevision += 1;\n generation = options.allocateGeneration?.() ?? generation + 1;\n\n return generation;\n };\n const isCurrent = (expectedGeneration: number): boolean => active && !closed && generation === expectedGeneration;\n const isCurrentRead = (revision: number): boolean => active && !closed && selectionRevision === revision;\n const isCurrentExecution = (expected: ResourceExecution): boolean =>\n execution === expected && !expected.abort.signal.aborted && isCurrent(expected.generation);\n const report = (error: unknown): void => reportRuntimeFailure(error, options.reporter);\n const notifyActivity = (): void => observation?.changed?.();\n const notify = (): void => {\n notifyActivity();\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n report(error);\n }\n }\n };\n const publish = (next: ResourceSnapshot<Data, Key>): void => {\n snapshot = Object.freeze(next);\n notify();\n };\n const clearRetry = (): void => {\n if (retryTimer === undefined) return;\n\n clearTimeout(retryTimer);\n retryTimer = undefined;\n };\n const fenceExecution = (): void => {\n clearRetry();\n const previous = execution;\n execution = undefined;\n // Abort listeners may synchronously install a newer execution; only the captured one belongs to this fence.\n previous?.abort.abort();\n };\n const publishError = (error: unknown, attempt: number, expectedGeneration: number, key: Key): void => {\n const previous = readResourceData(snapshot);\n publish({\n attempt,\n data: previous.present ? previous.data : undefined,\n error,\n generation: expectedGeneration,\n key,\n retryable: true,\n stale: previous.present,\n status: 'error',\n });\n report(error);\n };\n const execute = (\n attempt: number,\n expectedGeneration: number,\n key: Key,\n target: Target,\n data: ResourceData<Data> = readResourceData(snapshot),\n ): void => {\n if (!isCurrent(expectedGeneration)) return;\n\n fenceExecution();\n\n if (!isCurrent(expectedGeneration)) return;\n\n const abort = new AbortController();\n const nextExecution = {\n abort,\n attempt,\n generation: expectedGeneration,\n identity: ++nextLoadIdentity,\n started: false,\n };\n execution = nextExecution;\n const operation = Promise.resolve().then(async () => {\n if (!isCurrentExecution(nextExecution)) return;\n\n nextExecution.started = true;\n notifyActivity();\n let loaded: Data;\n\n try {\n loaded = await options.load(target, Object.freeze({ signal: abort.signal, source: options.source }));\n } catch (error) {\n if (!isCurrentExecution(nextExecution)) return;\n\n execution = undefined;\n\n if (attempt < maximumAttempts) {\n retryTimer = setTimeout(() => {\n retryTimer = undefined;\n execute(attempt + 1, expectedGeneration, key, target);\n }, retryDelayMs);\n\n return;\n }\n\n publishError(error, attempt, expectedGeneration, key);\n\n return;\n }\n\n if (!isCurrentExecution(nextExecution)) return;\n\n execution = undefined;\n cache?.set(key, loaded);\n publish({\n attempt,\n data: loaded,\n error: undefined,\n generation: expectedGeneration,\n key,\n stale: false,\n status: 'ready',\n });\n });\n draining.set(operation, nextExecution);\n // Publication can close the owner, so the physical drain must already know the admitted operation.\n publish(pendingSnapshot(attempt, expectedGeneration, key, data));\n notifyActivity();\n void operation.finally(() => {\n draining.delete(operation);\n notifyActivity();\n });\n };\n const openSelection = (target: Target, key: Key, allowCache: boolean, preserveCurrent: boolean): void => {\n const data = preserveCurrent ? readResourceData(snapshot) : ({ present: false } as const);\n const nextGeneration = allocateGeneration();\n fenceExecution();\n\n if (!isCurrent(nextGeneration)) return;\n\n const cached = allowCache ? cache?.get(key) : undefined;\n\n if (cached !== undefined) {\n publish({\n attempt: 1,\n data: cached.data,\n error: undefined,\n generation: nextGeneration,\n key,\n stale: false,\n status: 'ready',\n });\n\n return;\n }\n\n execute(1, nextGeneration, key, target, data);\n };\n const closeSelection = (): void => {\n if (selectedKey === undefined && selectedTarget === undefined && snapshot.status === 'idle') return;\n\n selectedKey = undefined;\n selectedTarget = undefined;\n const nextGeneration = allocateGeneration();\n fenceExecution();\n\n if (!isCurrent(nextGeneration)) return;\n\n publish({ ...idleSnapshot, generation: nextGeneration });\n };\n const selectTarget = (target: Target, revision: number): void => {\n let key: Key;\n\n try {\n key = options.key(target);\n } catch (error) {\n report(error);\n\n return;\n }\n\n if (!isCurrentRead(revision)) return;\n\n if (selectedKey !== undefined && Object.is(selectedKey, key)) {\n selectedTarget = target;\n\n return;\n }\n\n selectedKey = key;\n selectedTarget = target;\n openSelection(target, key, true, false);\n };\n const readTarget = (): void => {\n if (!active || closed) return;\n\n const revision = ++selectionRevision;\n let target: Target | null | undefined;\n\n try {\n target = options.target.getSnapshot();\n } catch (error) {\n report(error);\n\n return;\n }\n\n if (!isCurrentRead(revision)) return;\n\n if (target === null || target === undefined) {\n closeSelection();\n\n return;\n }\n\n selectTarget(target, revision);\n };\n /** A captured subscription belongs to that activation even if its release activates another one. */\n const releaseSubscription = (release: (() => void) | undefined): void => {\n try {\n release?.();\n } catch (error) {\n report(error);\n }\n };\n /** Both stops revoke the old activation before foreign cleanup; only a permanent fence blocks reactivation. */\n const stop = (permanent: boolean): void => {\n active = false;\n activation += 1;\n graceRevision += 1;\n\n if (permanent) {\n closed = true;\n retainers = 0;\n cache?.clear();\n }\n\n const unsubscribe = unsubscribeTarget;\n unsubscribeTarget = undefined;\n selectedKey = undefined;\n selectedTarget = undefined;\n const nextGeneration = allocateGeneration();\n fenceExecution();\n releaseSubscription(unsubscribe);\n\n if (!permanent && (active || closed || generation !== nextGeneration)) return;\n\n publish({ ...idleSnapshot, generation: nextGeneration });\n };\n const activate = (): void => {\n if (active || closed) return;\n\n active = true;\n const current = (activation += 1);\n\n try {\n // D195: `subscribe` runs foreign code that may close or deactivate this controller before it returns. The\n // disposer of an activation nobody waits for any more is released here, exactly once, and never recorded.\n const release = options.target.subscribe(readTarget);\n\n if (closed || !active || activation !== current) {\n releaseSubscription(release);\n\n return;\n }\n\n unsubscribeTarget = release;\n readTarget();\n } catch (error) {\n active = false;\n unsubscribeTarget = undefined;\n report(error);\n }\n };\n const deactivate = (): void => {\n if (!active || options.retention.kind === 'scope' || retainers !== 0) return;\n\n stop(false);\n };\n const requestDeactivation = (): void => {\n const revision = ++graceRevision;\n\n queueMicrotask(() => {\n if (revision === graceRevision) deactivate();\n });\n };\n const refresh = (): void => {\n if (!active || selectedKey === undefined || selectedTarget === undefined) return;\n\n openSelection(selectedTarget, selectedKey, false, true);\n };\n const retry = (): void => {\n if (!active || snapshot.status !== 'error' || selectedKey === undefined || selectedTarget === undefined) {\n return;\n }\n\n execute(snapshot.attempt + 1, generation, selectedKey, selectedTarget);\n };\n const invalidate = (): void => {\n cache?.clear();\n\n if (!active || selectedKey === undefined || selectedTarget === undefined) return;\n\n openSelection(selectedTarget, selectedKey, false, false);\n };\n const retain = (): (() => void) => {\n if (closed) return () => undefined;\n\n retainers += 1;\n // A second lease taken while the first one activates cancels the grace period and keeps that activation alive.\n graceRevision += 1;\n activate();\n notifyActivity();\n let retained = true;\n\n return (): void => {\n if (!retained) return;\n\n retained = false;\n retainers -= 1;\n notifyActivity();\n\n if (retainers === 0 && options.retention.kind === 'observer') requestDeactivation();\n };\n };\n const fence = (): void => {\n if (closed) return;\n\n stop(true);\n };\n const close = (): Promise<void> => {\n if (closePromise !== undefined) return closePromise;\n\n fence();\n closePromise = (async () => {\n while (draining.size !== 0) await Promise.all([...draining.keys()]);\n })();\n\n return closePromise;\n };\n\n const ref: ManagedResourceRef<Data, Key> = Object.freeze({\n close,\n fence,\n getSnapshot: () => snapshot,\n inspect(capacity: number): ResourceInspection {\n const loads: ResourceLoadActivity[] = [];\n let truncated = false;\n for (const load of draining.values()) {\n if (loads.length >= capacity) {\n truncated = true;\n break;\n }\n\n loads.push({\n attempt: load.attempt,\n generation: load.generation,\n id: String(load.identity),\n state: load.abort.signal.aborted ? 'draining' : load.started ? 'running' : 'scheduled',\n });\n }\n\n return {\n generation,\n loads,\n retainers: closed ? 0 : retainers,\n retention: options.retention.kind,\n state: closed ? 'fenced' : snapshot.status,\n truncated,\n };\n },\n invalidate,\n observe(slot: CallObservationSlot): void {\n observation = slot;\n notifyActivity();\n },\n refresh,\n retain,\n retry,\n subscribe(listener: () => void): () => void {\n if (typeof listener !== 'function') throw new TypeError('Resource listener must be a function.');\n\n listeners.add(listener);\n let subscribed = true;\n\n return (): void => {\n if (!subscribed) return;\n\n subscribed = false;\n listeners.delete(listener);\n };\n },\n });\n\n register?.(ref);\n\n if (options.retention.kind === 'scope') activate();\n\n return ref;\n}\n\nexport { createResourceController };\nexport type { ManagedResourceRef, ResourceControllerOptions, ResourceLoadContext };\n"],"names":["nextLoadIdentity","createResourceController","options","register","listeners","draining","observation","cache","createRetainedResourceCache","maximumAttempts","_a","retryDelayMs","_b","active","closePromise","closed","activation","graceRevision","execution","generation","retainers","retryTimer","selectedKey","selectedTarget","selectionRevision","snapshot","idleSnapshot","unsubscribeTarget","allocateGeneration","isCurrent","expectedGeneration","isCurrentRead","revision","isCurrentExecution","expected","report","error","reportRuntimeFailure","notifyActivity","notify","listener","publish","next","clearRetry","fenceExecution","previous","publishError","attempt","key","readResourceData","execute","target","data","abort","nextExecution","operation","loaded","pendingSnapshot","openSelection","allowCache","preserveCurrent","nextGeneration","cached","closeSelection","selectTarget","readTarget","releaseSubscription","release","stop","permanent","unsubscribe","activate","current","deactivate","requestDeactivation","refresh","retry","invalidate","retain","retained","fence","ref","capacity","loads","truncated","load","slot","subscribed"],"mappings":"0OAmDA,IAAIA,GAAmB,EAEvB,SAASC,GACPC,EACAC,EAA8D,SAE9D,MAAMC,EAAY,IAAI,IAChBC,EAAW,IAAI,IACrB,IAAIC,EACJ,MAAMC,EAA8CC,GAA4BN,EAAQ,SAAS,EAC3FO,IAAkBC,EAAAR,EAAQ,QAAR,YAAAQ,EAAe,WAAY,EAC7CC,IAAeC,EAAAV,EAAQ,QAAR,YAAAU,EAAe,UAAW,EAC/C,IAAIC,EAAS,GACTC,EACAC,EAAS,GAETC,EAAa,EAEbC,EAAgB,EAChBC,EACAC,EAAa,EACbC,EAAY,EACZC,EACAC,EACAC,EACAC,EAAoB,EACpBC,EAAWC,EACXC,EAEJ,MAAMC,EAAqB,IAAa,OACtC,OAAAJ,GAAqB,EACrBL,IAAaT,EAAAR,EAAQ,qBAAR,YAAAQ,EAAA,KAAAR,KAAkCiB,EAAa,EAErDA,CACT,EACMU,EAAaC,GAAwCjB,GAAU,CAACE,GAAUI,IAAeW,EACzFC,EAAiBC,GAA8BnB,GAAU,CAACE,GAAUS,IAAsBQ,EAC1FC,EAAsBC,GAC1BhB,IAAcgB,GAAY,CAACA,EAAS,MAAM,OAAO,SAAWL,EAAUK,EAAS,UAAU,EACrFC,EAAUC,GAAyBC,GAAqBD,EAAOlC,EAAQ,QAAQ,EAC/EoC,EAAiB,WAAY,OAAA5B,EAAAJ,GAAA,YAAAA,EAAa,UAAb,YAAAI,EAAA,KAAAJ,IAC7BiC,EAAS,IAAW,CACxBD,EAAc,EACd,UAAWE,IAAY,CAAC,GAAGpC,CAAS,EAClC,GAAI,CACFoC,EAAQ,CACV,OAASJ,EAAO,CACdD,EAAOC,CAAK,CACd,CAEJ,EACMK,EAAWC,GAA2C,CAC1DjB,EAAW,OAAO,OAAOiB,CAAI,EAC7BH,EAAM,CACR,EACMI,EAAa,IAAW,CACxBtB,IAAe,SAEnB,aAAaA,CAAU,EACvBA,EAAa,OACf,EACMuB,EAAiB,IAAW,CAChCD,EAAU,EACV,MAAME,EAAW3B,EACjBA,EAAY,OAEZ2B,GAAA,MAAAA,EAAU,MAAM,OAClB,EACMC,EAAe,CAACV,EAAgBW,EAAiBjB,EAA4BkB,IAAkB,CACnG,MAAMH,EAAWI,EAAiBxB,CAAQ,EAC1CgB,EAAQ,CACN,QAAAM,EACA,KAAMF,EAAS,QAAUA,EAAS,KAAO,OACzC,MAAAT,EACA,WAAYN,EACZ,IAAAkB,EACA,UAAW,GACX,MAAOH,EAAS,QAChB,OAAQ,OACT,CAAA,EACDV,EAAOC,CAAK,CACd,EACMc,EAAU,CACdH,EACAjB,EACAkB,EACAG,EACAC,EAA2BH,EAAiBxB,CAAQ,IAC5C,CAKR,GAJI,CAACI,EAAUC,CAAkB,IAEjCc,EAAc,EAEV,CAACf,EAAUC,CAAkB,GAAG,OAEpC,MAAMuB,EAAQ,IAAI,gBACZC,EAAgB,CACpB,MAAAD,EACA,QAAAN,EACA,WAAYjB,EACZ,SAAU,EAAE9B,GACZ,QAAS,IAEXkB,EAAYoC,EACZ,MAAMC,EAAY,QAAQ,QAAO,EAAG,KAAK,SAAW,CAClD,GAAI,CAACtB,EAAmBqB,CAAa,EAAG,OAExCA,EAAc,QAAU,GACxBhB,EAAc,EACd,IAAIkB,EAEJ,GAAI,CACFA,EAAS,MAAMtD,EAAQ,KAAKiD,EAAQ,OAAO,OAAO,CAAE,OAAQE,EAAM,OAAQ,OAAQnD,EAAQ,MAAM,CAAE,CAAC,CACrG,OAASkC,GAAO,CACd,GAAI,CAACH,EAAmBqB,CAAa,EAAG,OAIxC,GAFApC,EAAY,OAER6B,EAAUtC,EAAiB,CAC7BY,EAAa,WAAW,IAAK,CAC3BA,EAAa,OACb6B,EAAQH,EAAU,EAAGjB,EAAoBkB,EAAKG,CAAM,CACtD,EAAGxC,CAAY,EAEf,MACF,CAEAmC,EAAaV,GAAOW,EAASjB,EAAoBkB,CAAG,EAEpD,MACF,CAEKf,EAAmBqB,CAAa,IAErCpC,EAAY,OACZX,GAAA,MAAAA,EAAO,IAAIyC,EAAKQ,GAChBf,EAAQ,CACN,QAAAM,EACA,KAAMS,EACN,MAAO,OACP,WAAY1B,EACZ,IAAAkB,EACA,MAAO,GACP,OAAQ,OACT,CAAA,EACH,CAAC,EACD3C,EAAS,IAAIkD,EAAWD,CAAa,EAErCb,EAAQgB,GAAgBV,EAASjB,EAAoBkB,EAAKI,CAAI,CAAC,EAC/Dd,EAAc,EACTiB,EAAU,QAAQ,IAAK,CAC1BlD,EAAS,OAAOkD,CAAS,EACzBjB,EAAc,CAChB,CAAC,CACH,EACMoB,EAAgB,CAACP,EAAgBH,EAAUW,EAAqBC,IAAkC,CACtG,MAAMR,EAAOQ,EAAkBX,EAAiBxB,CAAQ,EAAK,CAAE,QAAS,EAAK,EACvEoC,EAAiBjC,EAAkB,EAGzC,GAFAgB,EAAc,EAEV,CAACf,EAAUgC,CAAc,EAAG,OAEhC,MAAMC,EAASH,EAAapD,GAAA,YAAAA,EAAO,IAAIyC,GAAO,OAE9C,GAAIc,IAAW,OAAW,CACxBrB,EAAQ,CACN,QAAS,EACT,KAAMqB,EAAO,KACb,MAAO,OACP,WAAYD,EACZ,IAAAb,EACA,MAAO,GACP,OAAQ,OACT,CAAA,EAED,MACF,CAEAE,EAAQ,EAAGW,EAAgBb,EAAKG,EAAQC,CAAI,CAC9C,EACMW,GAAiB,IAAW,CAChC,GAAIzC,IAAgB,QAAaC,IAAmB,QAAaE,EAAS,SAAW,OAAQ,OAE7FH,EAAc,OACdC,EAAiB,OACjB,MAAMsC,EAAiBjC,EAAkB,EACzCgB,EAAc,EAETf,EAAUgC,CAAc,GAE7BpB,EAAQ,CAAE,GAAGf,EAAc,WAAYmC,CAAc,CAAE,CACzD,EACMG,GAAe,CAACb,EAAgBnB,IAA0B,CAC9D,IAAIgB,EAEJ,GAAI,CACFA,EAAM9C,EAAQ,IAAIiD,CAAM,CAC1B,OAASf,EAAO,CACdD,EAAOC,CAAK,EAEZ,MACF,CAEA,GAAKL,EAAcC,CAAQ,EAE3B,IAAIV,IAAgB,QAAa,OAAO,GAAGA,EAAa0B,CAAG,EAAG,CAC5DzB,EAAiB4B,EAEjB,MACF,CAEA7B,EAAc0B,EACdzB,EAAiB4B,EACjBO,EAAcP,EAAQH,EAAK,GAAM,EAAK,EACxC,EACMiB,EAAa,IAAW,CAC5B,GAAI,CAACpD,GAAUE,EAAQ,OAEvB,MAAMiB,EAAW,EAAER,EACnB,IAAI2B,EAEJ,GAAI,CACFA,EAASjD,EAAQ,OAAO,YAAW,CACrC,OAASkC,EAAO,CACdD,EAAOC,CAAK,EAEZ,MACF,CAEA,GAAKL,EAAcC,CAAQ,EAE3B,IAAImB,GAAW,KAA8B,CAC3CY,GAAc,EAEd,MACF,CAEAC,GAAab,EAAQnB,CAAQ,EAC/B,EAEMkC,EAAuBC,GAA2C,CACtE,GAAI,CACFA,GAAA,MAAAA,GACF,OAAS/B,EAAO,CACdD,EAAOC,CAAK,CACd,CACF,EAEMgC,EAAQC,GAA4B,CACxCxD,EAAS,GACTG,GAAc,EACdC,GAAiB,EAEboD,IACFtD,EAAS,GACTK,EAAY,EACZb,GAAA,MAAAA,EAAO,SAGT,MAAM+D,EAAc3C,EACpBA,EAAoB,OACpBL,EAAc,OACdC,EAAiB,OACjB,MAAMsC,EAAiBjC,EAAkB,EACzCgB,EAAc,EACdsB,EAAoBI,CAAW,EAE3B,GAACD,IAAcxD,GAAUE,GAAUI,IAAe0C,KAEtDpB,EAAQ,CAAE,GAAGf,EAAc,WAAYmC,CAAc,CAAE,CACzD,EACMU,EAAW,IAAW,CAC1B,GAAI1D,GAAUE,EAAQ,OAEtBF,EAAS,GACT,MAAM2D,EAAWxD,GAAc,EAE/B,GAAI,CAGF,MAAMmD,EAAUjE,EAAQ,OAAO,UAAU+D,CAAU,EAEnD,GAAIlD,GAAU,CAACF,GAAUG,IAAewD,EAAS,CAC/CN,EAAoBC,CAAO,EAE3B,MACF,CAEAxC,EAAoBwC,EACpBF,EAAU,CACZ,OAAS7B,EAAO,CACdvB,EAAS,GACTc,EAAoB,OACpBQ,EAAOC,CAAK,CACd,CACF,EACMqC,GAAa,IAAW,CACxB,CAAC5D,GAAUX,EAAQ,UAAU,OAAS,SAAWkB,IAAc,GAEnEgD,EAAK,EAAK,CACZ,EACMM,GAAsB,IAAW,CACrC,MAAM1C,EAAW,EAAEf,EAEnB,eAAe,IAAK,CACde,IAAaf,GAAewD,GAAU,CAC5C,CAAC,CACH,EACME,GAAU,IAAW,CACrB,CAAC9D,GAAUS,IAAgB,QAAaC,IAAmB,QAE/DmC,EAAcnC,EAAgBD,EAAa,GAAO,EAAI,CACxD,EACMsD,GAAQ,IAAW,CACnB,CAAC/D,GAAUY,EAAS,SAAW,SAAWH,IAAgB,QAAaC,IAAmB,QAI9F2B,EAAQzB,EAAS,QAAU,EAAGN,EAAYG,EAAaC,CAAc,CACvE,EACMsD,GAAa,IAAW,CAC5BtE,GAAA,MAAAA,EAAO,QAEH,GAACM,GAAUS,IAAgB,QAAaC,IAAmB,SAE/DmC,EAAcnC,EAAgBD,EAAa,GAAO,EAAK,CACzD,EACMwD,GAAS,IAAmB,CAChC,GAAI/D,EAAQ,MAAO,OAEnBK,GAAa,EAEbH,GAAiB,EACjBsD,EAAQ,EACRjC,EAAc,EACd,IAAIyC,EAAW,GAEf,MAAO,IAAW,CACXA,IAELA,EAAW,GACX3D,GAAa,EACbkB,EAAc,EAEVlB,IAAc,GAAKlB,EAAQ,UAAU,OAAS,YAAYwE,GAAmB,EACnF,CACF,EACMM,EAAQ,IAAW,CACnBjE,GAEJqD,EAAK,EAAI,CACX,EAYMa,EAAqC,OAAO,OAAO,CACvD,MAZY,KACRnE,IAAiB,SAErBkE,EAAK,EACLlE,GAAgB,SAAW,CACzB,KAAOT,EAAS,OAAS,GAAG,MAAM,QAAQ,IAAI,CAAC,GAAGA,EAAS,KAAI,CAAE,CAAC,CACpE,GAAC,GAEMS,GAKP,MAAAkE,EACA,YAAa,IAAMvD,EACnB,QAAQyD,EAAgB,CACtB,MAAMC,EAAgC,CAAA,EACtC,IAAIC,EAAY,GAChB,UAAWC,KAAQhF,EAAS,SAAU,CACpC,GAAI8E,EAAM,QAAUD,EAAU,CAC5BE,EAAY,GACZ,KACF,CAEAD,EAAM,KAAK,CACT,QAASE,EAAK,QACd,WAAYA,EAAK,WACjB,GAAI,OAAOA,EAAK,QAAQ,EACxB,MAAOA,EAAK,MAAM,OAAO,QAAU,WAAaA,EAAK,QAAU,UAAY,WAC5E,CAAA,CACH,CAEA,MAAO,CACL,WAAAlE,EACA,MAAAgE,EACA,UAAWpE,EAAS,EAAIK,EACxB,UAAWlB,EAAQ,UAAU,KAC7B,MAAOa,EAAS,SAAWU,EAAS,OACpC,UAAA2D,EAEJ,EACA,WAAAP,GACA,QAAQS,EAAyB,CAC/BhF,EAAcgF,EACdhD,EAAc,CAChB,EACA,QAAAqC,GACA,OAAAG,GACA,MAAAF,GACA,UAAUpC,EAAoB,CAC5B,GAAI,OAAOA,GAAa,WAAY,MAAM,IAAI,UAAU,uCAAuC,EAE/FpC,EAAU,IAAIoC,CAAQ,EACtB,IAAI+C,EAAa,GAEjB,MAAO,IAAW,CACXA,IAELA,EAAa,GACbnF,EAAU,OAAOoC,CAAQ,EAC3B,CACF,CACD,CAAA,EAED,OAAArC,GAAA,MAAAA,EAAW8E,GAEP/E,EAAQ,UAAU,OAAS,SAASqE,EAAQ,EAEzCU,CACT"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ExactInput } from '@opetope/core/internal';
|
|
2
|
+
import type { LatestBackpressure, ResourceRetention, ResourceRetry, ScopedRetention, StreamBackpressure } from './resource-types.js';
|
|
3
|
+
declare function scoped<const Options extends {
|
|
4
|
+
readonly capacity: number;
|
|
5
|
+
}>(options: ExactInput<Options, {
|
|
6
|
+
readonly capacity: number;
|
|
7
|
+
}>): ScopedRetention;
|
|
8
|
+
declare function latest(): LatestBackpressure;
|
|
9
|
+
declare function snapshotResourceRetention(value: unknown): ResourceRetention;
|
|
10
|
+
declare function snapshotResourceRetry(value: unknown): ResourceRetry | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* One policy, because `spec.md` §3 publishes one: `latest` keeps the newest value and drops what nobody consumed
|
|
13
|
+
* (D160). A stream requires the option and an event admits it, so the label names the place the author wrote it.
|
|
14
|
+
*/
|
|
15
|
+
declare function snapshotStreamBackpressure(value: unknown, label?: string): StreamBackpressure;
|
|
16
|
+
export { latest, scoped, snapshotResourceRetention, snapshotResourceRetry, snapshotStreamBackpressure };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{hasOwn as a}from"@opetope/core/internal";import{assertPlainRecord as i,dataEntries as p}from"./feature-record.js";const s=Object.freeze({grace:"microtask",inFlight:"abort",kind:"observer"}),c=Object.freeze({kind:"latest"});function n(e,t,r){if(p(e,r).length!==t.length||t.some(f=>!a(e,f)))throw new TypeError(`${r} requires exact ${t.join(", ")} fields.`)}function o(e,t){if(!Number.isSafeInteger(e)||e<1)throw new TypeError(`${t} must be a positive safe integer.`);return e}function u(e,t){if(typeof e!="number"||!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be finite and >= 0.`);return e}function d(e){return i(e,"scoped retention"),n(e,["capacity"],"scoped retention"),Object.freeze({capacity:o(e.capacity,"Scoped retention capacity"),evict:"lru",kind:"scope"})}function y(){return c}function R(e){if(e===void 0)return s;i(e,"Resource retention");const t=Reflect.get(e,"kind");if(t==="observer")return n(e,["kind"],"Resource observer retention"),s;if(t==="scope"){n(e,["capacity","evict","kind"],"Resource scoped retention");const r=o(Reflect.get(e,"capacity"),"Resource retention capacity");if(Reflect.get(e,"evict")!=="lru")throw new TypeError("Resource scoped retention requires lru eviction.");return Object.freeze({capacity:r,evict:"lru",kind:"scope"})}throw new TypeError(`Unknown resource retention ${String(t)}.`)}function k(e){if(e!==void 0)return i(e,"Resource retry"),n(e,["attempts","delayMs"],"Resource retry"),Object.freeze({attempts:o(Reflect.get(e,"attempts"),"Resource retry attempts"),delayMs:u(Reflect.get(e,"delayMs"),"Resource retry delayMs")})}function m(e,t="Stream"){i(e,`${t} backpressure`);const r=Reflect.get(e,"kind");if(r!=="latest")throw new TypeError(`Unknown ${t.toLowerCase()} backpressure ${String(r)}.`);return n(e,["kind"],`${t} latest backpressure`),c}export{y as latest,d as scoped,R as snapshotResourceRetention,k as snapshotResourceRetry,m as snapshotStreamBackpressure};
|
|
2
|
+
//# sourceMappingURL=resource-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-policy.js","sources":["../src/resource-policy.ts"],"sourcesContent":["import type { ExactInput } from '@opetope/core/internal';\nimport { hasOwn } from '@opetope/core/internal';\n\nimport { assertPlainRecord, dataEntries } from './feature-record';\nimport type {\n LatestBackpressure,\n ObserverRetention,\n ResourceRetention,\n ResourceRetry,\n ScopedRetention,\n StreamBackpressure,\n} from './resource-types';\n\nconst defaultObserverRetention: ObserverRetention = Object.freeze({\n grace: 'microtask',\n inFlight: 'abort',\n kind: 'observer',\n});\nconst latestBackpressure: LatestBackpressure = Object.freeze({ kind: 'latest' });\n\nfunction assertExactKeys(value: Readonly<Record<string, unknown>>, expected: readonly string[], label: string): void {\n const entries = dataEntries(value, label);\n\n if (entries.length !== expected.length || expected.some(key => !hasOwn(value, key))) {\n throw new TypeError(`${label} requires exact ${expected.join(', ')} fields.`);\n }\n}\n\nfunction requirePositiveSafeInteger(value: unknown, label: string): number {\n if (!Number.isSafeInteger(value) || (value as number) < 1) {\n throw new TypeError(`${label} must be a positive safe integer.`);\n }\n\n return value as number;\n}\n\nfunction requireNonNegativeFinite(value: unknown, label: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {\n throw new TypeError(`${label} must be finite and >= 0.`);\n }\n\n return value;\n}\n\nfunction scoped<const Options extends { readonly capacity: number }>(\n options: ExactInput<Options, { readonly capacity: number }>,\n): ScopedRetention {\n assertPlainRecord(options, 'scoped retention');\n assertExactKeys(options, ['capacity'], 'scoped retention');\n\n return Object.freeze({\n capacity: requirePositiveSafeInteger(options.capacity, 'Scoped retention capacity'),\n evict: 'lru',\n kind: 'scope',\n });\n}\n\nfunction latest(): LatestBackpressure {\n return latestBackpressure;\n}\n\nfunction snapshotResourceRetention(value: unknown): ResourceRetention {\n if (value === undefined) return defaultObserverRetention;\n\n assertPlainRecord(value, 'Resource retention');\n const kind: unknown = Reflect.get(value, 'kind');\n\n if (kind === 'observer') {\n // D160: both fields of the old record admitted one value each, so the observer retention is its kind alone.\n assertExactKeys(value, ['kind'], 'Resource observer retention');\n\n return defaultObserverRetention;\n }\n\n if (kind === 'scope') {\n assertExactKeys(value, ['capacity', 'evict', 'kind'], 'Resource scoped retention');\n const capacity = requirePositiveSafeInteger(Reflect.get(value, 'capacity'), 'Resource retention capacity');\n\n if (Reflect.get(value, 'evict') !== 'lru') throw new TypeError('Resource scoped retention requires lru eviction.');\n\n return Object.freeze({ capacity, evict: 'lru', kind: 'scope' });\n }\n\n throw new TypeError(`Unknown resource retention ${String(kind)}.`);\n}\n\nfunction snapshotResourceRetry(value: unknown): ResourceRetry | undefined {\n if (value === undefined) return undefined;\n\n assertPlainRecord(value, 'Resource retry');\n assertExactKeys(value, ['attempts', 'delayMs'], 'Resource retry');\n\n return Object.freeze({\n attempts: requirePositiveSafeInteger(Reflect.get(value, 'attempts'), 'Resource retry attempts'),\n delayMs: requireNonNegativeFinite(Reflect.get(value, 'delayMs'), 'Resource retry delayMs'),\n });\n}\n\n/**\n * One policy, because `spec.md` §3 publishes one: `latest` keeps the newest value and drops what nobody consumed\n * (D160). A stream requires the option and an event admits it, so the label names the place the author wrote it.\n */\nfunction snapshotStreamBackpressure(value: unknown, label = 'Stream'): StreamBackpressure {\n assertPlainRecord(value, `${label} backpressure`);\n const kind: unknown = Reflect.get(value, 'kind');\n\n if (kind !== 'latest') throw new TypeError(`Unknown ${label.toLowerCase()} backpressure ${String(kind)}.`);\n\n assertExactKeys(value, ['kind'], `${label} latest backpressure`);\n\n return latestBackpressure;\n}\n\nexport { latest, scoped, snapshotResourceRetention, snapshotResourceRetry, snapshotStreamBackpressure };\n"],"names":["defaultObserverRetention","latestBackpressure","assertExactKeys","value","expected","label","dataEntries","key","hasOwn","requirePositiveSafeInteger","requireNonNegativeFinite","scoped","options","assertPlainRecord","latest","snapshotResourceRetention","kind","capacity","snapshotResourceRetry","snapshotStreamBackpressure"],"mappings":"yHAaA,MAAMA,EAA8C,OAAO,OAAO,CAChE,MAAO,YACP,SAAU,QACV,KAAM,UACP,CAAA,EACKC,EAAyC,OAAO,OAAO,CAAE,KAAM,QAAQ,CAAE,EAE/E,SAASC,EAAgBC,EAA0CC,EAA6BC,EAAa,CAG3G,GAFgBC,EAAYH,EAAOE,CAAK,EAE5B,SAAWD,EAAS,QAAUA,EAAS,KAAKG,GAAO,CAACC,EAAOL,EAAOI,CAAG,CAAC,EAChF,MAAM,IAAI,UAAU,GAAGF,CAAK,mBAAmBD,EAAS,KAAK,IAAI,CAAC,UAAU,CAEhF,CAEA,SAASK,EAA2BN,EAAgBE,EAAa,CAC/D,GAAI,CAAC,OAAO,cAAcF,CAAK,GAAMA,EAAmB,EACtD,MAAM,IAAI,UAAU,GAAGE,CAAK,mCAAmC,EAGjE,OAAOF,CACT,CAEA,SAASO,EAAyBP,EAAgBE,EAAa,CAC7D,GAAI,OAAOF,GAAU,UAAY,CAAC,OAAO,SAASA,CAAK,GAAKA,EAAQ,EAClE,MAAM,IAAI,UAAU,GAAGE,CAAK,2BAA2B,EAGzD,OAAOF,CACT,CAEA,SAASQ,EACPC,EAA2D,CAE3D,OAAAC,EAAkBD,EAAS,kBAAkB,EAC7CV,EAAgBU,EAAS,CAAC,UAAU,EAAG,kBAAkB,EAElD,OAAO,OAAO,CACnB,SAAUH,EAA2BG,EAAQ,SAAU,2BAA2B,EAClF,MAAO,MACP,KAAM,OACP,CAAA,CACH,CAEA,SAASE,GAAM,CACb,OAAOb,CACT,CAEA,SAASc,EAA0BZ,EAAc,CAC/C,GAAIA,IAAU,OAAW,OAAOH,EAEhCa,EAAkBV,EAAO,oBAAoB,EAC7C,MAAMa,EAAgB,QAAQ,IAAIb,EAAO,MAAM,EAE/C,GAAIa,IAAS,WAEX,OAAAd,EAAgBC,EAAO,CAAC,MAAM,EAAG,6BAA6B,EAEvDH,EAGT,GAAIgB,IAAS,QAAS,CACpBd,EAAgBC,EAAO,CAAC,WAAY,QAAS,MAAM,EAAG,2BAA2B,EACjF,MAAMc,EAAWR,EAA2B,QAAQ,IAAIN,EAAO,UAAU,EAAG,6BAA6B,EAEzG,GAAI,QAAQ,IAAIA,EAAO,OAAO,IAAM,MAAO,MAAM,IAAI,UAAU,kDAAkD,EAEjH,OAAO,OAAO,OAAO,CAAE,SAAAc,EAAU,MAAO,MAAO,KAAM,QAAS,CAChE,CAEA,MAAM,IAAI,UAAU,8BAA8B,OAAOD,CAAI,CAAC,GAAG,CACnE,CAEA,SAASE,EAAsBf,EAAc,CAC3C,GAAIA,IAAU,OAEd,OAAAU,EAAkBV,EAAO,gBAAgB,EACzCD,EAAgBC,EAAO,CAAC,WAAY,SAAS,EAAG,gBAAgB,EAEzD,OAAO,OAAO,CACnB,SAAUM,EAA2B,QAAQ,IAAIN,EAAO,UAAU,EAAG,yBAAyB,EAC9F,QAASO,EAAyB,QAAQ,IAAIP,EAAO,SAAS,EAAG,wBAAwB,CAC1F,CAAA,CACH,CAMA,SAASgB,EAA2BhB,EAAgBE,EAAQ,SAAQ,CAClEQ,EAAkBV,EAAO,GAAGE,CAAK,eAAe,EAChD,MAAMW,EAAgB,QAAQ,IAAIb,EAAO,MAAM,EAE/C,GAAIa,IAAS,SAAU,MAAM,IAAI,UAAU,WAAWX,EAAM,aAAa,iBAAiB,OAAOW,CAAI,CAAC,GAAG,EAEzG,OAAAd,EAAgBC,EAAO,CAAC,MAAM,EAAG,GAAGE,CAAK,sBAAsB,EAExDJ,CACT"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ResourceRequestKey, ResourceSnapshot } from './resource-types.js';
|
|
2
|
+
type ResourceData<Data> = {
|
|
3
|
+
readonly data: Data;
|
|
4
|
+
readonly present: true;
|
|
5
|
+
} | {
|
|
6
|
+
readonly present: false;
|
|
7
|
+
};
|
|
8
|
+
declare function readResourceData<Data>(snapshot: ResourceSnapshot<Data>): ResourceData<Data>;
|
|
9
|
+
declare function pendingSnapshot<Data, Key extends ResourceRequestKey>(attempt: number, generation: number, key: Key, data: ResourceData<Data>): ResourceSnapshot<Data, Key>;
|
|
10
|
+
declare const idleSnapshot: ResourceSnapshot<never, never>;
|
|
11
|
+
export { idleSnapshot, pendingSnapshot, readResourceData };
|
|
12
|
+
export type { ResourceData };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function a(e){return e.status==="ready"||e.stale?{data:e.data,present:!0}:{present:!1}}function d(e,t,n,r){return r.present?{attempt:e,data:r.data,error:void 0,generation:t,key:n,stale:!0,status:"refreshing"}:{attempt:e,data:void 0,error:void 0,generation:t,key:n,stale:!1,status:"opening"}}const s=Object.freeze({attempt:0,data:void 0,error:void 0,generation:0,key:null,stale:!1,status:"idle"});export{s as idleSnapshot,d as pendingSnapshot,a as readResourceData};
|
|
2
|
+
//# sourceMappingURL=resource-snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-snapshot.js","sources":["../src/resource-snapshot.ts"],"sourcesContent":["import type { ResourceRequestKey, ResourceSnapshot } from './resource-types';\n\ntype ResourceData<Data> = { readonly data: Data; readonly present: true } | { readonly present: false };\n\nfunction readResourceData<Data>(snapshot: ResourceSnapshot<Data>): ResourceData<Data> {\n // Ready owns fresh data; every other snapshot with data marks it stale, including a failed refresh.\n if (snapshot.status === 'ready' || snapshot.stale) return { data: snapshot.data as Data, present: true };\n\n return { present: false };\n}\n\nfunction pendingSnapshot<Data, Key extends ResourceRequestKey>(\n attempt: number,\n generation: number,\n key: Key,\n data: ResourceData<Data>,\n): ResourceSnapshot<Data, Key> {\n return data.present\n ? { attempt, data: data.data, error: undefined, generation, key, stale: true, status: 'refreshing' }\n : { attempt, data: undefined, error: undefined, generation, key, stale: false, status: 'opening' };\n}\n\nconst idleSnapshot: ResourceSnapshot<never, never> = Object.freeze({\n attempt: 0,\n data: undefined,\n error: undefined,\n generation: 0,\n key: null,\n stale: false,\n status: 'idle',\n});\n\nexport { idleSnapshot, pendingSnapshot, readResourceData };\nexport type { ResourceData };\n"],"names":["readResourceData","snapshot","pendingSnapshot","attempt","generation","key","data","idleSnapshot"],"mappings":"AAIA,SAASA,EAAuBC,EAAgC,CAE9D,OAAIA,EAAS,SAAW,SAAWA,EAAS,MAAc,CAAE,KAAMA,EAAS,KAAc,QAAS,EAAI,EAE/F,CAAE,QAAS,EAAK,CACzB,CAEA,SAASC,EACPC,EACAC,EACAC,EACAC,EAAwB,CAExB,OAAOA,EAAK,QACR,CAAE,QAAAH,EAAS,KAAMG,EAAK,KAAM,MAAO,OAAW,WAAAF,EAAY,IAAAC,EAAK,MAAO,GAAM,OAAQ,YAAY,EAChG,CAAE,QAAAF,EAAS,KAAM,OAAW,MAAO,OAAW,WAAAC,EAAY,IAAAC,EAAK,MAAO,GAAO,OAAQ,SAAS,CACpG,CAEA,MAAME,EAA+C,OAAO,OAAO,CACjE,QAAS,EACT,KAAM,OACN,MAAO,OACP,WAAY,EACZ,IAAK,KACL,MAAO,GACP,OAAQ,MACT,CAAA"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Data contracts live in `@opetope/core` (D73); this module keeps the runtime-facing names stable. */
|
|
2
|
+
export type { LatestBackpressure, Resource, ResourceSnapshot, ScopedRetention } from '@opetope/core';
|
|
3
|
+
export type { ObserverRetention, ResourceRequestKey, ResourceRetention, ResourceRetry, StreamBackpressure, } from '@opetope/core/internal';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-error-reporting.js","sources":["../src/runtime-error-reporting.ts"],"sourcesContent":["import { reportDetachedError } from '@opetope/core/internal';\n\ntype RuntimeErrorReporter = (error: unknown) => PromiseLike<void> | void;\n\nfunction reportRuntimeFailure(error: unknown, reporter: RuntimeErrorReporter | undefined): void {\n if (reporter === undefined) {\n reportDetachedError(error);\n\n return;\n }\n\n try {\n const result = reporter(error);\n\n if (result !== undefined) void Promise.resolve(result).catch(() => reportDetachedError(error));\n } catch {\n reportDetachedError(error);\n }\n}\n\nexport { reportRuntimeFailure };\nexport type { RuntimeErrorReporter };\n"],"names":["reportRuntimeFailure","error","reporter","reportDetachedError","result"],"mappings":"6DAIA,SAASA,EAAqBC,EAAgBC,EAA0C,CACtF,GAAIA,IAAa,OAAW,CAC1BC,EAAoBF,CAAK,EAEzB,MACF,CAEA,GAAI,CACF,MAAMG,EAASF,EAASD,CAAK,EAEzBG,IAAW,QAAgB,QAAQ,QAAQA,CAAM,EAAE,MAAM,IAAMD,EAAoBF,CAAK,CAAC,CAC/F,MAAQ,CACNE,EAAoBF,CAAK,CAC3B,CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Awaitable } from '@opetope/core/internal';
|
|
2
|
+
type StreamBackpressureOptions<Data> = {
|
|
3
|
+
readonly consume: (data: Data) => Awaitable<void>;
|
|
4
|
+
readonly onConsumeError: (error: unknown) => void;
|
|
5
|
+
};
|
|
6
|
+
interface StreamAdmission<Data> {
|
|
7
|
+
readonly close: () => Promise<void>;
|
|
8
|
+
readonly emit: (data: Data) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* One admission for the one published policy: `latest` keeps the newest value and drops what nobody consumed yet.
|
|
12
|
+
* The `drop`, `sample` and `queue` branches, their timer and the queue overflow error were unreachable —
|
|
13
|
+
* `spec.md` §3 never
|
|
14
|
+
* published a way to name them — so the whole state machine is a single slot now (D160).
|
|
15
|
+
*/
|
|
16
|
+
declare function createStreamAdmission<Data>(options: StreamBackpressureOptions<Data>): StreamAdmission<Data>;
|
|
17
|
+
export { createStreamAdmission };
|
|
18
|
+
export type { StreamAdmission };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function m(s){let u=!1,r=!1,d=!1,e,o=Promise.resolve(),n;const i=()=>{u=!1,n==null||n(),n=void 0,!(r||e===void 0)&&l()},a=()=>{if(d=!1,r||u||e===void 0)return;const f=e.data;e=void 0,u=!0,o=new Promise(t=>{n=t});let c;try{c=s.consume(f)}catch(t){s.onConsumeError(t),i();return}Promise.resolve(c).then(i,t=>{s.onConsumeError(t),i()})};function l(){r||u||d||e===void 0||(d=!0,queueMicrotask(a))}return Object.freeze({close(){return r=!0,e=void 0,o},emit(f){r||(e={data:f},l())}})}export{m as createStreamAdmission};
|
|
2
|
+
//# sourceMappingURL=stream-backpressure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-backpressure.js","sources":["../src/stream-backpressure.ts"],"sourcesContent":["import type { Awaitable } from '@opetope/core/internal';\n\ntype StreamBackpressureOptions<Data> = {\n readonly consume: (data: Data) => Awaitable<void>;\n readonly onConsumeError: (error: unknown) => void;\n};\n\ninterface StreamAdmission<Data> {\n readonly close: () => Promise<void>;\n readonly emit: (data: Data) => void;\n}\n\n/**\n * One admission for the one published policy: `latest` keeps the newest value and drops what nobody consumed yet.\n * The `drop`, `sample` and `queue` branches, their timer and the queue overflow error were unreachable —\n * `spec.md` §3 never\n * published a way to name them — so the whole state machine is a single slot now (D160).\n */\nfunction createStreamAdmission<Data>(options: StreamBackpressureOptions<Data>): StreamAdmission<Data> {\n let busy = false;\n let closed = false;\n let scheduled = false;\n let pending: { readonly data: Data } | undefined;\n let drain = Promise.resolve();\n let resolveDrain: (() => void) | undefined;\n\n const finish = (): void => {\n busy = false;\n resolveDrain?.();\n resolveDrain = undefined;\n\n if (closed || pending === undefined) return;\n\n // eslint-disable-next-line no-use-before-define -- consumption settles after admission construction completes.\n schedulePump();\n };\n const pump = (): void => {\n scheduled = false;\n\n if (closed || busy || pending === undefined) return;\n\n const next = pending.data;\n pending = undefined;\n busy = true;\n drain = new Promise<void>(resolve => {\n resolveDrain = resolve;\n });\n let result: Awaitable<void>;\n\n try {\n result = options.consume(next);\n } catch (error) {\n options.onConsumeError(error);\n finish();\n\n return;\n }\n\n void Promise.resolve(result).then(finish, (error: unknown) => {\n options.onConsumeError(error);\n finish();\n });\n };\n function schedulePump(): void {\n if (closed || busy || scheduled || pending === undefined) return;\n\n scheduled = true;\n queueMicrotask(pump);\n }\n\n return Object.freeze({\n close(): Promise<void> {\n closed = true;\n pending = undefined;\n\n return drain;\n },\n emit(data: Data): void {\n if (closed) return;\n\n pending = { data };\n schedulePump();\n },\n });\n}\n\nexport { createStreamAdmission };\nexport type { StreamAdmission };\n"],"names":["createStreamAdmission","options","busy","closed","scheduled","pending","drain","resolveDrain","finish","schedulePump","pump","next","resolve","result","error","data"],"mappings":"AAkBA,SAASA,EAA4BC,EAAwC,CAC3E,IAAIC,EAAO,GACPC,EAAS,GACTC,EAAY,GACZC,EACAC,EAAQ,QAAQ,QAAO,EACvBC,EAEJ,MAAMC,EAAS,IAAW,CACxBN,EAAO,GACPK,GAAA,MAAAA,IACAA,EAAe,OAEX,EAAAJ,GAAUE,IAAY,SAG1BI,EAAY,CACd,EACMC,EAAO,IAAW,CAGtB,GAFAN,EAAY,GAERD,GAAUD,GAAQG,IAAY,OAAW,OAE7C,MAAMM,EAAON,EAAQ,KACrBA,EAAU,OACVH,EAAO,GACPI,EAAQ,IAAI,QAAcM,GAAU,CAClCL,EAAeK,CACjB,CAAC,EACD,IAAIC,EAEJ,GAAI,CACFA,EAASZ,EAAQ,QAAQU,CAAI,CAC/B,OAASG,EAAO,CACdb,EAAQ,eAAea,CAAK,EAC5BN,EAAM,EAEN,MACF,CAEK,QAAQ,QAAQK,CAAM,EAAE,KAAKL,EAASM,GAAkB,CAC3Db,EAAQ,eAAea,CAAK,EAC5BN,EAAM,CACR,CAAC,CACH,EACA,SAASC,GAAY,CACfN,GAAUD,GAAQE,GAAaC,IAAY,SAE/CD,EAAY,GACZ,eAAeM,CAAI,EACrB,CAEA,OAAO,OAAO,OAAO,CACnB,OAAK,CACH,OAAAP,EAAS,GACTE,EAAU,OAEHC,CACT,EACA,KAAKS,EAAU,CACTZ,IAEJE,EAAU,CAAE,KAAAU,CAAI,EAChBN,EAAY,EACd,CACD,CAAA,CACH"}
|