@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.
Files changed (242) hide show
  1. package/README.md +454 -0
  2. package/dist/auth-headers.d.ts +8 -0
  3. package/dist/auth-headers.js +35 -0
  4. package/dist/diagnostics.d.ts +2 -0
  5. package/dist/diagnostics.js +1 -0
  6. package/dist/document.d.ts +8 -0
  7. package/dist/document.js +6 -0
  8. package/dist/identity.d.ts +23 -0
  9. package/dist/identity.js +73 -0
  10. package/dist/index.d.ts +7 -0
  11. package/dist/index.js +6 -0
  12. package/dist/internal/cache-engine/create.d.ts +5 -0
  13. package/dist/internal/cache-engine/create.js +7 -0
  14. package/dist/internal/cache-engine/engine.d.ts +32 -0
  15. package/dist/internal/cache-engine/engine.js +1287 -0
  16. package/dist/internal/cache-engine/errors.d.ts +5 -0
  17. package/dist/internal/cache-engine/errors.js +10 -0
  18. package/dist/internal/cache-engine/helpers.d.ts +55 -0
  19. package/dist/internal/cache-engine/helpers.js +545 -0
  20. package/dist/internal/cache-engine/index.d.ts +3 -0
  21. package/dist/internal/cache-engine/index.js +2 -0
  22. package/dist/internal/cache-engine/types.d.ts +300 -0
  23. package/dist/internal/cache-engine/types.js +1 -0
  24. package/dist/internal/cache-engine.d.ts +3 -0
  25. package/dist/internal/cache-engine.js +2 -0
  26. package/dist/lib/assert-name.d.ts +2 -0
  27. package/dist/lib/assert-name.js +6 -0
  28. package/dist/lib/compare-code-units.d.ts +2 -0
  29. package/dist/lib/compare-code-units.js +4 -0
  30. package/dist/lib/deep-equal.d.ts +2 -0
  31. package/dist/lib/deep-equal.js +24 -0
  32. package/dist/lib/freeze-record.d.ts +2 -0
  33. package/dist/lib/freeze-record.js +13 -0
  34. package/dist/lib/index.d.ts +6 -0
  35. package/dist/lib/index.js +6 -0
  36. package/dist/lib/is-plain-record.d.ts +2 -0
  37. package/dist/lib/is-plain-record.js +8 -0
  38. package/dist/lib/report.d.ts +7 -0
  39. package/dist/lib/report.js +26 -0
  40. package/dist/protocol.d.ts +179 -0
  41. package/dist/protocol.js +558 -0
  42. package/dist/react/context.d.ts +20 -0
  43. package/dist/react/context.js +24 -0
  44. package/dist/react/index.d.ts +2 -0
  45. package/dist/react/index.js +3 -0
  46. package/dist/react/query.d.ts +20 -0
  47. package/dist/react/query.js +99 -0
  48. package/dist/replica/command-id.d.ts +2 -0
  49. package/dist/replica/command-id.js +19 -0
  50. package/dist/replica/command-runtime/constants.d.ts +5 -0
  51. package/dist/replica/command-runtime/constants.js +5 -0
  52. package/dist/replica/command-runtime/create.d.ts +2 -0
  53. package/dist/replica/command-runtime/create.js +644 -0
  54. package/dist/replica/command-runtime/errors.d.ts +16 -0
  55. package/dist/replica/command-runtime/errors.js +41 -0
  56. package/dist/replica/command-runtime/index.d.ts +5 -0
  57. package/dist/replica/command-runtime/index.js +4 -0
  58. package/dist/replica/command-runtime/lib/binding.d.ts +4 -0
  59. package/dist/replica/command-runtime/lib/binding.js +64 -0
  60. package/dist/replica/command-runtime/lib/effects.d.ts +11 -0
  61. package/dist/replica/command-runtime/lib/effects.js +89 -0
  62. package/dist/replica/command-runtime/lib/index.d.ts +9 -0
  63. package/dist/replica/command-runtime/lib/index.js +9 -0
  64. package/dist/replica/command-runtime/lib/inventory.d.ts +10 -0
  65. package/dist/replica/command-runtime/lib/inventory.js +141 -0
  66. package/dist/replica/command-runtime/lib/output.d.ts +13 -0
  67. package/dist/replica/command-runtime/lib/output.js +190 -0
  68. package/dist/replica/command-runtime/lib/projection.d.ts +20 -0
  69. package/dist/replica/command-runtime/lib/projection.js +255 -0
  70. package/dist/replica/command-runtime/lib/status.d.ts +7 -0
  71. package/dist/replica/command-runtime/lib/status.js +127 -0
  72. package/dist/replica/command-runtime/lib/transport.d.ts +16 -0
  73. package/dist/replica/command-runtime/lib/transport.js +112 -0
  74. package/dist/replica/command-runtime/lib/util.d.ts +16 -0
  75. package/dist/replica/command-runtime/lib/util.js +127 -0
  76. package/dist/replica/command-runtime/lifecycle.d.ts +11 -0
  77. package/dist/replica/command-runtime/lifecycle.js +13 -0
  78. package/dist/replica/command-runtime/symbols.d.ts +30 -0
  79. package/dist/replica/command-runtime/symbols.js +30 -0
  80. package/dist/replica/command-runtime/types.d.ts +222 -0
  81. package/dist/replica/command-runtime/types.js +1 -0
  82. package/dist/replica/command-runtime.d.ts +3 -0
  83. package/dist/replica/command-runtime.js +2 -0
  84. package/dist/replica/commands/clone.d.ts +12 -0
  85. package/dist/replica/commands/clone.js +187 -0
  86. package/dist/replica/commands/constants.d.ts +6 -0
  87. package/dist/replica/commands/constants.js +6 -0
  88. package/dist/replica/commands/errors.d.ts +7 -0
  89. package/dist/replica/commands/errors.js +22 -0
  90. package/dist/replica/commands/implementation.d.ts +8 -0
  91. package/dist/replica/commands/implementation.js +8 -0
  92. package/dist/replica/commands/index.d.ts +5 -0
  93. package/dist/replica/commands/index.js +4 -0
  94. package/dist/replica/commands/prepare.d.ts +27 -0
  95. package/dist/replica/commands/prepare.js +77 -0
  96. package/dist/replica/commands/presets.d.ts +12 -0
  97. package/dist/replica/commands/presets.js +84 -0
  98. package/dist/replica/commands/receipt.d.ts +3 -0
  99. package/dist/replica/commands/receipt.js +36 -0
  100. package/dist/replica/commands/resolve.d.ts +11 -0
  101. package/dist/replica/commands/resolve.js +165 -0
  102. package/dist/replica/commands/types.d.ts +278 -0
  103. package/dist/replica/commands/types.js +2 -0
  104. package/dist/replica/commands/util.d.ts +21 -0
  105. package/dist/replica/commands/util.js +96 -0
  106. package/dist/replica/commands/validate.d.ts +18 -0
  107. package/dist/replica/commands/validate.js +477 -0
  108. package/dist/replica/commands.d.ts +3 -0
  109. package/dist/replica/commands.js +2 -0
  110. package/dist/replica/diagnostics/event-log.d.ts +4 -0
  111. package/dist/replica/diagnostics/event-log.js +463 -0
  112. package/dist/replica/diagnostics/implementation.d.ts +4 -0
  113. package/dist/replica/diagnostics/implementation.js +4 -0
  114. package/dist/replica/diagnostics/index.d.ts +2 -0
  115. package/dist/replica/diagnostics/index.js +1 -0
  116. package/dist/replica/diagnostics/inspect.d.ts +6 -0
  117. package/dist/replica/diagnostics/inspect.js +170 -0
  118. package/dist/replica/diagnostics/types.d.ts +295 -0
  119. package/dist/replica/diagnostics/types.js +2 -0
  120. package/dist/replica/diagnostics.d.ts +3 -0
  121. package/dist/replica/diagnostics.js +2 -0
  122. package/dist/replica/distributed-replica/clocks.d.ts +23 -0
  123. package/dist/replica/distributed-replica/clocks.js +156 -0
  124. package/dist/replica/distributed-replica/constants.d.ts +12 -0
  125. package/dist/replica/distributed-replica/constants.js +10 -0
  126. package/dist/replica/distributed-replica/helpers.d.ts +48 -0
  127. package/dist/replica/distributed-replica/helpers.js +445 -0
  128. package/dist/replica/distributed-replica/hydration.d.ts +19 -0
  129. package/dist/replica/distributed-replica/hydration.js +380 -0
  130. package/dist/replica/distributed-replica/impl-diagnostics.d.ts +22 -0
  131. package/dist/replica/distributed-replica/impl-diagnostics.js +189 -0
  132. package/dist/replica/distributed-replica/impl-fetch-live.d.ts +39 -0
  133. package/dist/replica/distributed-replica/impl-fetch-live.js +395 -0
  134. package/dist/replica/distributed-replica/impl-hydration-orchestrate.d.ts +56 -0
  135. package/dist/replica/distributed-replica/impl-hydration-orchestrate.js +299 -0
  136. package/dist/replica/distributed-replica/impl-optimistic.d.ts +31 -0
  137. package/dist/replica/distributed-replica/impl-optimistic.js +172 -0
  138. package/dist/replica/distributed-replica/impl-protocol.d.ts +53 -0
  139. package/dist/replica/distributed-replica/impl-protocol.js +108 -0
  140. package/dist/replica/distributed-replica/impl.d.ts +44 -0
  141. package/dist/replica/distributed-replica/impl.js +1776 -0
  142. package/dist/replica/distributed-replica/index.d.ts +2 -0
  143. package/dist/replica/distributed-replica/index.js +4 -0
  144. package/dist/replica/distributed-replica/optimistic.d.ts +30 -0
  145. package/dist/replica/distributed-replica/optimistic.js +221 -0
  146. package/dist/replica/distributed-replica/types.d.ts +147 -0
  147. package/dist/replica/distributed-replica/types.js +1 -0
  148. package/dist/replica/distributed-replica/watch.d.ts +19 -0
  149. package/dist/replica/distributed-replica/watch.js +95 -0
  150. package/dist/replica/distributed-replica.d.ts +2 -0
  151. package/dist/replica/distributed-replica.js +2 -0
  152. package/dist/replica/graphql-transport.d.ts +24 -0
  153. package/dist/replica/graphql-transport.js +122 -0
  154. package/dist/replica/identity/clone.d.ts +6 -0
  155. package/dist/replica/identity/clone.js +54 -0
  156. package/dist/replica/identity/codec.d.ts +48 -0
  157. package/dist/replica/identity/codec.js +789 -0
  158. package/dist/replica/identity/constants.d.ts +3 -0
  159. package/dist/replica/identity/constants.js +18 -0
  160. package/dist/replica/identity/implementation.d.ts +5 -0
  161. package/dist/replica/identity/implementation.js +5 -0
  162. package/dist/replica/identity/index.d.ts +3 -0
  163. package/dist/replica/identity/index.js +3 -0
  164. package/dist/replica/identity/keys.d.ts +29 -0
  165. package/dist/replica/identity/keys.js +173 -0
  166. package/dist/replica/identity.d.ts +2 -0
  167. package/dist/replica/identity.js +2 -0
  168. package/dist/replica/index-maintenance/engine.d.ts +84 -0
  169. package/dist/replica/index-maintenance/engine.js +677 -0
  170. package/dist/replica/index-maintenance/implementation.d.ts +4 -0
  171. package/dist/replica/index-maintenance/implementation.js +4 -0
  172. package/dist/replica/index-maintenance/index.d.ts +2 -0
  173. package/dist/replica/index-maintenance/index.js +1 -0
  174. package/dist/replica/index-maintenance/registry.d.ts +2 -0
  175. package/dist/replica/index-maintenance/registry.js +49 -0
  176. package/dist/replica/index-maintenance/types.d.ts +58 -0
  177. package/dist/replica/index-maintenance/types.js +1 -0
  178. package/dist/replica/index-maintenance.d.ts +3 -0
  179. package/dist/replica/index-maintenance.js +2 -0
  180. package/dist/replica/index.d.ts +17 -0
  181. package/dist/replica/index.js +9 -0
  182. package/dist/replica/materialize.d.ts +10 -0
  183. package/dist/replica/materialize.js +163 -0
  184. package/dist/replica/normalize.d.ts +27 -0
  185. package/dist/replica/normalize.js +298 -0
  186. package/dist/replica/operation-binding.d.ts +14 -0
  187. package/dist/replica/operation-binding.js +76 -0
  188. package/dist/replica/persistence/idb.d.ts +20 -0
  189. package/dist/replica/persistence/idb.js +193 -0
  190. package/dist/replica/persistence/implementation.d.ts +4 -0
  191. package/dist/replica/persistence/implementation.js +4 -0
  192. package/dist/replica/persistence/index.d.ts +2 -0
  193. package/dist/replica/persistence/index.js +1 -0
  194. package/dist/replica/persistence/state.d.ts +104 -0
  195. package/dist/replica/persistence/state.js +734 -0
  196. package/dist/replica/persistence/types.d.ts +54 -0
  197. package/dist/replica/persistence/types.js +1 -0
  198. package/dist/replica/persistence.d.ts +3 -0
  199. package/dist/replica/persistence.js +2 -0
  200. package/dist/replica/query-plan/constants.d.ts +13 -0
  201. package/dist/replica/query-plan/constants.js +7 -0
  202. package/dist/replica/query-plan/filter.d.ts +39 -0
  203. package/dist/replica/query-plan/filter.js +544 -0
  204. package/dist/replica/query-plan/index.d.ts +4 -0
  205. package/dist/replica/query-plan/index.js +3 -0
  206. package/dist/replica/query-plan/order.d.ts +11 -0
  207. package/dist/replica/query-plan/order.js +158 -0
  208. package/dist/replica/query-plan/pagination.d.ts +6 -0
  209. package/dist/replica/query-plan/pagination.js +90 -0
  210. package/dist/replica/query-plan/resolve.d.ts +14 -0
  211. package/dist/replica/query-plan/resolve.js +163 -0
  212. package/dist/replica/query-plan/types.d.ts +89 -0
  213. package/dist/replica/query-plan/types.js +1 -0
  214. package/dist/replica/query-plan/util.d.ts +13 -0
  215. package/dist/replica/query-plan/util.js +62 -0
  216. package/dist/replica/query-plan.d.ts +3 -0
  217. package/dist/replica/query-plan.js +2 -0
  218. package/dist/replica/revalidation.d.ts +9 -0
  219. package/dist/replica/revalidation.js +86 -0
  220. package/dist/replica/selection.d.ts +20 -0
  221. package/dist/replica/selection.js +109 -0
  222. package/dist/replica/types.d.ts +657 -0
  223. package/dist/replica/types.js +1 -0
  224. package/dist/request.d.ts +17 -0
  225. package/dist/request.js +123 -0
  226. package/dist/sveltekit/auth.d.ts +18 -0
  227. package/dist/sveltekit/auth.js +9 -0
  228. package/dist/sveltekit/context.d.ts +28 -0
  229. package/dist/sveltekit/context.js +58 -0
  230. package/dist/sveltekit/index.d.ts +4 -0
  231. package/dist/sveltekit/index.js +4 -0
  232. package/dist/sveltekit/replica.d.ts +145 -0
  233. package/dist/sveltekit/replica.js +491 -0
  234. package/dist/sveltekit/server-replica.d.ts +52 -0
  235. package/dist/sveltekit/server-replica.js +176 -0
  236. package/dist/sveltekit/vite.d.ts +103 -0
  237. package/dist/sveltekit/vite.js +878 -0
  238. package/dist/types.d.ts +33 -0
  239. package/dist/types.js +1 -0
  240. package/dist/websocket.d.ts +41 -0
  241. package/dist/websocket.js +187 -0
  242. package/package.json +95 -0
@@ -0,0 +1,491 @@
1
+ import { sameAuthCredential, snapshotAuthCredential } from '../identity.js';
2
+ import { createDistributedReplica, createReplicaGraphqlTransport } from '../replica/index.js';
3
+ import { replicaCommandProjectedLifecycleOf } from '../replica/command-runtime.js';
4
+ import { authFromPageData } from './auth.js';
5
+ /**
6
+ * Bind the framework-neutral replica to Svelte's readable-store lifecycle.
7
+ *
8
+ * Generated `$distributed` modules call this once, then export
9
+ * `client.operation(Operation_Todos)` and `client.commands`.
10
+ */
11
+ export function createDistributedSvelteKit(options) {
12
+ if (options.session === null ||
13
+ typeof options.session !== 'object' ||
14
+ typeof options.session.getAuth !== 'function') {
15
+ throw new TypeError('Distributed SvelteKit requires one session source');
16
+ }
17
+ if ((options.hydration === undefined) !==
18
+ (options.authority === undefined)) {
19
+ throw new TypeError('Distributed SvelteKit hydration requires separate trusted SSR authority');
20
+ }
21
+ let replica;
22
+ const auth = createAuthorizationFence(options.session, () => replica?.invalidateAuthorization(), options.onAuthError);
23
+ const configuredUrl = options.url;
24
+ const transport = createReplicaGraphqlTransport({
25
+ getUrl: typeof configuredUrl === 'function'
26
+ ? configuredUrl
27
+ : () => configuredUrl ?? '/graphql',
28
+ getAuth: auth.read,
29
+ ...(options.fetch === undefined ? {} : { fetch: options.fetch }),
30
+ ...(options.webSocket === undefined
31
+ ? {}
32
+ : { webSocket: options.webSocket })
33
+ });
34
+ replica = createDistributedReplica({
35
+ transport,
36
+ ...(options.replica ?? {})
37
+ });
38
+ const stores = new Set();
39
+ const pending = new PendingReceiptStore();
40
+ let destroyed = false;
41
+ const hydrate = (hydration, authority) => {
42
+ let accepted = false;
43
+ try {
44
+ const expected = validatedHydrationAuthority(authority);
45
+ const active = replica.scope;
46
+ if (active !== undefined && !sameReplicaScope(active, expected)) {
47
+ throw new TypeError('Distributed SvelteKit hydration authority changed before session invalidation');
48
+ }
49
+ accepted =
50
+ hydration?.version === 1 &&
51
+ replica.hydrate(hydration.state, expected);
52
+ }
53
+ catch {
54
+ accepted = false;
55
+ }
56
+ if (!accepted)
57
+ replica.invalidateAuthorization();
58
+ return accepted;
59
+ };
60
+ if (options.hydration !== undefined && options.authority !== undefined) {
61
+ hydrate(options.hydration, options.authority);
62
+ }
63
+ // Hydration must precede command authority registration: trusted presets are
64
+ // server-derived and restored only as part of an exact authoritative seed.
65
+ const commandRuntime = options.createCommands?.(replica, transport, Object.freeze({
66
+ ...(options.replica?.diagnostics === undefined
67
+ ? {}
68
+ : { diagnostics: options.replica.diagnostics })
69
+ }));
70
+ const commands = commandRuntime === undefined
71
+ ? Object.freeze({})
72
+ : wrapCommandTree(commandRuntime.commands, pending);
73
+ const operation = (artifact) => bindOperation(replica, artifact, pending, {
74
+ isAlive: () => !destroyed,
75
+ activateWatches: () => options.browser ?? true,
76
+ active: (store) => {
77
+ stores.add(store);
78
+ },
79
+ idle: (store) => {
80
+ stores.delete(store);
81
+ }
82
+ });
83
+ return Object.freeze({
84
+ replica,
85
+ transport,
86
+ commands,
87
+ operation,
88
+ hydrate,
89
+ invalidateAuthorization() {
90
+ if (!destroyed)
91
+ replica.invalidateAuthorization();
92
+ },
93
+ destroy() {
94
+ if (destroyed)
95
+ return;
96
+ destroyed = true;
97
+ auth.dispose();
98
+ for (const store of [...stores])
99
+ store.destroy();
100
+ stores.clear();
101
+ pending.clear();
102
+ commandRuntime?.dispose();
103
+ }
104
+ });
105
+ }
106
+ /**
107
+ * Low-level composition seam for applications that already own a replica.
108
+ *
109
+ * Most SvelteKit applications use `createDistributedSvelteKit().operation()`;
110
+ * this form exists for custom composition and framework adapter conformance.
111
+ */
112
+ export function bindSveltekitOperation(replica, artifact) {
113
+ return bindOperation(replica, artifact, new PendingReceiptStore(), {
114
+ isAlive: () => true,
115
+ activateWatches: () => true,
116
+ active: () => undefined,
117
+ idle: () => undefined
118
+ });
119
+ }
120
+ /** Map SvelteKit page data into the one shared transport/session source. */
121
+ export function sessionSourceFromPageData(source) {
122
+ if (source === null ||
123
+ typeof source !== 'object' ||
124
+ typeof source.get !== 'function') {
125
+ throw new TypeError('page-data session source requires get');
126
+ }
127
+ return Object.freeze({
128
+ getAuth: () => authFromPageData(source.get()),
129
+ ...(source.subscribe === undefined
130
+ ? {}
131
+ : { subscribe: source.subscribe.bind(source) })
132
+ });
133
+ }
134
+ /**
135
+ * Create the single mutable page-data/session source owned by one layout.
136
+ *
137
+ * HTTP, WebSocket reconnects, commands, and authorization invalidation all
138
+ * observe `session`; navigation updates the same source through `set`.
139
+ */
140
+ export function createPageDataSessionSource(initial) {
141
+ let current = initial;
142
+ const listeners = new Set();
143
+ const source = Object.freeze({
144
+ get() {
145
+ return current;
146
+ },
147
+ subscribe(listener) {
148
+ listeners.add(listener);
149
+ return () => listeners.delete(listener);
150
+ }
151
+ });
152
+ return Object.freeze({
153
+ session: sessionSourceFromPageData(source),
154
+ get: source.get,
155
+ set(next) {
156
+ current = next;
157
+ for (const listener of [...listeners])
158
+ listener();
159
+ }
160
+ });
161
+ }
162
+ function bindOperation(replica, artifact, pending, lifecycle) {
163
+ const use = (...args) => {
164
+ const variables = (args[0] ?? {});
165
+ const useOptions = args[1];
166
+ const store = new SveltekitQueryStoreImpl(replica, artifact, variables, Object.freeze({
167
+ live: useOptions?.live ?? artifact.live !== undefined
168
+ }), pending, lifecycle);
169
+ return store;
170
+ };
171
+ return Object.freeze({
172
+ artifact,
173
+ use,
174
+ read: (variables) => replica.read(artifact, variables)
175
+ });
176
+ }
177
+ class SveltekitQueryStoreImpl {
178
+ #replica;
179
+ #artifact;
180
+ #variables;
181
+ #options;
182
+ #pending;
183
+ #lifecycle;
184
+ #listeners = new Set();
185
+ #watch;
186
+ #unsubscribeWatch;
187
+ #unsubscribePending;
188
+ #snapshot;
189
+ #destroyed = false;
190
+ constructor(replica, artifact, variables, options, pending, lifecycle) {
191
+ this.#replica = replica;
192
+ this.#artifact = artifact;
193
+ this.#variables = variables;
194
+ this.#options = options;
195
+ this.#pending = pending;
196
+ this.#lifecycle = lifecycle;
197
+ this.#snapshot = querySnapshot(replica.read(artifact, variables), pending.get(), () => this.refetch());
198
+ }
199
+ get() {
200
+ if (!this.#destroyed && this.#watch === undefined) {
201
+ this.#snapshot = querySnapshot(this.#replica.read(this.#artifact, this.#variables), this.#pending.get(), () => this.refetch());
202
+ }
203
+ return this.#snapshot;
204
+ }
205
+ subscribe(listener) {
206
+ if (this.#destroyed) {
207
+ throw new Error('Distributed SvelteKit query is destroyed');
208
+ }
209
+ if (typeof listener !== 'function') {
210
+ throw new TypeError('Distributed SvelteKit query listener must be a function');
211
+ }
212
+ if (!this.#lifecycle.isAlive()) {
213
+ throw new Error('Distributed SvelteKit client is destroyed');
214
+ }
215
+ if (this.#listeners.size === 0 &&
216
+ this.#lifecycle.activateWatches()) {
217
+ this.#activate();
218
+ }
219
+ this.#listeners.add(listener);
220
+ listener(this.#snapshot);
221
+ let active = true;
222
+ return () => {
223
+ if (!active)
224
+ return;
225
+ active = false;
226
+ this.#listeners.delete(listener);
227
+ if (this.#listeners.size === 0)
228
+ this.#deactivate();
229
+ };
230
+ }
231
+ async refetch() {
232
+ if (this.#destroyed) {
233
+ throw new Error('Distributed SvelteKit query is destroyed');
234
+ }
235
+ if (!this.#lifecycle.isAlive()) {
236
+ throw new Error('Distributed SvelteKit client is destroyed');
237
+ }
238
+ if (this.#watch !== undefined) {
239
+ await this.#watch.refresh();
240
+ return;
241
+ }
242
+ const temporary = this.#replica.watch(this.#artifact, this.#variables, { ...this.#options, live: false });
243
+ try {
244
+ await temporary.refresh();
245
+ this.#snapshot = querySnapshot(temporary.get(), this.#pending.get(), () => this.refetch());
246
+ }
247
+ finally {
248
+ temporary.destroy();
249
+ }
250
+ }
251
+ destroy() {
252
+ if (this.#destroyed)
253
+ return;
254
+ this.#destroyed = true;
255
+ this.#deactivate();
256
+ this.#listeners.clear();
257
+ }
258
+ get data() {
259
+ return this.#snapshot.data;
260
+ }
261
+ get status() {
262
+ return this.#snapshot.status;
263
+ }
264
+ get complete() {
265
+ return this.#snapshot.complete;
266
+ }
267
+ get loading() {
268
+ return this.#snapshot.loading;
269
+ }
270
+ get fetching() {
271
+ return this.#snapshot.fetching;
272
+ }
273
+ get stale() {
274
+ return this.#snapshot.stale;
275
+ }
276
+ get live() {
277
+ return this.#snapshot.live;
278
+ }
279
+ get errors() {
280
+ return this.#snapshot.errors;
281
+ }
282
+ get error() {
283
+ return this.#snapshot.error;
284
+ }
285
+ get pending() {
286
+ return this.#snapshot.pending;
287
+ }
288
+ #activate() {
289
+ let watch;
290
+ try {
291
+ watch = this.#replica.watch(this.#artifact, this.#variables, this.#options);
292
+ this.#watch = watch;
293
+ this.#snapshot = querySnapshot(watch.get(), this.#pending.get(), () => this.refetch());
294
+ this.#unsubscribeWatch = watch.subscribe((snapshot) => {
295
+ this.#publish(snapshot, this.#pending.get());
296
+ });
297
+ this.#unsubscribePending = this.#pending.subscribe((receipts) => {
298
+ const current = this.#watch;
299
+ if (current !== undefined)
300
+ this.#publish(current.get(), receipts);
301
+ });
302
+ this.#lifecycle.active(this);
303
+ }
304
+ catch (error) {
305
+ this.#unsubscribeWatch?.();
306
+ this.#unsubscribePending?.();
307
+ watch?.destroy();
308
+ this.#watch = undefined;
309
+ this.#unsubscribeWatch = undefined;
310
+ this.#unsubscribePending = undefined;
311
+ throw error;
312
+ }
313
+ }
314
+ #deactivate() {
315
+ if (this.#watch === undefined)
316
+ return;
317
+ this.#unsubscribeWatch?.();
318
+ this.#unsubscribePending?.();
319
+ this.#watch.destroy();
320
+ this.#watch = undefined;
321
+ this.#unsubscribeWatch = undefined;
322
+ this.#unsubscribePending = undefined;
323
+ this.#lifecycle.idle(this);
324
+ }
325
+ #publish(replicaSnapshot, receipts) {
326
+ if (this.#destroyed)
327
+ return;
328
+ const next = querySnapshot(replicaSnapshot, receipts, () => this.refetch());
329
+ if (sameQuerySnapshot(this.#snapshot, next))
330
+ return;
331
+ this.#snapshot = next;
332
+ for (const listener of [...this.#listeners])
333
+ listener(next);
334
+ }
335
+ }
336
+ class PendingReceiptStore {
337
+ #receipts = new Map();
338
+ #listeners = new Set();
339
+ #snapshot = Object.freeze([]);
340
+ get() {
341
+ return this.#snapshot;
342
+ }
343
+ subscribe(listener) {
344
+ this.#listeners.add(listener);
345
+ return () => this.#listeners.delete(listener);
346
+ }
347
+ track(receipt) {
348
+ const lifecycle = replicaCommandProjectedLifecycleOf(receipt) ?? receipt.projected;
349
+ if (lifecycle === undefined || this.#receipts.has(receipt.commandId)) {
350
+ return;
351
+ }
352
+ this.#receipts.set(receipt.commandId, receipt);
353
+ this.#publish();
354
+ void lifecycle.then(() => this.#remove(receipt.commandId), () => this.#remove(receipt.commandId));
355
+ }
356
+ clear() {
357
+ if (this.#receipts.size === 0)
358
+ return;
359
+ this.#receipts.clear();
360
+ this.#publish();
361
+ this.#listeners.clear();
362
+ }
363
+ #remove(commandId) {
364
+ if (!this.#receipts.delete(commandId))
365
+ return;
366
+ this.#publish();
367
+ }
368
+ #publish() {
369
+ this.#snapshot = Object.freeze([...this.#receipts.values()]);
370
+ for (const listener of [...this.#listeners])
371
+ listener(this.#snapshot);
372
+ }
373
+ }
374
+ function wrapCommandTree(value, pending) {
375
+ if (typeof value === 'function') {
376
+ const command = value;
377
+ return ((...args) => {
378
+ const result = command(...args);
379
+ if (isPromiseLike(result)) {
380
+ return result.then((receipt) => {
381
+ if (isCommandReceipt(receipt))
382
+ pending.track(receipt);
383
+ return receipt;
384
+ });
385
+ }
386
+ return result;
387
+ });
388
+ }
389
+ if (value === null || typeof value !== 'object')
390
+ return value;
391
+ const output = Object.create(null);
392
+ for (const key of Object.keys(value)) {
393
+ output[key] = wrapCommandTree(value[key], pending);
394
+ }
395
+ return Object.freeze(output);
396
+ }
397
+ function isCommandReceipt(value) {
398
+ return (value !== null &&
399
+ typeof value === 'object' &&
400
+ typeof value.commandId === 'string' &&
401
+ typeof value.status === 'function');
402
+ }
403
+ function isPromiseLike(value) {
404
+ return (value !== null &&
405
+ (typeof value === 'object' || typeof value === 'function') &&
406
+ typeof value.then === 'function');
407
+ }
408
+ function querySnapshot(snapshot, pending, refetch) {
409
+ return Object.freeze({
410
+ ...snapshot,
411
+ loading: snapshot.fetching || snapshot.status === 'loading',
412
+ ...(snapshot.errors[0] === undefined
413
+ ? {}
414
+ : { error: snapshot.errors[0] }),
415
+ pending,
416
+ refetch
417
+ });
418
+ }
419
+ function sameQuerySnapshot(left, right) {
420
+ return (left.data === right.data &&
421
+ left.status === right.status &&
422
+ left.complete === right.complete &&
423
+ left.loading === right.loading &&
424
+ left.fetching === right.fetching &&
425
+ left.stale === right.stale &&
426
+ left.live === right.live &&
427
+ left.errors === right.errors &&
428
+ left.pending === right.pending);
429
+ }
430
+ function createAuthorizationFence(source, invalidate, onError) {
431
+ let current;
432
+ let queue = Promise.resolve();
433
+ let disposed = false;
434
+ const read = () => {
435
+ const candidate = Promise.resolve().then(() => source.getAuth());
436
+ const transition = queue.then(async () => {
437
+ try {
438
+ const next = snapshotAuthCredential(await candidate);
439
+ if (current !== undefined &&
440
+ !sameAuthCredential(current, next)) {
441
+ invalidate();
442
+ }
443
+ current = next;
444
+ return next;
445
+ }
446
+ catch (error) {
447
+ current = undefined;
448
+ invalidate();
449
+ throw error;
450
+ }
451
+ });
452
+ queue = transition.then(() => undefined, () => undefined);
453
+ return transition;
454
+ };
455
+ const unsubscribe = source.subscribe?.(() => {
456
+ if (disposed)
457
+ return;
458
+ void read().catch((error) => onError?.(error));
459
+ });
460
+ // Snapshot the bind-time credential so a later first request can fence a
461
+ // token refresh that retained the same unverified JWT subject.
462
+ void read().catch((error) => onError?.(error));
463
+ return Object.freeze({
464
+ read,
465
+ dispose() {
466
+ if (disposed)
467
+ return;
468
+ disposed = true;
469
+ unsubscribe?.();
470
+ }
471
+ });
472
+ }
473
+ function validatedHydrationAuthority(value) {
474
+ const scope = value?.scope;
475
+ if (value?.version !== 1 ||
476
+ scope === null ||
477
+ typeof scope !== 'object' ||
478
+ scope.protocolVersion !== 1 ||
479
+ typeof scope.schemaHash !== 'string' ||
480
+ scope.schemaHash.length === 0 ||
481
+ typeof scope.cacheScope !== 'string' ||
482
+ scope.cacheScope.length === 0) {
483
+ throw new TypeError('Distributed SvelteKit hydration authority is invalid');
484
+ }
485
+ return scope;
486
+ }
487
+ function sameReplicaScope(left, right) {
488
+ return (left.protocolVersion === right.protocolVersion &&
489
+ left.schemaHash === right.schemaHash &&
490
+ left.cacheScope === right.cacheScope);
491
+ }
@@ -0,0 +1,52 @@
1
+ import { type ReplicaOperationArtifact } from '../replica/index.js';
2
+ import type { FetchLike } from '../request.js';
3
+ import type { GqlAuth, GraphqlVariables } from '../types.js';
4
+ import { type PageGraphqlData } from './auth.js';
5
+ import type { SveltekitDistributedPageData } from './replica.js';
6
+ export type DistributedRoutePlan = Readonly<{
7
+ operation: string;
8
+ route: string;
9
+ source_path?: string;
10
+ discovery: 'convention' | 'explicit';
11
+ }>;
12
+ export type DistributedRouteOperation = Readonly<{
13
+ plan: DistributedRoutePlan;
14
+ artifact: ReplicaOperationArtifact<unknown, GraphqlVariables>;
15
+ }>;
16
+ export type SveltekitServerLoadEventLike<TLocals = unknown> = Readonly<{
17
+ locals: TLocals;
18
+ route?: Readonly<{
19
+ id?: string | null;
20
+ }>;
21
+ url?: URL;
22
+ fetch?: FetchLike;
23
+ }>;
24
+ export type DistributedRouteVariables<TEvent extends SveltekitServerLoadEventLike> = Readonly<Record<string, (event: TEvent) => GraphqlVariables | Promise<GraphqlVariables>>>;
25
+ export type CreateDistributedSvelteKitServerOptions<TSession extends NonNullable<PageGraphqlData['session']>, TEvent extends SveltekitServerLoadEventLike = SveltekitServerLoadEventLike> = Readonly<{
26
+ routes: readonly DistributedRouteOperation[];
27
+ getSession(event: TEvent): Promise<TSession | null>;
28
+ getRole(session: TSession | null, event: TEvent): string | null | undefined;
29
+ getAuth?(pageData: PageGraphqlData, event: TEvent): GqlAuth;
30
+ /** Private API origin or same-origin `/graphql`; defaults to `/graphql`. */
31
+ getUrl?(event: TEvent): string;
32
+ /** Variables for routed operations that do not accept `{}`. */
33
+ variables?: DistributedRouteVariables<TEvent>;
34
+ }>;
35
+ export type DistributedSvelteKitServer<TEvent> = Readonly<{
36
+ load(event: TEvent): Promise<SveltekitDistributedPageData & {
37
+ gqlError: string | null;
38
+ }>;
39
+ }>;
40
+ /**
41
+ * One app-level root layout loader for every compiler-discovered `@load`
42
+ * operation. Each invocation creates a fresh replica and never shares SSR data
43
+ * across requests.
44
+ */
45
+ export declare function createDistributedSvelteKitServer<TSession extends NonNullable<PageGraphqlData['session']>, TEvent extends SveltekitServerLoadEventLike = SveltekitServerLoadEventLike>(options: CreateDistributedSvelteKitServerOptions<TSession, TEvent>): DistributedSvelteKitServer<TEvent>;
46
+ /**
47
+ * Explicit one-line fallback when the compiler cannot discover route ownership.
48
+ *
49
+ * Prefer co-locating `+page.graphql`; the compiler diagnostic includes the
50
+ * equivalent `--route Operation=/route-id` registration.
51
+ */
52
+ export declare function registerDistributedRoute<TData, TVariables extends GraphqlVariables>(route: string, operation: string, artifact: ReplicaOperationArtifact<TData, TVariables>): DistributedRouteOperation;