@hops-ops/distributed 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +454 -0
- package/dist/auth-headers.d.ts +8 -0
- package/dist/auth-headers.js +35 -0
- package/dist/diagnostics.d.ts +2 -0
- package/dist/diagnostics.js +1 -0
- package/dist/document.d.ts +8 -0
- package/dist/document.js +6 -0
- package/dist/identity.d.ts +23 -0
- package/dist/identity.js +73 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/internal/cache-engine/create.d.ts +5 -0
- package/dist/internal/cache-engine/create.js +7 -0
- package/dist/internal/cache-engine/engine.d.ts +32 -0
- package/dist/internal/cache-engine/engine.js +1287 -0
- package/dist/internal/cache-engine/errors.d.ts +5 -0
- package/dist/internal/cache-engine/errors.js +10 -0
- package/dist/internal/cache-engine/helpers.d.ts +55 -0
- package/dist/internal/cache-engine/helpers.js +545 -0
- package/dist/internal/cache-engine/index.d.ts +3 -0
- package/dist/internal/cache-engine/index.js +2 -0
- package/dist/internal/cache-engine/types.d.ts +300 -0
- package/dist/internal/cache-engine/types.js +1 -0
- package/dist/internal/cache-engine.d.ts +3 -0
- package/dist/internal/cache-engine.js +2 -0
- package/dist/lib/assert-name.d.ts +2 -0
- package/dist/lib/assert-name.js +6 -0
- package/dist/lib/compare-code-units.d.ts +2 -0
- package/dist/lib/compare-code-units.js +4 -0
- package/dist/lib/deep-equal.d.ts +2 -0
- package/dist/lib/deep-equal.js +24 -0
- package/dist/lib/freeze-record.d.ts +2 -0
- package/dist/lib/freeze-record.js +13 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.js +6 -0
- package/dist/lib/is-plain-record.d.ts +2 -0
- package/dist/lib/is-plain-record.js +8 -0
- package/dist/lib/report.d.ts +7 -0
- package/dist/lib/report.js +26 -0
- package/dist/protocol.d.ts +179 -0
- package/dist/protocol.js +558 -0
- package/dist/react/context.d.ts +20 -0
- package/dist/react/context.js +24 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +3 -0
- package/dist/react/query.d.ts +20 -0
- package/dist/react/query.js +99 -0
- package/dist/replica/command-id.d.ts +2 -0
- package/dist/replica/command-id.js +19 -0
- package/dist/replica/command-runtime/constants.d.ts +5 -0
- package/dist/replica/command-runtime/constants.js +5 -0
- package/dist/replica/command-runtime/create.d.ts +2 -0
- package/dist/replica/command-runtime/create.js +644 -0
- package/dist/replica/command-runtime/errors.d.ts +16 -0
- package/dist/replica/command-runtime/errors.js +41 -0
- package/dist/replica/command-runtime/index.d.ts +5 -0
- package/dist/replica/command-runtime/index.js +4 -0
- package/dist/replica/command-runtime/lib/binding.d.ts +4 -0
- package/dist/replica/command-runtime/lib/binding.js +64 -0
- package/dist/replica/command-runtime/lib/effects.d.ts +11 -0
- package/dist/replica/command-runtime/lib/effects.js +89 -0
- package/dist/replica/command-runtime/lib/index.d.ts +9 -0
- package/dist/replica/command-runtime/lib/index.js +9 -0
- package/dist/replica/command-runtime/lib/inventory.d.ts +10 -0
- package/dist/replica/command-runtime/lib/inventory.js +141 -0
- package/dist/replica/command-runtime/lib/output.d.ts +13 -0
- package/dist/replica/command-runtime/lib/output.js +190 -0
- package/dist/replica/command-runtime/lib/projection.d.ts +20 -0
- package/dist/replica/command-runtime/lib/projection.js +255 -0
- package/dist/replica/command-runtime/lib/status.d.ts +7 -0
- package/dist/replica/command-runtime/lib/status.js +127 -0
- package/dist/replica/command-runtime/lib/transport.d.ts +16 -0
- package/dist/replica/command-runtime/lib/transport.js +112 -0
- package/dist/replica/command-runtime/lib/util.d.ts +16 -0
- package/dist/replica/command-runtime/lib/util.js +127 -0
- package/dist/replica/command-runtime/lifecycle.d.ts +11 -0
- package/dist/replica/command-runtime/lifecycle.js +13 -0
- package/dist/replica/command-runtime/symbols.d.ts +30 -0
- package/dist/replica/command-runtime/symbols.js +30 -0
- package/dist/replica/command-runtime/types.d.ts +222 -0
- package/dist/replica/command-runtime/types.js +1 -0
- package/dist/replica/command-runtime.d.ts +3 -0
- package/dist/replica/command-runtime.js +2 -0
- package/dist/replica/commands/clone.d.ts +12 -0
- package/dist/replica/commands/clone.js +187 -0
- package/dist/replica/commands/constants.d.ts +6 -0
- package/dist/replica/commands/constants.js +6 -0
- package/dist/replica/commands/errors.d.ts +7 -0
- package/dist/replica/commands/errors.js +22 -0
- package/dist/replica/commands/implementation.d.ts +8 -0
- package/dist/replica/commands/implementation.js +8 -0
- package/dist/replica/commands/index.d.ts +5 -0
- package/dist/replica/commands/index.js +4 -0
- package/dist/replica/commands/prepare.d.ts +27 -0
- package/dist/replica/commands/prepare.js +77 -0
- package/dist/replica/commands/presets.d.ts +12 -0
- package/dist/replica/commands/presets.js +84 -0
- package/dist/replica/commands/receipt.d.ts +3 -0
- package/dist/replica/commands/receipt.js +36 -0
- package/dist/replica/commands/resolve.d.ts +11 -0
- package/dist/replica/commands/resolve.js +165 -0
- package/dist/replica/commands/types.d.ts +278 -0
- package/dist/replica/commands/types.js +2 -0
- package/dist/replica/commands/util.d.ts +21 -0
- package/dist/replica/commands/util.js +96 -0
- package/dist/replica/commands/validate.d.ts +18 -0
- package/dist/replica/commands/validate.js +477 -0
- package/dist/replica/commands.d.ts +3 -0
- package/dist/replica/commands.js +2 -0
- package/dist/replica/diagnostics/event-log.d.ts +4 -0
- package/dist/replica/diagnostics/event-log.js +463 -0
- package/dist/replica/diagnostics/implementation.d.ts +4 -0
- package/dist/replica/diagnostics/implementation.js +4 -0
- package/dist/replica/diagnostics/index.d.ts +2 -0
- package/dist/replica/diagnostics/index.js +1 -0
- package/dist/replica/diagnostics/inspect.d.ts +6 -0
- package/dist/replica/diagnostics/inspect.js +170 -0
- package/dist/replica/diagnostics/types.d.ts +295 -0
- package/dist/replica/diagnostics/types.js +2 -0
- package/dist/replica/diagnostics.d.ts +3 -0
- package/dist/replica/diagnostics.js +2 -0
- package/dist/replica/distributed-replica/clocks.d.ts +23 -0
- package/dist/replica/distributed-replica/clocks.js +156 -0
- package/dist/replica/distributed-replica/constants.d.ts +12 -0
- package/dist/replica/distributed-replica/constants.js +10 -0
- package/dist/replica/distributed-replica/helpers.d.ts +48 -0
- package/dist/replica/distributed-replica/helpers.js +445 -0
- package/dist/replica/distributed-replica/hydration.d.ts +19 -0
- package/dist/replica/distributed-replica/hydration.js +380 -0
- package/dist/replica/distributed-replica/impl-diagnostics.d.ts +22 -0
- package/dist/replica/distributed-replica/impl-diagnostics.js +189 -0
- package/dist/replica/distributed-replica/impl-fetch-live.d.ts +39 -0
- package/dist/replica/distributed-replica/impl-fetch-live.js +395 -0
- package/dist/replica/distributed-replica/impl-hydration-orchestrate.d.ts +56 -0
- package/dist/replica/distributed-replica/impl-hydration-orchestrate.js +299 -0
- package/dist/replica/distributed-replica/impl-optimistic.d.ts +31 -0
- package/dist/replica/distributed-replica/impl-optimistic.js +172 -0
- package/dist/replica/distributed-replica/impl-protocol.d.ts +53 -0
- package/dist/replica/distributed-replica/impl-protocol.js +108 -0
- package/dist/replica/distributed-replica/impl.d.ts +44 -0
- package/dist/replica/distributed-replica/impl.js +1776 -0
- package/dist/replica/distributed-replica/index.d.ts +2 -0
- package/dist/replica/distributed-replica/index.js +4 -0
- package/dist/replica/distributed-replica/optimistic.d.ts +30 -0
- package/dist/replica/distributed-replica/optimistic.js +221 -0
- package/dist/replica/distributed-replica/types.d.ts +147 -0
- package/dist/replica/distributed-replica/types.js +1 -0
- package/dist/replica/distributed-replica/watch.d.ts +19 -0
- package/dist/replica/distributed-replica/watch.js +95 -0
- package/dist/replica/distributed-replica.d.ts +2 -0
- package/dist/replica/distributed-replica.js +2 -0
- package/dist/replica/graphql-transport.d.ts +24 -0
- package/dist/replica/graphql-transport.js +122 -0
- package/dist/replica/identity/clone.d.ts +6 -0
- package/dist/replica/identity/clone.js +54 -0
- package/dist/replica/identity/codec.d.ts +48 -0
- package/dist/replica/identity/codec.js +789 -0
- package/dist/replica/identity/constants.d.ts +3 -0
- package/dist/replica/identity/constants.js +18 -0
- package/dist/replica/identity/implementation.d.ts +5 -0
- package/dist/replica/identity/implementation.js +5 -0
- package/dist/replica/identity/index.d.ts +3 -0
- package/dist/replica/identity/index.js +3 -0
- package/dist/replica/identity/keys.d.ts +29 -0
- package/dist/replica/identity/keys.js +173 -0
- package/dist/replica/identity.d.ts +2 -0
- package/dist/replica/identity.js +2 -0
- package/dist/replica/index-maintenance/engine.d.ts +84 -0
- package/dist/replica/index-maintenance/engine.js +677 -0
- package/dist/replica/index-maintenance/implementation.d.ts +4 -0
- package/dist/replica/index-maintenance/implementation.js +4 -0
- package/dist/replica/index-maintenance/index.d.ts +2 -0
- package/dist/replica/index-maintenance/index.js +1 -0
- package/dist/replica/index-maintenance/registry.d.ts +2 -0
- package/dist/replica/index-maintenance/registry.js +49 -0
- package/dist/replica/index-maintenance/types.d.ts +58 -0
- package/dist/replica/index-maintenance/types.js +1 -0
- package/dist/replica/index-maintenance.d.ts +3 -0
- package/dist/replica/index-maintenance.js +2 -0
- package/dist/replica/index.d.ts +17 -0
- package/dist/replica/index.js +9 -0
- package/dist/replica/materialize.d.ts +10 -0
- package/dist/replica/materialize.js +163 -0
- package/dist/replica/normalize.d.ts +27 -0
- package/dist/replica/normalize.js +298 -0
- package/dist/replica/operation-binding.d.ts +14 -0
- package/dist/replica/operation-binding.js +76 -0
- package/dist/replica/persistence/idb.d.ts +20 -0
- package/dist/replica/persistence/idb.js +193 -0
- package/dist/replica/persistence/implementation.d.ts +4 -0
- package/dist/replica/persistence/implementation.js +4 -0
- package/dist/replica/persistence/index.d.ts +2 -0
- package/dist/replica/persistence/index.js +1 -0
- package/dist/replica/persistence/state.d.ts +104 -0
- package/dist/replica/persistence/state.js +734 -0
- package/dist/replica/persistence/types.d.ts +54 -0
- package/dist/replica/persistence/types.js +1 -0
- package/dist/replica/persistence.d.ts +3 -0
- package/dist/replica/persistence.js +2 -0
- package/dist/replica/query-plan/constants.d.ts +13 -0
- package/dist/replica/query-plan/constants.js +7 -0
- package/dist/replica/query-plan/filter.d.ts +39 -0
- package/dist/replica/query-plan/filter.js +544 -0
- package/dist/replica/query-plan/index.d.ts +4 -0
- package/dist/replica/query-plan/index.js +3 -0
- package/dist/replica/query-plan/order.d.ts +11 -0
- package/dist/replica/query-plan/order.js +158 -0
- package/dist/replica/query-plan/pagination.d.ts +6 -0
- package/dist/replica/query-plan/pagination.js +90 -0
- package/dist/replica/query-plan/resolve.d.ts +14 -0
- package/dist/replica/query-plan/resolve.js +163 -0
- package/dist/replica/query-plan/types.d.ts +89 -0
- package/dist/replica/query-plan/types.js +1 -0
- package/dist/replica/query-plan/util.d.ts +13 -0
- package/dist/replica/query-plan/util.js +62 -0
- package/dist/replica/query-plan.d.ts +3 -0
- package/dist/replica/query-plan.js +2 -0
- package/dist/replica/revalidation.d.ts +9 -0
- package/dist/replica/revalidation.js +86 -0
- package/dist/replica/selection.d.ts +20 -0
- package/dist/replica/selection.js +109 -0
- package/dist/replica/types.d.ts +657 -0
- package/dist/replica/types.js +1 -0
- package/dist/request.d.ts +17 -0
- package/dist/request.js +123 -0
- package/dist/sveltekit/auth.d.ts +18 -0
- package/dist/sveltekit/auth.js +9 -0
- package/dist/sveltekit/context.d.ts +28 -0
- package/dist/sveltekit/context.js +58 -0
- package/dist/sveltekit/index.d.ts +4 -0
- package/dist/sveltekit/index.js +4 -0
- package/dist/sveltekit/replica.d.ts +145 -0
- package/dist/sveltekit/replica.js +491 -0
- package/dist/sveltekit/server-replica.d.ts +52 -0
- package/dist/sveltekit/server-replica.js +176 -0
- package/dist/sveltekit/vite.d.ts +103 -0
- package/dist/sveltekit/vite.js +878 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.js +1 -0
- package/dist/websocket.d.ts +41 -0
- package/dist/websocket.js +187 -0
- package/package.json +95 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { replicaCommandProjectedLifecycle } from './symbols.js';
|
|
2
|
+
/**
|
|
3
|
+
* Package-private causal lifecycle used by framework adapters.
|
|
4
|
+
*
|
|
5
|
+
* A caller-scoped `receipt.projected` can reject when its AbortSignal fires
|
|
6
|
+
* after acceptance. The underlying command remains globally pending until
|
|
7
|
+
* canonical projection evidence settles this independent promise.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export function replicaCommandProjectedLifecycleOf(receipt) {
|
|
12
|
+
return receipt[replicaCommandProjectedLifecycle];
|
|
13
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-private authority handshake implemented by DistributedReplica.
|
|
3
|
+
*
|
|
4
|
+
* This symbol is intentionally not exported from the public replica barrel.
|
|
5
|
+
* Generated command binders can therefore consume server-derived preset values,
|
|
6
|
+
* while application code cannot pass an ambient caller-owned inventory.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare const replicaCommandAuthority: unique symbol;
|
|
11
|
+
/**
|
|
12
|
+
* Package-private post-commit observation channel implemented by
|
|
13
|
+
* DistributedReplica. Generated command runtimes register here so framework
|
|
14
|
+
* adapters never guess replica commit ordering.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export declare const replicaResultObservation: unique symbol;
|
|
19
|
+
/**
|
|
20
|
+
* Package-private direct-projection commit implemented by DistributedReplica.
|
|
21
|
+
*
|
|
22
|
+
* The replica must advance its protocol record clock in the same confirmation
|
|
23
|
+
* path as the base-cache write. Otherwise an older query response can be
|
|
24
|
+
* mistaken for an incomplete write after the cache correctly rejects it.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export declare const replicaCommandDirectProjection: unique symbol;
|
|
29
|
+
/** @internal Package-private; intentionally absent from the public barrel. */
|
|
30
|
+
export declare const replicaCommandProjectedLifecycle: unique symbol;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-private authority handshake implemented by DistributedReplica.
|
|
3
|
+
*
|
|
4
|
+
* This symbol is intentionally not exported from the public replica barrel.
|
|
5
|
+
* Generated command binders can therefore consume server-derived preset values,
|
|
6
|
+
* while application code cannot pass an ambient caller-owned inventory.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export const replicaCommandAuthority = Symbol('distributed.replica.command-authority');
|
|
11
|
+
/**
|
|
12
|
+
* Package-private post-commit observation channel implemented by
|
|
13
|
+
* DistributedReplica. Generated command runtimes register here so framework
|
|
14
|
+
* adapters never guess replica commit ordering.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export const replicaResultObservation = Symbol('distributed.replica.result-observation');
|
|
19
|
+
/**
|
|
20
|
+
* Package-private direct-projection commit implemented by DistributedReplica.
|
|
21
|
+
*
|
|
22
|
+
* The replica must advance its protocol record clock in the same confirmation
|
|
23
|
+
* path as the base-cache write. Otherwise an older query response can be
|
|
24
|
+
* mistaken for an incomplete write after the cache correctly rejects it.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export const replicaCommandDirectProjection = Symbol('distributed.replica.command-direct-projection');
|
|
29
|
+
/** @internal Package-private; intentionally absent from the public barrel. */
|
|
30
|
+
export const replicaCommandProjectedLifecycle = Symbol('distributed.replica.command-projected-lifecycle');
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import type { DistributedCommandMetadata, DistributedCommandState, DistributedRecordRevision, DistributedTrustedPreset } from '../../protocol.js';
|
|
2
|
+
import type { GqlError } from '../../types.js';
|
|
3
|
+
import type { PrepareReplicaCommandOptions, ReplicaCommandArtifact, ReplicaPreparedCommand, ReplicaTrustedPresetDescriptor } from '../commands.js';
|
|
4
|
+
import type { ReplicaDiagnosticsSink } from '../diagnostics.js';
|
|
5
|
+
import type { ReplicaIndexSemanticChange } from '../index-maintenance.js';
|
|
6
|
+
import type { DistributedReplica, ReplicaAuthoritativeScope, ReplicaClientSurface, ReplicaIdentity, ReplicaModelArtifact, ReplicaOptimisticWriter, ReplicaResultEnvelope, ReplicaValue } from '../types.js';
|
|
7
|
+
import { replicaCommandAuthority, replicaCommandDirectProjection, replicaCommandProjectedLifecycle, replicaResultObservation } from './symbols.js';
|
|
8
|
+
export type ReplicaCommandSurfaceContract = Readonly<{
|
|
9
|
+
protocolVersion: 1;
|
|
10
|
+
schemaHash: string;
|
|
11
|
+
protocolHash: string;
|
|
12
|
+
surface: ReplicaClientSurface;
|
|
13
|
+
trustedPresets: readonly ReplicaTrustedPresetDescriptor[];
|
|
14
|
+
}>;
|
|
15
|
+
export type ReplicaCommandAuthoritySnapshot = Readonly<{
|
|
16
|
+
generation: number;
|
|
17
|
+
scope: ReplicaAuthoritativeScope | undefined;
|
|
18
|
+
trustedPresets: readonly DistributedTrustedPreset[];
|
|
19
|
+
/** Aborted by the replica when this authorization generation closes. */
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}>;
|
|
22
|
+
export type ReplicaCommandAuthorityRegistration = Readonly<{
|
|
23
|
+
read(): ReplicaCommandAuthoritySnapshot;
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}>;
|
|
26
|
+
export type ReplicaResultObservationRegistration = Readonly<{
|
|
27
|
+
dispose(): void;
|
|
28
|
+
}>;
|
|
29
|
+
export type ReplicaCommandDirectProjection = Readonly<{
|
|
30
|
+
model: ReplicaModelArtifact;
|
|
31
|
+
identity: ReplicaIdentity;
|
|
32
|
+
evidence: DistributedRecordRevision;
|
|
33
|
+
fields: Readonly<Record<string, ReplicaValue>>;
|
|
34
|
+
}>;
|
|
35
|
+
export type ReplicaCommandAuthorityHost = DistributedReplica & {
|
|
36
|
+
readonly [replicaCommandAuthority]?: (contract: ReplicaCommandSurfaceContract) => ReplicaCommandAuthorityRegistration;
|
|
37
|
+
readonly [replicaResultObservation]?: (observer: (envelope: ReplicaResultEnvelope<unknown>) => void) => ReplicaResultObservationRegistration;
|
|
38
|
+
readonly [replicaCommandDirectProjection]?: (commandId: string, projection: ReplicaCommandDirectProjection) => void;
|
|
39
|
+
};
|
|
40
|
+
export type ReplicaCommandTransportRequest = Readonly<{
|
|
41
|
+
operation: 'mutation';
|
|
42
|
+
commandName: string;
|
|
43
|
+
commandId: string;
|
|
44
|
+
mutationField: string;
|
|
45
|
+
document: string;
|
|
46
|
+
operationHash: string;
|
|
47
|
+
variables: Readonly<Record<string, unknown>>;
|
|
48
|
+
extensions: Readonly<Record<string, unknown>>;
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
}>;
|
|
51
|
+
export type ReplicaCommandStatusArtifact = Readonly<{
|
|
52
|
+
name: string;
|
|
53
|
+
document: string;
|
|
54
|
+
operationHash: string;
|
|
55
|
+
protocol: Readonly<{
|
|
56
|
+
version: 1;
|
|
57
|
+
schemaHash: string;
|
|
58
|
+
protocolHash: string;
|
|
59
|
+
surface: ReplicaClientSurface;
|
|
60
|
+
operation: string;
|
|
61
|
+
/** Exact surface union: command presets plus client-evaluable policy claims. */
|
|
62
|
+
trustedPresets: readonly ReplicaTrustedPresetDescriptor[];
|
|
63
|
+
}>;
|
|
64
|
+
}>;
|
|
65
|
+
export type ReplicaCommandStatusRequest = Readonly<{
|
|
66
|
+
operation: 'status';
|
|
67
|
+
commandId: string;
|
|
68
|
+
name: string;
|
|
69
|
+
document: string;
|
|
70
|
+
operationHash: string;
|
|
71
|
+
variables: Readonly<{
|
|
72
|
+
commandId: string;
|
|
73
|
+
}>;
|
|
74
|
+
extensions: Readonly<Record<string, unknown>>;
|
|
75
|
+
signal?: AbortSignal;
|
|
76
|
+
}>;
|
|
77
|
+
export type ReplicaCommandTransportResult = Readonly<{
|
|
78
|
+
data?: Readonly<Record<string, unknown>> | null;
|
|
79
|
+
errors?: readonly GqlError[];
|
|
80
|
+
extensions?: unknown;
|
|
81
|
+
status: number;
|
|
82
|
+
}>;
|
|
83
|
+
export interface ReplicaCommandTransport {
|
|
84
|
+
dispatch(request: ReplicaCommandTransportRequest): Promise<ReplicaCommandTransportResult>;
|
|
85
|
+
/** Execute the exact compiler-owned command-status operation. */
|
|
86
|
+
status?(request: ReplicaCommandStatusRequest): Promise<ReplicaCommandTransportResult>;
|
|
87
|
+
}
|
|
88
|
+
export type ReplicaCommandProjectedOutcome<TOutput> = Readonly<{
|
|
89
|
+
commandId: string;
|
|
90
|
+
state: 'projected';
|
|
91
|
+
/** Present for same-transaction Projected<T>, absent for async facts. */
|
|
92
|
+
result?: TOutput;
|
|
93
|
+
metadata?: DistributedCommandMetadata;
|
|
94
|
+
}>;
|
|
95
|
+
export type ReplicaCommandStatus = Readonly<{
|
|
96
|
+
commandId: string;
|
|
97
|
+
state: DistributedCommandState;
|
|
98
|
+
/**
|
|
99
|
+
* Durable causal evidence. The server deliberately omits it for the
|
|
100
|
+
* non-enumerating `unknown` and compact `expired` states.
|
|
101
|
+
*/
|
|
102
|
+
metadata?: DistributedCommandMetadata;
|
|
103
|
+
}>;
|
|
104
|
+
export type ReplicaCommandReceipt<TOutput> = Readonly<{
|
|
105
|
+
commandId: string;
|
|
106
|
+
state: Extract<DistributedCommandState, 'accepted' | 'accepted_pending_projection' | 'projected'>;
|
|
107
|
+
/** Typed application payload returned by the generated mutation. */
|
|
108
|
+
result: TOutput;
|
|
109
|
+
metadata: DistributedCommandMetadata;
|
|
110
|
+
/** One exact generated status read. Calls coalesce while in flight. */
|
|
111
|
+
status(): Promise<ReplicaCommandStatus>;
|
|
112
|
+
/**
|
|
113
|
+
* Causal visibility awaitable. It is omitted when no finite projection
|
|
114
|
+
* contract exists and never resolves because a wall-clock timer elapsed.
|
|
115
|
+
*/
|
|
116
|
+
projected?: Promise<ReplicaCommandProjectedOutcome<TOutput>>;
|
|
117
|
+
}>;
|
|
118
|
+
export type ReplicaCommandReceiptWithLifecycle = ReplicaCommandReceipt<unknown> & Readonly<{
|
|
119
|
+
[replicaCommandProjectedLifecycle]?: Promise<ReplicaCommandProjectedOutcome<unknown>>;
|
|
120
|
+
}>;
|
|
121
|
+
/**
|
|
122
|
+
* Package-private causal lifecycle used by framework adapters.
|
|
123
|
+
*
|
|
124
|
+
* A caller-scoped `receipt.projected` can reject when its AbortSignal fires
|
|
125
|
+
* after acceptance. The underlying command remains globally pending until
|
|
126
|
+
* canonical projection evidence settles this independent promise.
|
|
127
|
+
*
|
|
128
|
+
* @internal
|
|
129
|
+
*/
|
|
130
|
+
/**
|
|
131
|
+
* Stable recovery handle attached to an ambiguous dispatch error.
|
|
132
|
+
*
|
|
133
|
+
* `status()` never infers success from time. The original immutable prepared
|
|
134
|
+
* mutation remains retained by the runtime/layer; status reports the durable
|
|
135
|
+
* server outcome without manufacturing rollback or confirmation.
|
|
136
|
+
*/
|
|
137
|
+
export type ReplicaCommandRecoveryReceipt<TOutput = unknown> = Readonly<{
|
|
138
|
+
commandId: string;
|
|
139
|
+
status(): Promise<ReplicaCommandStatus>;
|
|
140
|
+
/** Phantom slot retains the originating generated output type. */
|
|
141
|
+
readonly __output?: TOutput;
|
|
142
|
+
}>;
|
|
143
|
+
export type ReplicaCommandCallOptions<TOutput> = PrepareReplicaCommandOptions & Readonly<{
|
|
144
|
+
/**
|
|
145
|
+
* Cancels dispatch while the command outcome is unknown. After finite
|
|
146
|
+
* acceptance it instead bounds only this caller's `receipt.projected`
|
|
147
|
+
* wait; causal tracking and the optimistic layer continue independently.
|
|
148
|
+
*/
|
|
149
|
+
signal?: AbortSignal;
|
|
150
|
+
/** Exact same prepared request retries after thrown/ambiguous transport. */
|
|
151
|
+
transportRetries?: number;
|
|
152
|
+
onAccepted?: (receipt: ReplicaCommandReceipt<TOutput>) => void | Promise<void>;
|
|
153
|
+
}>;
|
|
154
|
+
export type ReplicaCommandRuntimeErrorCode = 'REPLICA_COMMAND_ABORTED' | 'REPLICA_COMMAND_AUTHORITY_UNAVAILABLE' | 'REPLICA_COMMAND_DISPOSED' | 'REPLICA_COMMAND_OUTCOME_PENDING' | 'REPLICA_COMMAND_PROJECTION_FAILED' | 'REPLICA_COMMAND_PROTOCOL_INVALID' | 'REPLICA_COMMAND_REJECTED' | 'REPLICA_COMMAND_SCOPE_INVALIDATED' | 'REPLICA_COMMAND_STATUS_UNAVAILABLE' | 'REPLICA_COMMAND_TRANSPORT_AMBIGUOUS';
|
|
155
|
+
export type AnyCommandArtifact = ReplicaCommandArtifact<unknown, unknown>;
|
|
156
|
+
export type CommandEntry = AnyCommandArtifact | Readonly<{
|
|
157
|
+
artifact: AnyCommandArtifact;
|
|
158
|
+
}>;
|
|
159
|
+
export type ArtifactOf<TEntry> = TEntry extends ReplicaCommandArtifact<infer TInput, infer TOutput> ? ReplicaCommandArtifact<TInput, TOutput> : TEntry extends Readonly<{
|
|
160
|
+
artifact: ReplicaCommandArtifact<infer TInput, infer TOutput>;
|
|
161
|
+
}> ? ReplicaCommandArtifact<TInput, TOutput> : never;
|
|
162
|
+
export type InputOf<TEntry> = ArtifactOf<TEntry> extends ReplicaCommandArtifact<infer TInput, unknown> ? TInput : never;
|
|
163
|
+
export type OutputOf<TEntry> = ArtifactOf<TEntry> extends ReplicaCommandArtifact<unknown, infer TOutput> ? TOutput : never;
|
|
164
|
+
export type ReplicaBoundCommand<TInput, TOutput> = [TInput] extends [void] ? (options?: ReplicaCommandCallOptions<TOutput>) => Promise<ReplicaCommandReceipt<TOutput>> : (input: TInput, options?: ReplicaCommandCallOptions<TOutput>) => Promise<ReplicaCommandReceipt<TOutput>>;
|
|
165
|
+
export type ReplicaBoundCommandPath<TPath extends string, TCommand> = TPath extends `${infer THead}.${infer TTail}` ? THead extends '' ? never : Readonly<{
|
|
166
|
+
[TKey in THead]: ReplicaBoundCommandPath<TTail, TCommand>;
|
|
167
|
+
}> : TPath extends '' ? never : Readonly<{
|
|
168
|
+
[TKey in TPath]: TCommand;
|
|
169
|
+
}>;
|
|
170
|
+
export type UnionToIntersection<TValue> = (TValue extends unknown ? (value: TValue) => void : never) extends (value: infer TIntersection) => void ? TIntersection : never;
|
|
171
|
+
export type SimplifyCommandTree<TValue> = TValue extends (...args: infer _TArguments) => infer _TResult ? TValue : Readonly<{
|
|
172
|
+
[TKey in keyof TValue]: SimplifyCommandTree<TValue[TKey]>;
|
|
173
|
+
}>;
|
|
174
|
+
export type ReplicaBoundCommands<TEntries extends Readonly<Record<string, CommandEntry>>> = SimplifyCommandTree<UnionToIntersection<{
|
|
175
|
+
[TKey in Extract<keyof TEntries, string>]: ReplicaBoundCommandPath<TKey, ReplicaBoundCommand<InputOf<TEntries[TKey]>, OutputOf<TEntries[TKey]>>>;
|
|
176
|
+
}[Extract<keyof TEntries, string>]>>;
|
|
177
|
+
export type ReplicaCommandRuntimeOptions = Readonly<{
|
|
178
|
+
onBackgroundError?: (error: unknown) => void;
|
|
179
|
+
/** Exact generated status operation for delayed/ambiguous recovery. */
|
|
180
|
+
status?: ReplicaCommandStatusArtifact;
|
|
181
|
+
/** Optional shared replica diagnostics sink used only for static artifact inspection. */
|
|
182
|
+
diagnostics?: ReplicaDiagnosticsSink;
|
|
183
|
+
}>;
|
|
184
|
+
export interface ReplicaCommandRuntime<TEntries extends Readonly<Record<string, CommandEntry>>> {
|
|
185
|
+
readonly commands: ReplicaBoundCommands<TEntries>;
|
|
186
|
+
/**
|
|
187
|
+
* Observe a query/live result only after the replica committed it.
|
|
188
|
+
*
|
|
189
|
+
* This completes pending causal awaitables from exact scoped observations;
|
|
190
|
+
* it does not normalize or confirm cache data itself.
|
|
191
|
+
*/
|
|
192
|
+
observeResult(envelope: ReplicaResultEnvelope<unknown>): void;
|
|
193
|
+
dispose(): void;
|
|
194
|
+
}
|
|
195
|
+
export type CapturedAuthority = Readonly<{
|
|
196
|
+
generation: number;
|
|
197
|
+
scope: ReplicaAuthoritativeScope;
|
|
198
|
+
trustedPresets: readonly DistributedTrustedPreset[];
|
|
199
|
+
signal?: AbortSignal;
|
|
200
|
+
}>;
|
|
201
|
+
export type PendingProjection = {
|
|
202
|
+
readonly commandId: string;
|
|
203
|
+
readonly causationId: string;
|
|
204
|
+
readonly authority: CapturedAuthority;
|
|
205
|
+
readonly resolve: (value: ReplicaCommandProjectedOutcome<unknown>) => void;
|
|
206
|
+
readonly reject: (error: unknown) => void;
|
|
207
|
+
readonly promise: Promise<ReplicaCommandProjectedOutcome<unknown>>;
|
|
208
|
+
readonly prepared: ReplicaPreparedCommand<unknown, unknown>;
|
|
209
|
+
abort?: () => void;
|
|
210
|
+
stopMonitor?: () => void;
|
|
211
|
+
metadata: DistributedCommandMetadata;
|
|
212
|
+
settled: boolean;
|
|
213
|
+
};
|
|
214
|
+
export type CommandStatusTracker = {
|
|
215
|
+
state: DistributedCommandState | undefined;
|
|
216
|
+
metadata: DistributedCommandMetadata | undefined;
|
|
217
|
+
inFlight: Promise<ReplicaCommandStatus> | undefined;
|
|
218
|
+
pending?: PendingProjection;
|
|
219
|
+
};
|
|
220
|
+
export type SemanticReplica = DistributedReplica & {
|
|
221
|
+
createOptimisticLayer(id: string, update: (writer: ReplicaOptimisticWriter) => void, semanticChanges?: readonly ReplicaIndexSemanticChange[]): void;
|
|
222
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { replicaCommandAuthority, replicaCommandDirectProjection, replicaCommandProjectedLifecycle, replicaResultObservation } from './symbols.js';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Public entry for command runtime; implementation lives in ./command-runtime/. */
|
|
2
|
+
export { createReplicaCommandRuntime, ReplicaCommandRuntimeError, replicaCommandAuthority, replicaCommandDirectProjection, replicaCommandProjectedLifecycle, replicaCommandProjectedLifecycleOf, replicaResultObservation } from './command-runtime/index.js';
|
|
3
|
+
export type { ReplicaBoundCommand, ReplicaBoundCommands, ReplicaCommandAuthorityHost, ReplicaCommandAuthorityRegistration, ReplicaCommandAuthoritySnapshot, ReplicaCommandCallOptions, ReplicaCommandDirectProjection, ReplicaCommandProjectedOutcome, ReplicaCommandReceipt, ReplicaCommandRecoveryReceipt, ReplicaCommandRuntime, ReplicaCommandRuntimeErrorCode, ReplicaCommandRuntimeOptions, ReplicaCommandStatus, ReplicaCommandStatusArtifact, ReplicaCommandStatusRequest, ReplicaCommandSurfaceContract, ReplicaCommandTransport, ReplicaCommandTransportRequest, ReplicaCommandTransportResult, ReplicaResultObservationRegistration } from './command-runtime/index.js';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/** Public entry for command runtime; implementation lives in ./command-runtime/. */
|
|
2
|
+
export { createReplicaCommandRuntime, ReplicaCommandRuntimeError, replicaCommandAuthority, replicaCommandDirectProjection, replicaCommandProjectedLifecycle, replicaCommandProjectedLifecycleOf, replicaResultObservation } from './command-runtime/index.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReplicaClientSurface, ReplicaValue } from '../types.js';
|
|
2
|
+
import type { ReplicaCommandGenerators, ReplicaCommandInputDefault, ReplicaCommandRevalidationPlan, ReplicaCommandEffectRelationship, ReplicaCommandScalarCodec, ReplicaCommandTypeDefinition, ReplicaCommandTypeField, ReplicaTrustedPresetDescriptor } from './types.js';
|
|
3
|
+
export declare function cloneClientSurface(surface: ReplicaClientSurface): ReplicaClientSurface;
|
|
4
|
+
export declare function cloneTrustedPresetDescriptors(value: readonly ReplicaTrustedPresetDescriptor[]): readonly ReplicaTrustedPresetDescriptor[];
|
|
5
|
+
export declare function cloneDefinitionValue(definition: ReplicaCommandTypeDefinition, value: unknown, path: readonly string[], defaults: readonly ReplicaCommandInputDefault[], generators: ReplicaCommandGenerators | undefined, label: string): Readonly<Record<string, unknown>>;
|
|
6
|
+
export declare function cloneFieldValue(field: ReplicaCommandTypeField, value: unknown, path: readonly string[], defaults: readonly ReplicaCommandInputDefault[], generators: ReplicaCommandGenerators | undefined, label: string): unknown;
|
|
7
|
+
export declare function cloneNonNullFieldValue(field: ReplicaCommandTypeField, value: unknown, path: readonly string[], defaults: readonly ReplicaCommandInputDefault[], generators: ReplicaCommandGenerators | undefined, label: string): unknown;
|
|
8
|
+
export declare function cloneScalar(codec: ReplicaCommandScalarCodec | undefined, value: unknown, path: string): ReplicaValue;
|
|
9
|
+
export declare function cloneJson(value: unknown, path: string, active?: Set<object>, depth?: number): ReplicaValue;
|
|
10
|
+
export declare function cloneRevalidation(plan: ReplicaCommandRevalidationPlan): ReplicaCommandRevalidationPlan;
|
|
11
|
+
export declare function cloneRelationship(relationship: ReplicaCommandEffectRelationship, path: string): ReplicaCommandEffectRelationship;
|
|
12
|
+
export declare function generateDefault(entry: ReplicaCommandInputDefault, generators: ReplicaCommandGenerators | undefined, path: string): string;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { createReplicaCommandId } from '../command-id.js';
|
|
2
|
+
import { isPlainRecord } from '../../lib/is-plain-record.js';
|
|
3
|
+
import { MAX_TYPE_DEPTH } from './constants.js';
|
|
4
|
+
import { artifactInvalid, createUlid, defineEnumerable, inputInvalid, requiredString, samePath, validateUlid, validateUuidV7 } from './util.js';
|
|
5
|
+
export function cloneClientSurface(surface) {
|
|
6
|
+
return surface.kind === 'role'
|
|
7
|
+
? Object.freeze({ kind: 'role', name: surface.name })
|
|
8
|
+
: Object.freeze({
|
|
9
|
+
kind: 'application',
|
|
10
|
+
name: surface.name,
|
|
11
|
+
roles: Object.freeze([...surface.roles])
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export function cloneTrustedPresetDescriptors(value) {
|
|
15
|
+
return Object.freeze(value.map(({ name, codec }) => Object.freeze({ name, codec })));
|
|
16
|
+
}
|
|
17
|
+
export function cloneDefinitionValue(definition, value, path, defaults, generators, label) {
|
|
18
|
+
if (!isPlainRecord(value))
|
|
19
|
+
inputInvalid(label);
|
|
20
|
+
const ownKeys = Reflect.ownKeys(value);
|
|
21
|
+
if (ownKeys.some((key) => typeof key !== 'string'))
|
|
22
|
+
inputInvalid(label);
|
|
23
|
+
const known = new Set(definition.fields.map((field) => field.name));
|
|
24
|
+
for (const key of ownKeys) {
|
|
25
|
+
if (!known.has(key))
|
|
26
|
+
inputInvalid(`${label}.${key}`);
|
|
27
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
28
|
+
if (descriptor === undefined || !('value' in descriptor)) {
|
|
29
|
+
inputInvalid(`${label}.${key}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const result = {};
|
|
33
|
+
for (const field of definition.fields) {
|
|
34
|
+
const fieldPath = [...path, field.name];
|
|
35
|
+
const fieldLabel = `${label}.${field.name}`;
|
|
36
|
+
const present = Object.prototype.hasOwnProperty.call(value, field.name) &&
|
|
37
|
+
value[field.name] !== undefined;
|
|
38
|
+
let fieldValue;
|
|
39
|
+
if (present) {
|
|
40
|
+
fieldValue = value[field.name];
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const declared = defaults.find((entry) => samePath(entry.path, fieldPath));
|
|
44
|
+
if (declared !== undefined) {
|
|
45
|
+
fieldValue = generateDefault(declared, generators, fieldLabel);
|
|
46
|
+
}
|
|
47
|
+
else if (field.nullable) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
inputInvalid(fieldLabel);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
defineEnumerable(result, field.name, cloneFieldValue(field, fieldValue, fieldPath, defaults, generators, fieldLabel));
|
|
55
|
+
}
|
|
56
|
+
return Object.freeze(result);
|
|
57
|
+
}
|
|
58
|
+
export function cloneFieldValue(field, value, path, defaults, generators, label) {
|
|
59
|
+
if (value === null) {
|
|
60
|
+
if (!field.nullable)
|
|
61
|
+
inputInvalid(label);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
if (field.list) {
|
|
65
|
+
if (!Array.isArray(value))
|
|
66
|
+
inputInvalid(label);
|
|
67
|
+
return Object.freeze(value.map((item, index) => {
|
|
68
|
+
if (item === null) {
|
|
69
|
+
if (!field.itemNullable)
|
|
70
|
+
inputInvalid(`${label}[${index}]`);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return cloneNonNullFieldValue(field, item, path, defaults, generators, `${label}[${index}]`);
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
return cloneNonNullFieldValue(field, value, path, defaults, generators, label);
|
|
77
|
+
}
|
|
78
|
+
export function cloneNonNullFieldValue(field, value, path, defaults, generators, label) {
|
|
79
|
+
if (field.nested !== undefined) {
|
|
80
|
+
return cloneDefinitionValue(field.nested, value, path, defaults, generators, label);
|
|
81
|
+
}
|
|
82
|
+
return cloneScalar(field.codec, value, label);
|
|
83
|
+
}
|
|
84
|
+
export function cloneScalar(codec, value, path) {
|
|
85
|
+
switch (codec) {
|
|
86
|
+
case 'string':
|
|
87
|
+
case 'string_unvalidated_timestamp':
|
|
88
|
+
case 'base64':
|
|
89
|
+
if (typeof value !== 'string')
|
|
90
|
+
inputInvalid(path);
|
|
91
|
+
return value;
|
|
92
|
+
case 'boolean':
|
|
93
|
+
if (typeof value !== 'boolean')
|
|
94
|
+
inputInvalid(path);
|
|
95
|
+
return value;
|
|
96
|
+
case 'int32':
|
|
97
|
+
if (typeof value !== 'number' ||
|
|
98
|
+
!Number.isInteger(value) ||
|
|
99
|
+
value < -2_147_483_648 ||
|
|
100
|
+
value > 2_147_483_647) {
|
|
101
|
+
inputInvalid(path);
|
|
102
|
+
}
|
|
103
|
+
return Object.is(value, -0) ? 0 : value;
|
|
104
|
+
case 'json_number_precision_limited':
|
|
105
|
+
if (typeof value !== 'number' || !Number.isInteger(value)) {
|
|
106
|
+
inputInvalid(path);
|
|
107
|
+
}
|
|
108
|
+
return Object.is(value, -0) ? 0 : value;
|
|
109
|
+
case 'float64':
|
|
110
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
111
|
+
inputInvalid(path);
|
|
112
|
+
}
|
|
113
|
+
return Object.is(value, -0) ? 0 : value;
|
|
114
|
+
case 'json':
|
|
115
|
+
return cloneJson(value, path);
|
|
116
|
+
default:
|
|
117
|
+
artifactInvalid(`${path}.codec`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export function cloneJson(value, path, active = new Set(), depth = 0) {
|
|
121
|
+
if (depth > MAX_TYPE_DEPTH)
|
|
122
|
+
inputInvalid(path);
|
|
123
|
+
if (value === null ||
|
|
124
|
+
typeof value === 'string' ||
|
|
125
|
+
typeof value === 'boolean') {
|
|
126
|
+
return value;
|
|
127
|
+
}
|
|
128
|
+
if (typeof value === 'number') {
|
|
129
|
+
if (!Number.isFinite(value))
|
|
130
|
+
inputInvalid(path);
|
|
131
|
+
return Object.is(value, -0) ? 0 : value;
|
|
132
|
+
}
|
|
133
|
+
if (Array.isArray(value)) {
|
|
134
|
+
if (active.has(value))
|
|
135
|
+
inputInvalid(path);
|
|
136
|
+
active.add(value);
|
|
137
|
+
const result = Object.freeze(value.map((item, index) => cloneJson(item, `${path}[${index}]`, active, depth + 1)));
|
|
138
|
+
active.delete(value);
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
if (!isPlainRecord(value))
|
|
142
|
+
inputInvalid(path);
|
|
143
|
+
if (active.has(value))
|
|
144
|
+
inputInvalid(path);
|
|
145
|
+
active.add(value);
|
|
146
|
+
const keys = Reflect.ownKeys(value);
|
|
147
|
+
if (keys.some((key) => typeof key !== 'string'))
|
|
148
|
+
inputInvalid(path);
|
|
149
|
+
const result = {};
|
|
150
|
+
for (const key of keys.sort()) {
|
|
151
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
152
|
+
if (descriptor === undefined ||
|
|
153
|
+
!('value' in descriptor) ||
|
|
154
|
+
descriptor.value === undefined) {
|
|
155
|
+
inputInvalid(`${path}.${key}`);
|
|
156
|
+
}
|
|
157
|
+
defineEnumerable(result, key, cloneJson(descriptor.value, `${path}.${key}`, active, depth + 1));
|
|
158
|
+
}
|
|
159
|
+
active.delete(value);
|
|
160
|
+
return Object.freeze(result);
|
|
161
|
+
}
|
|
162
|
+
export function cloneRevalidation(plan) {
|
|
163
|
+
return Object.freeze({
|
|
164
|
+
version: 1,
|
|
165
|
+
required: plan.required,
|
|
166
|
+
dependencies: Object.freeze([...plan.dependencies]),
|
|
167
|
+
models: Object.freeze([...plan.models]),
|
|
168
|
+
relationships: Object.freeze(plan.relationships.map((relationship, index) => cloneRelationship(relationship, `artifact.revalidation.relationships[${index}]`)))
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
export function cloneRelationship(relationship, path) {
|
|
172
|
+
return Object.freeze({
|
|
173
|
+
sourceModel: requiredString(relationship.sourceModel, `${path}.sourceModel`),
|
|
174
|
+
field: requiredString(relationship.field, `${path}.field`),
|
|
175
|
+
targetModel: requiredString(relationship.targetModel, `${path}.targetModel`)
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
export function generateDefault(entry, generators, path) {
|
|
179
|
+
switch (entry.generator) {
|
|
180
|
+
case 'uuid_v7':
|
|
181
|
+
return validateUuidV7((generators?.uuidV7 ?? createReplicaCommandId)(), path, 'REPLICA_COMMAND_INPUT_INVALID');
|
|
182
|
+
case 'ulid':
|
|
183
|
+
return validateUlid((generators?.ulid ?? createUlid)(), path);
|
|
184
|
+
default:
|
|
185
|
+
artifactInvalid(`${path}.generator`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const SHA256: RegExp;
|
|
2
|
+
export declare const UUID_V7: RegExp;
|
|
3
|
+
export declare const ULID: RegExp;
|
|
4
|
+
export declare const GRAPHQL_NAME: RegExp;
|
|
5
|
+
export declare const ULID_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
6
|
+
export declare const MAX_TYPE_DEPTH = 64;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const SHA256 = /^sha256:[0-9a-f]{64}$/;
|
|
2
|
+
export const UUID_V7 = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
3
|
+
export const ULID = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
|
|
4
|
+
export const GRAPHQL_NAME = /^[_A-Za-z][_0-9A-Za-z]*$/;
|
|
5
|
+
export const ULID_ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
6
|
+
export const MAX_TYPE_DEPTH = 64;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReplicaCommandContractErrorCode } from './types.js';
|
|
2
|
+
export declare function commandErrorMessage(code: ReplicaCommandContractErrorCode, path: string): string;
|
|
3
|
+
export declare class ReplicaCommandContractError extends Error {
|
|
4
|
+
readonly code: ReplicaCommandContractErrorCode;
|
|
5
|
+
readonly path: string;
|
|
6
|
+
constructor(code: ReplicaCommandContractErrorCode, path: string);
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function commandErrorMessage(code, path) {
|
|
2
|
+
switch (code) {
|
|
3
|
+
case 'REPLICA_COMMAND_ARTIFACT_INVALID':
|
|
4
|
+
return `Invalid generated replica command artifact at ${path}`;
|
|
5
|
+
case 'REPLICA_COMMAND_INPUT_INVALID':
|
|
6
|
+
return `Invalid replica command input at ${path}`;
|
|
7
|
+
case 'REPLICA_COMMAND_RECEIPT_MISMATCH':
|
|
8
|
+
return `Replica command receipt does not match ${path}`;
|
|
9
|
+
case 'REPLICA_COMMAND_TRUSTED_PRESET_MISMATCH':
|
|
10
|
+
return `Authoritative trusted preset inventory does not match ${path}`;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class ReplicaCommandContractError extends Error {
|
|
14
|
+
code;
|
|
15
|
+
path;
|
|
16
|
+
constructor(code, path) {
|
|
17
|
+
super(commandErrorMessage(code, path));
|
|
18
|
+
this.name = 'ReplicaCommandContractError';
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.path = path;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Re-export surface for command implementation modules (body-split). */
|
|
2
|
+
export * from './util.js';
|
|
3
|
+
export * from './clone.js';
|
|
4
|
+
export * from './presets.js';
|
|
5
|
+
export * from './validate.js';
|
|
6
|
+
export * from './resolve.js';
|
|
7
|
+
export * from './receipt.js';
|
|
8
|
+
export * from './prepare.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Re-export surface for command implementation modules (body-split). */
|
|
2
|
+
export * from './util.js';
|
|
3
|
+
export * from './clone.js';
|
|
4
|
+
export * from './presets.js';
|
|
5
|
+
export * from './validate.js';
|
|
6
|
+
export * from './resolve.js';
|
|
7
|
+
export * from './receipt.js';
|
|
8
|
+
export * from './prepare.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { prepareReplicaCommand, prepareReplicaCommandWithTrustedPresets } from './prepare.js';
|
|
2
|
+
export { matchReplicaTrustedPresetInventory } from './presets.js';
|
|
3
|
+
export { verifyReplicaCommandReceipt } from './receipt.js';
|
|
4
|
+
export { ReplicaCommandContractError } from './errors.js';
|
|
5
|
+
export type { PrepareReplicaCommandOptions, ReplicaCommandArtifact, ReplicaCommandConfirmation, ReplicaCommandConfirmations, ReplicaCommandContractErrorCode, ReplicaCommandDirectProjection, ReplicaCommandEffect, ReplicaCommandEffectExpression, ReplicaCommandEffectField, ReplicaCommandEffectKey, ReplicaCommandEffectRelationship, ReplicaCommandEffects, ReplicaCommandGenerators, ReplicaCommandInputDefault, ReplicaCommandInputDefaults, ReplicaCommandRevalidationPlan, ReplicaCommandScalarCodec, ReplicaCommandShape, ReplicaCommandTypeDefinition, ReplicaCommandTypeField, ReplicaCommandVariables, ReplicaMatchedTrustedPresetInventory, ReplicaPreparedCommand, ReplicaPreparedCommandEffect, ReplicaPreparedConfirmation, ReplicaPreparedConfirmations, ReplicaPreparedEffectField, ReplicaPreparedEffectKey, ReplicaReceiptVerification, ReplicaTrustedPresetDescriptor } from './types.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { prepareReplicaCommand, prepareReplicaCommandWithTrustedPresets } from './prepare.js';
|
|
2
|
+
export { matchReplicaTrustedPresetInventory } from './presets.js';
|
|
3
|
+
export { verifyReplicaCommandReceipt } from './receipt.js';
|
|
4
|
+
export { ReplicaCommandContractError } from './errors.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DistributedTrustedPreset } from '../../protocol.js';
|
|
2
|
+
import type { PrepareReplicaCommandOptions, ReplicaCommandArtifact, ReplicaPreparedCommand } from './types.js';
|
|
3
|
+
export declare function prepareReplicaCommand<TInput, TOutput>(artifact: ReplicaCommandArtifact<TInput, TOutput>, input: TInput, options?: PrepareReplicaCommandOptions): ReplicaPreparedCommand<TInput, TOutput>;
|
|
4
|
+
/**
|
|
5
|
+
* Finalize a command with values obtained from the replica's current
|
|
6
|
+
* authoritative scope generation.
|
|
7
|
+
*
|
|
8
|
+
* The incoming inventory is scope-wide, so values owned by other commands are
|
|
9
|
+
* ignored. Every descriptor consumed by this artifact must nevertheless have
|
|
10
|
+
* one exact name/codec match before defaults, optimism, or transport state is
|
|
11
|
+
* created.
|
|
12
|
+
*
|
|
13
|
+
* This seam is package-internal and deliberately omitted from the public
|
|
14
|
+
* `@hops-ops/distributed/replica` entry point.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export declare function prepareReplicaCommandWithTrustedPresets<TInput, TOutput>(artifact: ReplicaCommandArtifact<TInput, TOutput>, input: TInput, authoritativePresets: readonly DistributedTrustedPreset[], options?: PrepareReplicaCommandOptions): ReplicaPreparedCommand<TInput, TOutput>;
|
|
19
|
+
export declare function prepareReplicaCommandInternal<TInput, TOutput>(artifact: ReplicaCommandArtifact<TInput, TOutput>, input: TInput, options: PrepareReplicaCommandOptions, authoritativePresets?: readonly DistributedTrustedPreset[]): ReplicaPreparedCommand<TInput, TOutput>;
|
|
20
|
+
/**
|
|
21
|
+
* Match two command-local inventories as exact name/codec sets.
|
|
22
|
+
*
|
|
23
|
+
* Both sides are reparsed instead of trusting TypeScript annotations. Missing,
|
|
24
|
+
* extra, duplicate, unsupported, or codec-mismatched entries fail closed.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|