@hops-ops/distributed 4.8.0 → 4.10.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.
Files changed (37) hide show
  1. package/README.md +46 -8
  2. package/dist/generation.d.ts +15 -0
  3. package/dist/generation.js +41 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +1 -0
  6. package/dist/protocol.d.ts +2 -0
  7. package/dist/protocol.js +5 -0
  8. package/dist/replica/command-runtime/create.js +11 -0
  9. package/dist/replica/command-runtime/errors.js +2 -0
  10. package/dist/replica/command-runtime/types.d.ts +7 -1
  11. package/dist/replica/distributed-replica/impl-protocol.d.ts +1 -0
  12. package/dist/replica/distributed-replica/impl-protocol.js +1 -0
  13. package/dist/replica/distributed-replica/impl.js +11 -0
  14. package/dist/replica/distributed-replica/watch.js +13 -1
  15. package/dist/replica/index.d.ts +1 -1
  16. package/dist/replica/types.d.ts +38 -0
  17. package/dist/sveltekit/boundary-lifecycle.d.ts +37 -0
  18. package/dist/sveltekit/boundary-lifecycle.js +355 -0
  19. package/dist/sveltekit/boundary-variables.d.ts +57 -0
  20. package/dist/sveltekit/boundary-variables.js +290 -0
  21. package/dist/sveltekit/context.d.ts +3 -0
  22. package/dist/sveltekit/context.js +8 -0
  23. package/dist/sveltekit/index.d.ts +7 -3
  24. package/dist/sveltekit/index.js +6 -2
  25. package/dist/sveltekit/islands/boundaries.d.ts +104 -0
  26. package/dist/sveltekit/islands/boundaries.js +734 -0
  27. package/dist/sveltekit/lifecycle.d.ts +57 -0
  28. package/dist/sveltekit/lifecycle.js +454 -0
  29. package/dist/sveltekit/operation-identity.d.ts +4 -0
  30. package/dist/sveltekit/operation-identity.js +10 -0
  31. package/dist/sveltekit/replica.d.ts +29 -2
  32. package/dist/sveltekit/replica.js +102 -6
  33. package/dist/sveltekit/server-replica.d.ts +10 -26
  34. package/dist/sveltekit/server-replica.js +159 -132
  35. package/dist/sveltekit/vite.d.ts +46 -3
  36. package/dist/sveltekit/vite.js +643 -36
  37. package/package.json +4 -3
package/README.md CHANGED
@@ -5,7 +5,7 @@ The generated, end-to-end typed client for
5
5
 
6
6
  Rust table, relationship, role, and command definitions produce one authorized
7
7
  client surface. `distributed client` combines that surface with application GraphQL
8
- documents and emits typed operations, live companions, route-load plans, and
8
+ documents and emits typed operations, live companions, island metadata, and
9
9
  commands. This package executes those artifacts through one normalized,
10
10
  causally consistent browser replica.
11
11
 
@@ -67,7 +67,7 @@ injects wire-only identity and revision fields, and emits:
67
67
  - an exact typed operation and optional live companion;
68
68
  - normalization, identity, relationship, filter, order, and pagination plans;
69
69
  - the closed variable codec used before cache lookup or transport;
70
- - a static `@load` route registry;
70
+ - framework-neutral island metadata plus an inspectable SvelteKit boundary plan;
71
71
  - an SSR-safe SvelteKit wrapper with static operation bindings and tree-local
72
72
  client/command access;
73
73
  - a nested command tree with input defaults, optimistic effects, and causal
@@ -100,7 +100,10 @@ export const distributedClients = [
100
100
  module: '$distributed',
101
101
  manifest: { args: serviceManifestArgs },
102
102
  surface: 'e2e-ui',
103
- documents: ['src/routes/(app)/**/*.graphql'],
103
+ documents: [
104
+ 'src/routes/(app)/**/*.graphql',
105
+ 'src/lib/components/**/*.graphql'
106
+ ],
104
107
  out: 'src/lib/generated/distributed'
105
108
  },
106
109
  {
@@ -128,6 +131,13 @@ keeps ordinary application documents out of the admin tree; each trust boundary
128
131
  has its own Rust manifest entrypoint, generated directory, virtual module, and
129
132
  request-local replica. A single-surface application can omit the second entry.
130
133
 
134
+ A component can own a sibling `Component.graphql` island. The adapter walks
135
+ static Svelte imports and promotes `@load` work to the nearest page/layout.
136
+ Route-local `+page.graphql` and `+layout.graphql` remain first-class. When a
137
+ required variable cannot be proved from route/search/session/forwarded-prop
138
+ sources, add one typed `boundaries` registration here; that generated binding
139
+ is reused by SSR, hover prefetch, navigation, hydration, and live work.
140
+
131
141
  The Vite integration runs `distributed client` at startup/build, watches GraphQL
132
142
  documents, stages all surfaces, commits a rollback-capable multi-output
133
143
  transaction, then triggers one reload. It exposes the generated Svelte wrapper
@@ -194,11 +204,11 @@ import {
194
204
  createDistributedSvelteKitServer
195
205
  } from '@hops-ops/distributed/sveltekit';
196
206
  import {
197
- DISTRIBUTED_ROUTE_OPERATIONS
207
+ DISTRIBUTED_BOUNDARY_OPERATIONS
198
208
  } from '$distributed';
199
209
 
200
210
  const distributed = createDistributedSvelteKitServer({
201
- routes: DISTRIBUTED_ROUTE_OPERATIONS,
211
+ boundaries: DISTRIBUTED_BOUNDARY_OPERATIONS,
202
212
  getSession: ({ locals }) => locals.auth(),
203
213
  getRole: (session) => roleFromSession(session)
204
214
  });
@@ -212,15 +222,20 @@ authorization lifecycle. The generated module retains no client singleton:
212
222
  ```ts
213
223
  // src/routes/+layout.svelte
214
224
  import { browser } from '$app/environment';
225
+ import { page } from '$app/state';
215
226
  import {
216
227
  createPageDataSessionSource
217
228
  } from '@hops-ops/distributed/sveltekit';
218
- import { provideDistributed } from '$distributed';
229
+ import {
230
+ DISTRIBUTED_BOUNDARY_OPERATIONS,
231
+ provideDistributed
232
+ } from '$distributed';
219
233
 
220
234
  let { data, children } = $props();
221
235
  const pageData = createPageDataSessionSource(data);
222
236
 
223
237
  const client = provideDistributed({
238
+ boundaries: DISTRIBUTED_BOUNDARY_OPERATIONS,
224
239
  browser,
225
240
  session: pageData.session,
226
241
  ...(data.distributed !== undefined &&
@@ -233,6 +248,26 @@ const client = provideDistributed({
233
248
  });
234
249
 
235
250
  $effect(() => pageData.set(data));
251
+
252
+ $effect(() => {
253
+ const retained = client.retainLocation(
254
+ { id: 'active-page', pathname: page.url.pathname, kind: 'page' },
255
+ {
256
+ search: page.url.searchParams,
257
+ session: data.session,
258
+ props: data
259
+ }
260
+ );
261
+ return () => retained.release();
262
+ });
263
+
264
+ // A delegated link-hover handler can warm any generated target without an
265
+ // operation-name switch or a second variable map.
266
+ await client.prefetchLocation(target.pathname, {
267
+ search: target.searchParams,
268
+ session: data.session,
269
+ props: data
270
+ });
236
271
  ```
237
272
 
238
273
  Route components import only their generated surface. Static operation wrappers
@@ -296,7 +331,10 @@ deduplicates work, and optionally maintains the generated live operation.
296
331
  `read()` is side-effect-free. `dehydrate()` and `hydrate()` transfer confirmed
297
332
  state without exposing a public storage schema. Cold `hydrate` seeds an empty
298
333
  client; warm same-scope `hydrate` merges so soft navigation cannot discard
299
- confirmed session data the next route did not re-dehydrate.
334
+ confirmed session data the next boundary did not re-dehydrate. Layout
335
+ retention survives child navigation, page retention is replaced on page exit,
336
+ and exact layout/page duplicates share one replica watch until the final owner
337
+ releases it.
300
338
 
301
339
  The replica stores normalized records and exact argument-sensitive indexes,
302
340
  not GraphQL response blobs. Generated selection metadata reconstructs each
@@ -423,7 +461,7 @@ duplicated as decision documents in this package.
423
461
  command runtime, query-plan helpers, and optional persistence.
424
462
  - `@hops-ops/distributed/diagnostics` — redacted support snapshots and artifact
425
463
  inspection.
426
- - `@hops-ops/distributed/sveltekit` — Svelte stores, SSR route loading,
464
+ - `@hops-ops/distributed/sveltekit` — Svelte stores, island SSR composition,
427
465
  hydration, auth lifecycle, and tree-local generated bindings.
428
466
  - `@hops-ops/distributed/sveltekit/vite` — Node-only one-shot/check/watch
429
467
  generation, virtual module aliases, and GraphQL HTTP/WebSocket proxy helpers.
@@ -0,0 +1,15 @@
1
+ export type DistributedGenerationEnvelope = Readonly<{
2
+ version: 1;
3
+ generationId: string;
4
+ releaseId: string;
5
+ applicationId?: string;
6
+ clientId?: string;
7
+ schemaId?: string;
8
+ protocolId?: string;
9
+ topologyId?: string;
10
+ workerId?: string;
11
+ memberId?: string;
12
+ compatibilityId?: string;
13
+ }>;
14
+ /** Parse a generation envelope without trusting unbounded process metadata. */
15
+ export declare function parseDistributedGenerationEnvelope(value: unknown, path?: string): DistributedGenerationEnvelope;
@@ -0,0 +1,41 @@
1
+ /** Parse a generation envelope without trusting unbounded process metadata. */
2
+ export function parseDistributedGenerationEnvelope(value, path = 'generation') {
3
+ const record = object(value, path);
4
+ if (record.version !== 1)
5
+ throw new TypeError(`${path}.version must be 1`);
6
+ const parsed = {
7
+ version: 1,
8
+ generationId: identity(record.generationId, `${path}.generationId`),
9
+ releaseId: identity(record.releaseId, `${path}.releaseId`)
10
+ };
11
+ for (const key of [
12
+ 'applicationId',
13
+ 'clientId',
14
+ 'schemaId',
15
+ 'protocolId',
16
+ 'topologyId',
17
+ 'workerId',
18
+ 'memberId',
19
+ 'compatibilityId'
20
+ ]) {
21
+ if (record[key] !== undefined)
22
+ parsed[key] = identity(record[key], `${path}.${key}`);
23
+ }
24
+ return Object.freeze(parsed);
25
+ }
26
+ function object(value, path) {
27
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
28
+ throw new TypeError(`${path} must be an object`);
29
+ }
30
+ return value;
31
+ }
32
+ function identity(value, path) {
33
+ if (typeof value !== 'string' ||
34
+ value.length === 0 ||
35
+ value.length > 512 ||
36
+ value !== value.trim() ||
37
+ /[\u0000-\u001f\u007f]/.test(value)) {
38
+ throw new TypeError(`${path} must be a bounded stable identity`);
39
+ }
40
+ return value;
41
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export type { GqlAuth, GqlError, GqlErrorLocation, GqlResult, GraphqlVariables } from './types.js';
2
+ export { parseDistributedGenerationEnvelope, type DistributedGenerationEnvelope } from './generation.js';
2
3
  export { DISTRIBUTED_PROTOCOL_VERSION, DistributedProtocolError, compareDistributedDecimal, distributedLiveResumeExtensions, parseDistributedProtocolEnvelope, parseGraphqlResponseExtensions, type DistributedDecimalString, type DistributedCommandConsistency, type DistributedCommandMetadata, type DistributedCommandState, type DistributedIndexRevision, type DistributedLiveCursor, type DistributedLiveMetadata, type DistributedLiveResumeExtensions, type DistributedOpaqueString, type DistributedProjectionExpectation, type DistributedProjectionObservation, type DistributedProtocolValue, type DistributedProtocolEnvelope, type DistributedProtocolErrorCode, type DistributedQuerySnapshot, type DistributedRecordRevision, type DistributedTrustedPreset, type DistributedTrustedPresetCodec, type GraphqlResponseExtensions } from './protocol.js';
3
4
  export { documentToString, type GqlDocument } from './document.js';
4
5
  export { applyWsDevHeaderParams, buildAuthHeaders, wsConnectionInitPayload } from './auth-headers.js';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { parseDistributedGenerationEnvelope } from './generation.js';
1
2
  export { DISTRIBUTED_PROTOCOL_VERSION, DistributedProtocolError, compareDistributedDecimal, distributedLiveResumeExtensions, parseDistributedProtocolEnvelope, parseGraphqlResponseExtensions } from './protocol.js';
2
3
  export { documentToString } from './document.js';
3
4
  export { applyWsDevHeaderParams, buildAuthHeaders, wsConnectionInitPayload } from './auth-headers.js';
@@ -7,6 +7,7 @@
7
7
  * them, but never parses them as numbers or reconstructs server scopes.
8
8
  */
9
9
  import { type CommandProjectionMetadata } from './replica/projection-delta/index.js';
10
+ import { type DistributedGenerationEnvelope } from './generation.js';
10
11
  /** The only Distributed GraphQL protocol version understood by this package. */
11
12
  export declare const DISTRIBUTED_PROTOCOL_VERSION: 1;
12
13
  declare const opaqueDistributedString: unique symbol;
@@ -125,6 +126,7 @@ export type DistributedProtocolEnvelope = Readonly<Record<string, unknown> & {
125
126
  schemaHash: string;
126
127
  authorizationGeneration: string;
127
128
  cacheScope: DistributedOpaqueString;
129
+ generation?: DistributedGenerationEnvelope;
128
130
  operation?: string;
129
131
  command?: DistributedCommandMetadata;
130
132
  snapshot?: DistributedQuerySnapshot;
package/dist/protocol.js CHANGED
@@ -7,6 +7,7 @@
7
7
  * them, but never parses them as numbers or reconstructs server scopes.
8
8
  */
9
9
  import { parseCommandProjectionMetadata } from './replica/projection-delta/index.js';
10
+ import { parseDistributedGenerationEnvelope } from './generation.js';
10
11
  /** The only Distributed GraphQL protocol version understood by this package. */
11
12
  export const DISTRIBUTED_PROTOCOL_VERSION = 1;
12
13
  /** Safe parse failure that reports structure, never hidden server values. */
@@ -82,6 +83,9 @@ export function parseDistributedProtocolEnvelope(value) {
82
83
  const schemaHash = publicString(envelope.schemaHash, 'extensions.distributed.schemaHash');
83
84
  const authorizationGeneration = publicString(envelope.authorizationGeneration, 'extensions.distributed.authorizationGeneration');
84
85
  const cacheScope = opaqueString(envelope.cacheScope, 'extensions.distributed.cacheScope');
86
+ const generation = envelope.generation === undefined
87
+ ? undefined
88
+ : parseDistributedGenerationEnvelope(envelope.generation, 'extensions.distributed.generation');
85
89
  const operation = envelope.operation === undefined
86
90
  ? undefined
87
91
  : publicString(envelope.operation, 'extensions.distributed.operation');
@@ -102,6 +106,7 @@ export function parseDistributedProtocolEnvelope(value) {
102
106
  schemaHash,
103
107
  authorizationGeneration,
104
108
  cacheScope,
109
+ ...(generation === undefined ? {} : { generation }),
105
110
  ...(operation === undefined ? {} : { operation }),
106
111
  ...(command === undefined ? {} : { command }),
107
112
  ...(snapshot === undefined ? {} : { snapshot }),
@@ -372,6 +372,14 @@ export function createReplicaCommandRuntime(replica, transport, entries, options
372
372
  if (disposed) {
373
373
  throw new ReplicaCommandRuntimeError('REPLICA_COMMAND_DISPOSED');
374
374
  }
375
+ try {
376
+ options.lifecycle?.assertDispatchOpen();
377
+ }
378
+ catch (error) {
379
+ throw new ReplicaCommandRuntimeError('REPLICA_COMMAND_RELOADING', {
380
+ cause: error
381
+ });
382
+ }
375
383
  const snapshot = authoritySnapshot();
376
384
  const scope = snapshot.scope;
377
385
  if (scope === undefined ||
@@ -1088,6 +1096,9 @@ export function createReplicaCommandRuntime(replica, transport, entries, options
1088
1096
  return Object.freeze({
1089
1097
  commands: commands,
1090
1098
  observeResult,
1099
+ pendingCommandIds() {
1100
+ return Object.freeze([...new Set([...pending.keys(), ...unmanagedLayers])].sort());
1101
+ },
1091
1102
  dispose() {
1092
1103
  if (disposed)
1093
1104
  return;
@@ -14,6 +14,8 @@ export function commandRuntimeErrorMessage(code) {
14
14
  return 'Command response violated the generated protocol contract';
15
15
  case 'REPLICA_COMMAND_REJECTED':
16
16
  return 'Command was rejected';
17
+ case 'REPLICA_COMMAND_RELOADING':
18
+ return 'Command dispatch is paused during a coherent application reload';
17
19
  case 'REPLICA_COMMAND_SCOPE_INVALIDATED':
18
20
  return 'Command authorization scope changed';
19
21
  case 'REPLICA_COMMAND_STATUS_UNAVAILABLE':
@@ -154,7 +154,7 @@ export type ReplicaCommandCallOptions<TOutput> = PrepareReplicaCommandOptions &
154
154
  transportRetries?: number;
155
155
  onSucceeded?: (receipt: ReplicaCommandReceipt<TOutput>) => void | Promise<void>;
156
156
  }>;
157
- 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';
157
+ 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_RELOADING' | 'REPLICA_COMMAND_SCOPE_INVALIDATED' | 'REPLICA_COMMAND_STATUS_UNAVAILABLE' | 'REPLICA_COMMAND_TRANSPORT_AMBIGUOUS';
158
158
  export type AnyCommandArtifact = ReplicaCommandArtifact<unknown, unknown>;
159
159
  export type CommandEntry = AnyCommandArtifact | Readonly<{
160
160
  artifact: AnyCommandArtifact;
@@ -188,6 +188,10 @@ export type ReplicaCommandRuntimeOptions = Readonly<{
188
188
  * Generated clients ship their inventory; apps do not invent board sims ad hoc.
189
189
  */
190
190
  pureFunctions?: Readonly<Record<string, ReplicaPureFunction>>;
191
+ /** Framework lifecycle fence checked immediately before command preparation. */
192
+ lifecycle?: Readonly<{
193
+ assertDispatchOpen(): void;
194
+ }>;
191
195
  }>;
192
196
  export interface ReplicaCommandRuntime<TEntries extends Readonly<Record<string, CommandEntry>>> {
193
197
  readonly commands: ReplicaBoundCommands<TEntries>;
@@ -198,6 +202,8 @@ export interface ReplicaCommandRuntime<TEntries extends Readonly<Record<string,
198
202
  * it does not normalize or confirm cache data itself.
199
203
  */
200
204
  observeResult(envelope: ReplicaResultEnvelope<unknown>): void;
205
+ /** Opaque receipt identities safe to carry across a controlled reload. */
206
+ pendingCommandIds(): readonly string[];
201
207
  dispose(): void;
202
208
  }
203
209
  export type CapturedAuthority = Readonly<{
@@ -34,6 +34,7 @@ export type ProtocolHost = {
34
34
  setProtocolGeneration(value: ProtocolGeneration | undefined): void;
35
35
  getProtocolGenerationSequence(): number;
36
36
  bumpProtocolGenerationSequence(): void;
37
+ disposeAuthorizationGeneration(): void;
37
38
  getTrustedPresets(): readonly DistributedTrustedPreset[];
38
39
  setTrustedPresets(value: readonly DistributedTrustedPreset[]): void;
39
40
  getCommandAuthorityContract(): RegisteredCommandAuthorityContract | undefined;
@@ -107,6 +107,7 @@ export function purgeProtocolGeneration(host) {
107
107
  }
108
108
  export function closeAuthorizationGeneration(host) {
109
109
  host.bumpProtocolGenerationSequence();
110
+ host.disposeAuthorizationGeneration();
110
111
  host.abortAuthorization();
111
112
  host.closeActiveTransports();
112
113
  }
@@ -22,6 +22,7 @@ export class DistributedReplicaImpl {
22
22
  #engine;
23
23
  #transport;
24
24
  #reportObserverError;
25
+ #onAuthorizationGenerationDispose;
25
26
  #diagnostics;
26
27
  #diagnosticLayers;
27
28
  #inFlight = new Map();
@@ -68,6 +69,8 @@ export class DistributedReplicaImpl {
68
69
  constructor(options = {}) {
69
70
  this.#transport = options.transport;
70
71
  this.#reportObserverError = options.onObserverError ?? reportUnhandledObserverError;
72
+ this.#onAuthorizationGenerationDispose =
73
+ options.onAuthorizationGenerationDispose;
71
74
  this.#diagnostics = options.diagnostics;
72
75
  this.#diagnosticLayers =
73
76
  options.diagnostics === undefined ? undefined : new Map();
@@ -209,6 +212,14 @@ export class DistributedReplicaImpl {
209
212
  bumpProtocolGenerationSequence: () => {
210
213
  self.#protocolGenerationSequence += 1;
211
214
  },
215
+ disposeAuthorizationGeneration: () => {
216
+ try {
217
+ self.#onAuthorizationGenerationDispose?.();
218
+ }
219
+ catch (error) {
220
+ self._reportObserverErrors([error]);
221
+ }
222
+ },
212
223
  getTrustedPresets: () => self.#trustedPresets,
213
224
  setTrustedPresets: (value) => {
214
225
  self.#trustedPresets = value;
@@ -11,6 +11,7 @@ export class ReplicaWatchState {
11
11
  #snapshot;
12
12
  #identitySignature;
13
13
  #destroyed = false;
14
+ #autoFetchScheduled = false;
14
15
  #unregister;
15
16
  constructor(owner, artifact, variables, options) {
16
17
  this.#owner = owner;
@@ -57,7 +58,8 @@ export class ReplicaWatchState {
57
58
  if (this.#destroyed)
58
59
  return;
59
60
  this.materialized = materialized;
60
- this.#sync(true);
61
+ this.#sync(false);
62
+ this.#scheduleAutoFetch();
61
63
  }
62
64
  _stateChanged(allowFetch) {
63
65
  if (this.#destroyed)
@@ -92,4 +94,14 @@ export class ReplicaWatchState {
92
94
  if (allowFetch)
93
95
  void this.#owner._fetch(this, false);
94
96
  }
97
+ #scheduleAutoFetch() {
98
+ if (this.#autoFetchScheduled || this.#destroyed)
99
+ return;
100
+ this.#autoFetchScheduled = true;
101
+ queueMicrotask(() => {
102
+ this.#autoFetchScheduled = false;
103
+ if (!this.#destroyed)
104
+ void this.#owner._fetch(this, false);
105
+ });
106
+ }
95
107
  }
@@ -17,6 +17,6 @@ export { compareReplicaOrder, decideReplicaPaginationMaintenance, evaluateReplic
17
17
  export { createReplicaIndexMaintenanceRegistry, formatReplicaIndexStaleReason } from './index-maintenance.js';
18
18
  export type { ReplicaIndexDependencyChange, ReplicaIndexMaintenanceDecision, ReplicaIndexMaintenanceIndex, ReplicaIndexMaintenanceReason, ReplicaIndexMaintenanceReasonCode, ReplicaIndexMaintenanceRecord, ReplicaIndexMaintenanceRegistry, ReplicaIndexMaintenanceSnapshot, ReplicaIndexPlanRegistration, ReplicaIndexRecordChange, ReplicaIndexRelationshipChange, ReplicaIndexSemanticChange, ReplicaIndexSemanticLayer } from './index-maintenance.js';
19
19
  export type { ReplicaFilterEvaluation, ReplicaFilterEvaluationOptions, ReplicaOrderComparison, ReplicaPaginationChange, ReplicaPaginationMaintenanceDecision, ReplicaQueryPlanPath, ReplicaQueryPlanReason, ReplicaQueryPlanReasonCode, ReplicaRelationshipFilterRequest } from './query-plan.js';
20
- export type { DistributedReplicaOptions, DistributedReplica, ReplicaArgumentsArtifact, ReplicaArgumentValue, ReplicaAuthoritativeScope, ReplicaBaseWriter, ReplicaBranchSemantic, ReplicaClientSurface, ReplicaCoverageArtifact, ReplicaDehydratedState, ReplicaFilterArtifact, ReplicaFilterExpression, ReplicaFilterFieldArtifact, ReplicaFilterLiteral, ReplicaFilterOperand, ReplicaFilterOperator, ReplicaIdentity, ReplicaIndexCoverage, ReplicaIndexInspection, ReplicaIndexTarget, ReplicaListValue, ReplicaLiveObserver, ReplicaLiveState, ReplicaLiteralValue, ReplicaModelArtifact, ReplicaObjectBranch, ReplicaObjectMember, ReplicaObjectSelection, ReplicaObjectValue, ReplicaOperationArtifact, ReplicaOperationSourceLocation, ReplicaOperationProtocol, ReplicaOrderArtifact, ReplicaOrderFieldArtifact, ReplicaOrderTieBreakerArtifact, ReplicaOptimisticWriter, ReplicaPaginationArtifact, ReplicaPaginationDisposition, ReplicaProtocolOperationArtifact, ReplicaRecordInspection, ReplicaRecordPatch, ReplicaRevalidationPlan, ReplicaRevalidationRelationship, ReplicaRevision, ReplicaRelationshipArtifact, ReplicaRelationshipKeyMapping, ReplicaRelationshipKind, ReplicaResultEnvelope, ReplicaRowPolicyArtifact, ReplicaRootSelection, ReplicaScalarSelection, ReplicaSelectionStorage, ReplicaSparse, ReplicaSnapshot, ReplicaStatus, ReplicaTransport, ReplicaTransportRequest, ReplicaVariableValue, ReplicaVariableCodecArtifact, ReplicaVariableEnumInputRef, ReplicaVariableFilterInputDefinition, ReplicaVariableFilterInputField, ReplicaVariableFilterInputRelationship, ReplicaVariableFilterInputTarget, ReplicaVariableInputDefinition, ReplicaVariableInputRef, ReplicaVariableListInputRef, ReplicaVariableNamedInputRef, ReplicaVariableOrderInputDefinition, ReplicaVariableOrderInputField, ReplicaVariableScalarInputRef, ReplicaValue, ReplicaWatch, ReplicaWriteSource, WatchReplicaOptions } from './types.js';
20
+ export type { DistributedReplicaOptions, DistributedReplica, ReplicaArgumentsArtifact, ReplicaArgumentValue, ReplicaAuthoritativeScope, ReplicaBaseWriter, ReplicaBranchSemantic, ReplicaClientSurface, ReplicaCoverageArtifact, ReplicaDehydratedState, ReplicaFilterArtifact, ReplicaFilterExpression, ReplicaFilterFieldArtifact, ReplicaFilterLiteral, ReplicaFilterOperand, ReplicaFilterOperator, ReplicaIdentity, ReplicaIndexCoverage, ReplicaIndexInspection, ReplicaIndexTarget, ReplicaIslandMetadata, ReplicaIslandOperation, ReplicaListValue, ReplicaLiveObserver, ReplicaLiveState, ReplicaLiteralValue, ReplicaModelArtifact, ReplicaObjectBranch, ReplicaObjectMember, ReplicaObjectSelection, ReplicaObjectValue, ReplicaOperationArtifact, ReplicaOperationSourceLocation, ReplicaOperationProtocol, ReplicaOrderArtifact, ReplicaOrderFieldArtifact, ReplicaOrderTieBreakerArtifact, ReplicaOptimisticWriter, ReplicaPaginationArtifact, ReplicaPaginationDisposition, ReplicaProtocolOperationArtifact, ReplicaRecordInspection, ReplicaRecordPatch, ReplicaRevalidationPlan, ReplicaRevalidationRelationship, ReplicaRevision, ReplicaRelationshipArtifact, ReplicaRelationshipKeyMapping, ReplicaRelationshipKind, ReplicaResultEnvelope, ReplicaRowPolicyArtifact, ReplicaRootSelection, ReplicaScalarSelection, ReplicaSelectionStorage, ReplicaSparse, ReplicaSnapshot, ReplicaStatus, ReplicaTransport, ReplicaTransportRequest, ReplicaVariableValue, ReplicaVariableCodecArtifact, ReplicaVariableEnumInputRef, ReplicaVariableFilterInputDefinition, ReplicaVariableFilterInputField, ReplicaVariableFilterInputRelationship, ReplicaVariableFilterInputTarget, ReplicaVariableInputDefinition, ReplicaVariableInputRef, ReplicaVariableListInputRef, ReplicaVariableNamedInputRef, ReplicaVariableOrderInputDefinition, ReplicaVariableOrderInputField, ReplicaVariableScalarInputRef, ReplicaValue, ReplicaWatch, ReplicaWriteSource, WatchReplicaOptions } from './types.js';
21
21
  export { lowerMutationCache, MUTATION_CACHE_VISIBILITY_FULL, MUTATION_CACHE_VISIBILITY_UNAUTHORIZED, } from './mutation-cache.js';
22
22
  export type { MutationCacheEffect, MutationCacheProgram, MutationCacheVisibility, MutationField, MutationOperation, MutationProgram, MutationTarget, } from './mutation-cache.js';
@@ -444,6 +444,39 @@ export type ReplicaProtocolOperationArtifact<TData = Record<string, unknown>, TV
444
444
  readonly variableCodec: ReplicaVariableCodecArtifact;
445
445
  };
446
446
  export type ReplicaOperationArtifact<TData = Record<string, unknown>, TVariables extends GraphqlVariables = GraphqlVariables> = ReplicaProtocolOperationArtifact<TData, TVariables>;
447
+ /** Framework-neutral compiler metadata consumed by placement adapters. */
448
+ export type ReplicaIslandMetadata = {
449
+ readonly version: 1;
450
+ readonly id: string;
451
+ readonly operation: string;
452
+ readonly operationHash: string;
453
+ readonly modulePath: string;
454
+ readonly exportName: string;
455
+ readonly source: ReplicaOperationSourceLocation;
456
+ readonly directives: {
457
+ readonly load: boolean;
458
+ readonly live: boolean;
459
+ };
460
+ readonly variableSchema: {
461
+ readonly reference: string;
462
+ readonly codecVersion: number;
463
+ readonly variables: readonly {
464
+ readonly name: string;
465
+ readonly graphqlType: string;
466
+ }[];
467
+ };
468
+ readonly liveCoverage: {
469
+ readonly requested: boolean;
470
+ readonly finite: boolean;
471
+ readonly kind: string;
472
+ readonly maxItems?: number;
473
+ };
474
+ };
475
+ /** One adapter-consumable island plan bound to its executable operation. */
476
+ export type ReplicaIslandOperation<TData = Record<string, unknown>, TVariables extends GraphqlVariables = GraphqlVariables> = {
477
+ readonly plan: ReplicaIslandMetadata;
478
+ readonly artifact: ReplicaOperationArtifact<TData, TVariables>;
479
+ };
447
480
  export type ReplicaWriteSource = 'network' | 'live' | 'ssr' | 'restore' | 'atomic';
448
481
  export type ReplicaResultEnvelope<TData = unknown> = {
449
482
  readonly data?: TData | null;
@@ -532,6 +565,11 @@ export type WatchReplicaOptions = {
532
565
  export type DistributedReplicaOptions = {
533
566
  readonly transport?: ReplicaTransport;
534
567
  readonly onObserverError?: (error: AggregateError) => void;
568
+ /**
569
+ * Runs after the old generation is fenced and before its transports/state
570
+ * are purged. Framework adapters use this to release generation-owned views.
571
+ */
572
+ readonly onAuthorizationGenerationDispose?: () => void;
535
573
  /** Opt-in framework-neutral diagnostics; absent in production by default. */
536
574
  readonly diagnostics?: ReplicaDiagnosticsSink;
537
575
  };
@@ -0,0 +1,37 @@
1
+ import type { DistributedReplica } from '../replica/index.js';
2
+ import type { DistributedBoundaryOperation, DistributedBoundaryVariableContext } from './boundary-variables.js';
3
+ export type DistributedSvelteKitBoundaryInstance = Readonly<{
4
+ /** Opaque identity for one mounted SvelteKit page or layout instance. */
5
+ id: string;
6
+ route: string;
7
+ kind: 'layout' | 'page';
8
+ }>;
9
+ export type DistributedSvelteKitBoundaryLocation = Readonly<{
10
+ /** Opaque identity for one mounted page or layout instance. */
11
+ id: string;
12
+ pathname: string;
13
+ kind: 'layout' | 'page';
14
+ }>;
15
+ export type DistributedSvelteKitLocationContext<TSession = unknown, TProps = Readonly<Record<string, unknown>>> = Omit<DistributedBoundaryVariableContext<TSession, TProps>, 'params'>;
16
+ export type SveltekitBoundaryLifecycleDiagnostic = Readonly<{
17
+ action: 'acquire' | 'retain' | 'release' | 'scope-dispose' | 'final-unsubscribe';
18
+ boundary: string;
19
+ operation?: string;
20
+ live?: boolean;
21
+ owners: number;
22
+ }>;
23
+ export type SveltekitBoundaryRetention = Readonly<{
24
+ release(): void;
25
+ }>;
26
+ export declare class DistributedSvelteKitBoundaryController {
27
+ #private;
28
+ constructor(replica: DistributedReplica, operations: readonly DistributedBoundaryOperation[], diagnostic?: (event: SveltekitBoundaryLifecycleDiagnostic) => void);
29
+ retain<TSession, TProps>(instance: DistributedSvelteKitBoundaryInstance, context: DistributedBoundaryVariableContext<TSession, TProps>): SveltekitBoundaryRetention;
30
+ /** Retain the nearest generated page/layout boundary at a browser location. */
31
+ retainLocation<TSession, TProps>(location: DistributedSvelteKitBoundaryLocation, context: DistributedSvelteKitLocationContext<TSession, TProps>): SveltekitBoundaryRetention;
32
+ /** Warm every generated page and owning layout selection for one target URL. */
33
+ prefetchLocation<TSession, TProps>(pathname: string, context: DistributedSvelteKitLocationContext<TSession, TProps>): Promise<void>;
34
+ /** Close every old-scope owner while keeping the controller reusable. */
35
+ disposeScope(): void;
36
+ destroy(): void;
37
+ }