syncorejs 0.2.1 → 0.2.2

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 (135) hide show
  1. package/README.md +2 -1
  2. package/dist/_vendor/cli/app.d.mts.map +1 -1
  3. package/dist/_vendor/cli/app.mjs +323 -42
  4. package/dist/_vendor/cli/app.mjs.map +1 -1
  5. package/dist/_vendor/cli/context.mjs +27 -9
  6. package/dist/_vendor/cli/context.mjs.map +1 -1
  7. package/dist/_vendor/cli/doctor.mjs +513 -46
  8. package/dist/_vendor/cli/doctor.mjs.map +1 -1
  9. package/dist/_vendor/cli/messages.mjs +5 -4
  10. package/dist/_vendor/cli/messages.mjs.map +1 -1
  11. package/dist/_vendor/cli/project.mjs +110 -12
  12. package/dist/_vendor/cli/project.mjs.map +1 -1
  13. package/dist/_vendor/cli/render.mjs +57 -9
  14. package/dist/_vendor/cli/render.mjs.map +1 -1
  15. package/dist/_vendor/cli/targets.mjs +4 -3
  16. package/dist/_vendor/cli/targets.mjs.map +1 -1
  17. package/dist/_vendor/core/cli.d.mts +13 -3
  18. package/dist/_vendor/core/cli.d.mts.map +1 -1
  19. package/dist/_vendor/core/cli.mjs +242 -91
  20. package/dist/_vendor/core/cli.mjs.map +1 -1
  21. package/dist/_vendor/core/devtools-auth.mjs +60 -0
  22. package/dist/_vendor/core/devtools-auth.mjs.map +1 -0
  23. package/dist/_vendor/core/index.d.mts +5 -3
  24. package/dist/_vendor/core/index.mjs +22 -2
  25. package/dist/_vendor/core/index.mjs.map +1 -1
  26. package/dist/_vendor/core/runtime/components.d.mts +111 -0
  27. package/dist/_vendor/core/runtime/components.d.mts.map +1 -0
  28. package/dist/_vendor/core/runtime/components.mjs +186 -0
  29. package/dist/_vendor/core/runtime/components.mjs.map +1 -0
  30. package/dist/_vendor/core/runtime/devtools.d.mts +4 -4
  31. package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
  32. package/dist/_vendor/core/runtime/devtools.mjs +52 -41
  33. package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
  34. package/dist/_vendor/core/runtime/functions.d.mts +10 -10
  35. package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
  36. package/dist/_vendor/core/runtime/functions.mjs +2 -2
  37. package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
  38. package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +77 -0
  39. package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -0
  40. package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +617 -0
  41. package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -0
  42. package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +186 -0
  43. package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -0
  44. package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +220 -0
  45. package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -0
  46. package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +203 -0
  47. package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -0
  48. package/dist/_vendor/core/runtime/internal/engines/shared.mjs +177 -0
  49. package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -0
  50. package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +144 -0
  51. package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -0
  52. package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +220 -0
  53. package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -0
  54. package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs +32 -0
  55. package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -0
  56. package/dist/_vendor/core/runtime/internal/systemMeta.mjs +61 -0
  57. package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -0
  58. package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +37 -0
  59. package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -0
  60. package/dist/_vendor/core/runtime/runtime.d.mts +159 -205
  61. package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
  62. package/dist/_vendor/core/runtime/runtime.mjs +16 -1371
  63. package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
  64. package/dist/_vendor/core/transport.d.mts +111 -0
  65. package/dist/_vendor/core/transport.d.mts.map +1 -0
  66. package/dist/_vendor/core/transport.mjs +419 -0
  67. package/dist/_vendor/core/transport.mjs.map +1 -0
  68. package/dist/_vendor/devtools-protocol/index.d.ts +39 -1
  69. package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
  70. package/dist/_vendor/devtools-protocol/index.js +25 -9
  71. package/dist/_vendor/devtools-protocol/index.js.map +1 -1
  72. package/dist/_vendor/next/index.d.ts +1 -1
  73. package/dist/_vendor/next/index.d.ts.map +1 -1
  74. package/dist/_vendor/next/index.js +31 -13
  75. package/dist/_vendor/next/index.js.map +1 -1
  76. package/dist/_vendor/platform-expo/index.d.ts +12 -12
  77. package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
  78. package/dist/_vendor/platform-expo/index.js +4 -2
  79. package/dist/_vendor/platform-expo/index.js.map +1 -1
  80. package/dist/_vendor/platform-expo/react.d.ts.map +1 -1
  81. package/dist/_vendor/platform-expo/react.js +11 -10
  82. package/dist/_vendor/platform-expo/react.js.map +1 -1
  83. package/dist/_vendor/platform-node/index.d.mts +23 -19
  84. package/dist/_vendor/platform-node/index.d.mts.map +1 -1
  85. package/dist/_vendor/platform-node/index.mjs +13 -5
  86. package/dist/_vendor/platform-node/index.mjs.map +1 -1
  87. package/dist/_vendor/platform-node/ipc-react.d.mts.map +1 -1
  88. package/dist/_vendor/platform-node/ipc-react.mjs +15 -2
  89. package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
  90. package/dist/_vendor/platform-node/ipc.d.mts +11 -35
  91. package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
  92. package/dist/_vendor/platform-node/ipc.mjs +3 -273
  93. package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
  94. package/dist/_vendor/platform-web/external-change.d.ts +2 -1
  95. package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
  96. package/dist/_vendor/platform-web/external-change.js +2 -1
  97. package/dist/_vendor/platform-web/external-change.js.map +1 -1
  98. package/dist/_vendor/platform-web/index.d.ts +21 -21
  99. package/dist/_vendor/platform-web/index.d.ts.map +1 -1
  100. package/dist/_vendor/platform-web/index.js +44 -7
  101. package/dist/_vendor/platform-web/index.js.map +1 -1
  102. package/dist/_vendor/platform-web/react.d.ts.map +1 -1
  103. package/dist/_vendor/platform-web/react.js +29 -13
  104. package/dist/_vendor/platform-web/react.js.map +1 -1
  105. package/dist/_vendor/platform-web/worker.d.ts +11 -35
  106. package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
  107. package/dist/_vendor/platform-web/worker.js +3 -267
  108. package/dist/_vendor/platform-web/worker.js.map +1 -1
  109. package/dist/_vendor/react/index.d.ts +36 -20
  110. package/dist/_vendor/react/index.d.ts.map +1 -1
  111. package/dist/_vendor/react/index.js +279 -57
  112. package/dist/_vendor/react/index.js.map +1 -1
  113. package/dist/_vendor/schema/definition.d.ts +48 -63
  114. package/dist/_vendor/schema/definition.d.ts.map +1 -1
  115. package/dist/_vendor/schema/definition.js +22 -39
  116. package/dist/_vendor/schema/definition.js.map +1 -1
  117. package/dist/_vendor/schema/index.d.ts +4 -4
  118. package/dist/_vendor/schema/index.js +2 -2
  119. package/dist/_vendor/schema/planner.d.ts +19 -2
  120. package/dist/_vendor/schema/planner.d.ts.map +1 -1
  121. package/dist/_vendor/schema/planner.js +79 -3
  122. package/dist/_vendor/schema/planner.js.map +1 -1
  123. package/dist/_vendor/schema/validators.d.ts +141 -121
  124. package/dist/_vendor/schema/validators.d.ts.map +1 -1
  125. package/dist/_vendor/schema/validators.js +300 -42
  126. package/dist/_vendor/schema/validators.js.map +1 -1
  127. package/dist/_vendor/svelte/index.d.ts +47 -19
  128. package/dist/_vendor/svelte/index.d.ts.map +1 -1
  129. package/dist/_vendor/svelte/index.js +250 -20
  130. package/dist/_vendor/svelte/index.js.map +1 -1
  131. package/dist/components.d.ts +2 -0
  132. package/dist/components.js +2 -0
  133. package/dist/index.d.ts +3 -2
  134. package/dist/index.js +2 -1
  135. package/package.json +8 -3
@@ -1,137 +1,6 @@
1
- import { generateId } from "../core/index.mjs";
1
+ import { SyncoreBridgeClient, attachRuntimeBridge } from "../core/index.mjs";
2
2
  //#region src/worker.ts
3
- var SyncoreWebWorkerClient = class {
4
- pendingRequests = /* @__PURE__ */ new Map();
5
- watchRecordsByKey = /* @__PURE__ */ new Map();
6
- watchKeyBySubscriptionId = /* @__PURE__ */ new Map();
7
- disposed = false;
8
- handleMessage = (event) => {
9
- const message = event.data;
10
- if (!message || typeof message !== "object" || !("type" in message)) return;
11
- switch (message.type) {
12
- case "runtime.ready": return;
13
- case "runtime.error":
14
- this.rejectAllPending(new Error(message.error));
15
- return;
16
- case "invoke.result": {
17
- const pending = this.pendingRequests.get(message.requestId);
18
- if (!pending) return;
19
- this.pendingRequests.delete(message.requestId);
20
- if (message.success) pending.resolve(message.value);
21
- else pending.reject(new Error(message.error));
22
- return;
23
- }
24
- case "watch.update": {
25
- const watchKey = this.watchKeyBySubscriptionId.get(message.subscriptionId);
26
- if (!watchKey) return;
27
- const watchRecord = this.watchRecordsByKey.get(watchKey);
28
- if (!watchRecord) return;
29
- if (message.success) {
30
- watchRecord.result = message.value;
31
- watchRecord.error = void 0;
32
- } else watchRecord.error = new Error(message.error);
33
- for (const listener of watchRecord.listeners) listener();
34
- }
35
- }
36
- };
37
- constructor(endpoint) {
38
- this.endpoint = endpoint;
39
- this.endpoint.addEventListener("message", this.handleMessage);
40
- }
41
- query(reference, ...args) {
42
- return this.invoke("query", reference, normalizeOptionalArgs(args));
43
- }
44
- mutation(reference, ...args) {
45
- return this.invoke("mutation", reference, normalizeOptionalArgs(args));
46
- }
47
- action(reference, ...args) {
48
- return this.invoke("action", reference, normalizeOptionalArgs(args));
49
- }
50
- watchQuery(reference, ...args) {
51
- this.ensureNotDisposed();
52
- const normalizedArgs = normalizeOptionalArgs(args);
53
- const watchKey = createWatchKey(reference, normalizedArgs);
54
- let watchRecord = this.watchRecordsByKey.get(watchKey);
55
- if (!watchRecord) {
56
- watchRecord = {
57
- subscriptionId: generateId(),
58
- listeners: /* @__PURE__ */ new Set(),
59
- consumers: 0,
60
- result: void 0,
61
- error: void 0
62
- };
63
- this.watchRecordsByKey.set(watchKey, watchRecord);
64
- this.watchKeyBySubscriptionId.set(watchRecord.subscriptionId, watchKey);
65
- this.endpoint.postMessage({
66
- type: "watch.subscribe",
67
- subscriptionId: watchRecord.subscriptionId,
68
- reference,
69
- args: normalizedArgs
70
- });
71
- }
72
- watchRecord.consumers += 1;
73
- let disposed = false;
74
- const ownedListeners = /* @__PURE__ */ new Set();
75
- return {
76
- onUpdate: (callback) => {
77
- watchRecord.listeners.add(callback);
78
- ownedListeners.add(callback);
79
- queueMicrotask(callback);
80
- return () => {
81
- watchRecord.listeners.delete(callback);
82
- ownedListeners.delete(callback);
83
- };
84
- },
85
- localQueryResult: () => watchRecord.result,
86
- localQueryError: () => watchRecord.error,
87
- dispose: () => {
88
- if (disposed) return;
89
- disposed = true;
90
- for (const callback of ownedListeners) watchRecord.listeners.delete(callback);
91
- ownedListeners.clear();
92
- watchRecord.consumers = Math.max(0, watchRecord.consumers - 1);
93
- if (watchRecord.consumers > 0) return;
94
- this.endpoint.postMessage({
95
- type: "watch.unsubscribe",
96
- subscriptionId: watchRecord.subscriptionId
97
- });
98
- this.watchKeyBySubscriptionId.delete(watchRecord.subscriptionId);
99
- this.watchRecordsByKey.delete(watchKey);
100
- }
101
- };
102
- }
103
- dispose() {
104
- if (this.disposed) return;
105
- this.disposed = true;
106
- this.endpoint.removeEventListener("message", this.handleMessage);
107
- for (const watchRecord of this.watchRecordsByKey.values()) this.endpoint.postMessage({
108
- type: "watch.unsubscribe",
109
- subscriptionId: watchRecord.subscriptionId
110
- });
111
- this.watchKeyBySubscriptionId.clear();
112
- this.watchRecordsByKey.clear();
113
- this.rejectAllPending(/* @__PURE__ */ new Error("Syncore worker client was disposed."));
114
- }
115
- invoke(kind, reference, args) {
116
- this.ensureNotDisposed();
117
- const requestId = generateId();
118
- const promise = new Promise((resolve, reject) => {
119
- this.pendingRequests.set(requestId, {
120
- resolve,
121
- reject
122
- });
123
- });
124
- this.endpoint.postMessage(createInvokeRequest(requestId, kind, reference, args));
125
- return promise;
126
- }
127
- rejectAllPending(error) {
128
- for (const pending of this.pendingRequests.values()) pending.reject(error);
129
- this.pendingRequests.clear();
130
- }
131
- ensureNotDisposed() {
132
- if (this.disposed) throw new Error("Syncore worker client was disposed.");
133
- }
134
- };
3
+ var SyncoreWebWorkerClient = class extends SyncoreBridgeClient {};
135
4
  /**
136
5
  * Create a web worker Syncore client from a low-level message endpoint.
137
6
  */
@@ -166,140 +35,7 @@ function createSyncoreWebWorkerClient(options) {
166
35
  * Attach a Syncore runtime implementation to a worker message endpoint.
167
36
  */
168
37
  function attachWebWorkerRuntime(options) {
169
- const subscriptions = /* @__PURE__ */ new Map();
170
- const runtimePromise = Promise.resolve(options.createRuntime()).then(async (runtime) => {
171
- await runtime.start();
172
- return runtime;
173
- });
174
- const clientPromise = runtimePromise.then((runtime) => runtime.createClient());
175
- const ready = clientPromise.then(() => {
176
- options.endpoint.postMessage({ type: "runtime.ready" });
177
- }).catch((error) => {
178
- options.endpoint.postMessage({
179
- type: "runtime.error",
180
- error: error instanceof Error ? error.message : String(error)
181
- });
182
- throw error;
183
- });
184
- const handleMessage = (event) => {
185
- (async () => {
186
- const message = event.data;
187
- if (!message || typeof message !== "object" || !("type" in message)) return;
188
- try {
189
- const client = await clientPromise;
190
- switch (message.type) {
191
- case "invoke": {
192
- const value = message.kind === "query" ? await client.query(message.reference, message.args) : message.kind === "mutation" ? await client.mutation(message.reference, message.args) : await client.action(message.reference, message.args);
193
- options.endpoint.postMessage({
194
- type: "invoke.result",
195
- requestId: message.requestId,
196
- success: true,
197
- value
198
- });
199
- return;
200
- }
201
- case "watch.subscribe": {
202
- if (subscriptions.has(message.subscriptionId)) return;
203
- const watch = client.watchQuery(message.reference, message.args);
204
- const sendCurrentState = () => {
205
- const error = watch.localQueryError();
206
- if (error) {
207
- options.endpoint.postMessage({
208
- type: "watch.update",
209
- subscriptionId: message.subscriptionId,
210
- success: false,
211
- error: error.message
212
- });
213
- return;
214
- }
215
- options.endpoint.postMessage({
216
- type: "watch.update",
217
- subscriptionId: message.subscriptionId,
218
- success: true,
219
- value: watch.localQueryResult()
220
- });
221
- };
222
- const unsubscribe = watch.onUpdate(sendCurrentState);
223
- subscriptions.set(message.subscriptionId, {
224
- watch,
225
- unsubscribe
226
- });
227
- sendCurrentState();
228
- return;
229
- }
230
- case "watch.unsubscribe": {
231
- const subscription = subscriptions.get(message.subscriptionId);
232
- if (!subscription) return;
233
- subscription.unsubscribe();
234
- subscriptions.delete(message.subscriptionId);
235
- }
236
- }
237
- } catch (error) {
238
- const errorMessage = error instanceof Error ? error.message : String(error);
239
- if (message.type === "invoke") options.endpoint.postMessage({
240
- type: "invoke.result",
241
- requestId: message.requestId,
242
- success: false,
243
- error: errorMessage
244
- });
245
- if (message.type === "watch.subscribe") options.endpoint.postMessage({
246
- type: "watch.update",
247
- subscriptionId: message.subscriptionId,
248
- success: false,
249
- error: errorMessage
250
- });
251
- }
252
- })();
253
- };
254
- options.endpoint.addEventListener("message", handleMessage);
255
- return {
256
- ready,
257
- async dispose() {
258
- options.endpoint.removeEventListener("message", handleMessage);
259
- for (const subscription of subscriptions.values()) subscription.unsubscribe();
260
- subscriptions.clear();
261
- await (await runtimePromise).stop();
262
- }
263
- };
264
- }
265
- function createWatchKey(reference, args) {
266
- return `${reference.name}:${stableStringify(args)}`;
267
- }
268
- function createInvokeRequest(requestId, kind, reference, args) {
269
- switch (kind) {
270
- case "query": return {
271
- type: "invoke",
272
- requestId,
273
- kind,
274
- reference,
275
- args
276
- };
277
- case "mutation": return {
278
- type: "invoke",
279
- requestId,
280
- kind,
281
- reference,
282
- args
283
- };
284
- case "action": return {
285
- type: "invoke",
286
- requestId,
287
- kind,
288
- reference,
289
- args
290
- };
291
- }
292
- }
293
- function stableStringify(value) {
294
- return JSON.stringify(sortValue(value));
295
- }
296
- function sortValue(value) {
297
- if (Array.isArray(value)) return value.map(sortValue);
298
- if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortValue(nested)]));
299
- return value;
300
- }
301
- function normalizeOptionalArgs(args) {
302
- return args[0] ?? {};
38
+ return attachRuntimeBridge(options);
303
39
  }
304
40
  //#endregion
305
41
  export { SyncoreWebWorkerClient, attachWebWorkerRuntime, createManagedWebWorkerClient, createSyncoreWebWorkerClient, createWebWorkerClient };
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","names":[],"sources":["../src/worker.ts"],"sourcesContent":["import {\n generateId,\n type AnySyncoreSchema,\n type FunctionReference,\n type JsonObject,\n type SyncoreClient,\n type SyncoreRuntime,\n type SyncoreWatch\n} from \"@syncore/core\";\nexport type WebWorkerSyncoreSchema = AnySyncoreSchema;\n\nexport interface SyncoreWorkerMessageEndpoint {\n postMessage(message: unknown): void;\n addEventListener(\n type: \"message\",\n listener: (event: MessageEvent<unknown>) => void\n ): void;\n removeEventListener(\n type: \"message\",\n listener: (event: MessageEvent<unknown>) => void\n ): void;\n}\n\ntype SyncoreWorkerRequest =\n | {\n type: \"invoke\";\n requestId: string;\n kind: \"query\";\n reference: FunctionReference<\"query\", unknown, unknown>;\n args: JsonObject;\n }\n | {\n type: \"invoke\";\n requestId: string;\n kind: \"mutation\";\n reference: FunctionReference<\"mutation\", unknown, unknown>;\n args: JsonObject;\n }\n | {\n type: \"invoke\";\n requestId: string;\n kind: \"action\";\n reference: FunctionReference<\"action\", unknown, unknown>;\n args: JsonObject;\n }\n | {\n type: \"watch.subscribe\";\n subscriptionId: string;\n reference: FunctionReference<\"query\", unknown, unknown>;\n args: JsonObject;\n }\n | {\n type: \"watch.unsubscribe\";\n subscriptionId: string;\n };\n\ntype SyncoreWorkerResponse =\n | {\n type: \"runtime.ready\";\n }\n | {\n type: \"runtime.error\";\n error: string;\n }\n | {\n type: \"invoke.result\";\n requestId: string;\n success: true;\n value: unknown;\n }\n | {\n type: \"invoke.result\";\n requestId: string;\n success: false;\n error: string;\n }\n | {\n type: \"watch.update\";\n subscriptionId: string;\n success: true;\n value: unknown;\n }\n | {\n type: \"watch.update\";\n subscriptionId: string;\n success: false;\n error: string;\n };\n\ninterface PendingRequest {\n resolve(value: unknown): void;\n reject(error: Error): void;\n}\n\ninterface WatchRecord {\n subscriptionId: string;\n listeners: Set<() => void>;\n consumers: number;\n result: unknown;\n error: Error | undefined;\n}\n\nexport type WorkerQueryWatch<TValue> = SyncoreWatch<TValue> & {\n dispose(): void;\n};\n\ntype OptionalArgsTuple<TArgs> =\n Record<never, never> extends TArgs ? [args?: TArgs] : [args: TArgs];\n\nexport class SyncoreWebWorkerClient implements SyncoreClient {\n private readonly pendingRequests = new Map<string, PendingRequest>();\n private readonly watchRecordsByKey = new Map<string, WatchRecord>();\n private readonly watchKeyBySubscriptionId = new Map<string, string>();\n private disposed = false;\n\n private readonly handleMessage = (event: MessageEvent<unknown>) => {\n const message = event.data as SyncoreWorkerResponse;\n if (!message || typeof message !== \"object\" || !(\"type\" in message)) {\n return;\n }\n\n switch (message.type) {\n case \"runtime.ready\":\n return;\n case \"runtime.error\":\n this.rejectAllPending(new Error(message.error));\n return;\n case \"invoke.result\": {\n const pending = this.pendingRequests.get(message.requestId);\n if (!pending) {\n return;\n }\n this.pendingRequests.delete(message.requestId);\n if (message.success) {\n pending.resolve(message.value);\n } else {\n pending.reject(new Error(message.error));\n }\n return;\n }\n case \"watch.update\": {\n const watchKey = this.watchKeyBySubscriptionId.get(\n message.subscriptionId\n );\n if (!watchKey) {\n return;\n }\n const watchRecord = this.watchRecordsByKey.get(watchKey);\n if (!watchRecord) {\n return;\n }\n if (message.success) {\n watchRecord.result = message.value;\n watchRecord.error = undefined;\n } else {\n watchRecord.error = new Error(message.error);\n }\n for (const listener of watchRecord.listeners) {\n listener();\n }\n }\n }\n };\n\n constructor(private readonly endpoint: SyncoreWorkerMessageEndpoint) {\n this.endpoint.addEventListener(\"message\", this.handleMessage);\n }\n\n query<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs>\n ): Promise<TResult> {\n return this.invoke(\n \"query\",\n reference,\n normalizeOptionalArgs(args) as JsonObject\n );\n }\n\n mutation<TArgs, TResult>(\n reference: FunctionReference<\"mutation\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs>\n ): Promise<TResult> {\n return this.invoke(\n \"mutation\",\n reference,\n normalizeOptionalArgs(args) as JsonObject\n );\n }\n\n action<TArgs, TResult>(\n reference: FunctionReference<\"action\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs>\n ): Promise<TResult> {\n return this.invoke(\n \"action\",\n reference,\n normalizeOptionalArgs(args) as JsonObject\n );\n }\n\n watchQuery<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs>\n ): WorkerQueryWatch<TResult> {\n this.ensureNotDisposed();\n const normalizedArgs = normalizeOptionalArgs(args) as JsonObject;\n const watchKey = createWatchKey(reference, normalizedArgs);\n let watchRecord = this.watchRecordsByKey.get(watchKey);\n if (!watchRecord) {\n watchRecord = {\n subscriptionId: generateId(),\n listeners: new Set<() => void>(),\n consumers: 0,\n result: undefined,\n error: undefined\n };\n this.watchRecordsByKey.set(watchKey, watchRecord);\n this.watchKeyBySubscriptionId.set(watchRecord.subscriptionId, watchKey);\n this.endpoint.postMessage({\n type: \"watch.subscribe\",\n subscriptionId: watchRecord.subscriptionId,\n reference,\n args: normalizedArgs\n } satisfies SyncoreWorkerRequest);\n }\n\n watchRecord.consumers += 1;\n let disposed = false;\n const ownedListeners = new Set<() => void>();\n\n return {\n onUpdate: (callback) => {\n watchRecord.listeners.add(callback);\n ownedListeners.add(callback);\n queueMicrotask(callback);\n return () => {\n watchRecord.listeners.delete(callback);\n ownedListeners.delete(callback);\n };\n },\n localQueryResult: () => watchRecord.result as TResult | undefined,\n localQueryError: () => watchRecord.error,\n dispose: () => {\n if (disposed) {\n return;\n }\n disposed = true;\n for (const callback of ownedListeners) {\n watchRecord.listeners.delete(callback);\n }\n ownedListeners.clear();\n watchRecord.consumers = Math.max(0, watchRecord.consumers - 1);\n if (watchRecord.consumers > 0) {\n return;\n }\n this.endpoint.postMessage({\n type: \"watch.unsubscribe\",\n subscriptionId: watchRecord.subscriptionId\n } satisfies SyncoreWorkerRequest);\n this.watchKeyBySubscriptionId.delete(watchRecord.subscriptionId);\n this.watchRecordsByKey.delete(watchKey);\n }\n };\n }\n\n dispose(): void {\n if (this.disposed) {\n return;\n }\n this.disposed = true;\n this.endpoint.removeEventListener(\"message\", this.handleMessage);\n for (const watchRecord of this.watchRecordsByKey.values()) {\n this.endpoint.postMessage({\n type: \"watch.unsubscribe\",\n subscriptionId: watchRecord.subscriptionId\n } satisfies SyncoreWorkerRequest);\n }\n this.watchKeyBySubscriptionId.clear();\n this.watchRecordsByKey.clear();\n this.rejectAllPending(new Error(\"Syncore worker client was disposed.\"));\n }\n\n private invoke<TArgs, TResult>(\n kind: \"query\",\n reference: FunctionReference<\"query\", TArgs, TResult>,\n args: JsonObject\n ): Promise<TResult>;\n private invoke<TArgs, TResult>(\n kind: \"mutation\",\n reference: FunctionReference<\"mutation\", TArgs, TResult>,\n args: JsonObject\n ): Promise<TResult>;\n private invoke<TArgs, TResult>(\n kind: \"action\",\n reference: FunctionReference<\"action\", TArgs, TResult>,\n args: JsonObject\n ): Promise<TResult>;\n private invoke<TArgs, TResult>(\n kind: \"query\" | \"mutation\" | \"action\",\n reference: FunctionReference<\n \"query\" | \"mutation\" | \"action\",\n TArgs,\n TResult\n >,\n args: JsonObject\n ): Promise<TResult> {\n this.ensureNotDisposed();\n const requestId = generateId();\n const promise = new Promise<TResult>((resolve, reject) => {\n this.pendingRequests.set(requestId, { resolve, reject });\n });\n\n this.endpoint.postMessage(\n createInvokeRequest(requestId, kind, reference, args)\n );\n\n return promise;\n }\n\n private rejectAllPending(error: Error): void {\n for (const pending of this.pendingRequests.values()) {\n pending.reject(error);\n }\n this.pendingRequests.clear();\n }\n\n private ensureNotDisposed(): void {\n if (this.disposed) {\n throw new Error(\"Syncore worker client was disposed.\");\n }\n }\n}\n\nexport interface AttachWebWorkerRuntimeOptions {\n endpoint: SyncoreWorkerMessageEndpoint;\n createRuntime:\n | (() => Promise<SyncoreRuntime<WebWorkerSyncoreSchema>>)\n | (() => SyncoreRuntime<WebWorkerSyncoreSchema>);\n}\n\nexport interface AttachedWebWorkerRuntime {\n ready: Promise<void>;\n dispose(): Promise<void>;\n}\n\n/**\n * A worker-backed browser client plus the Worker instance it owns.\n */\nexport interface ManagedWebWorkerClient {\n client: SyncoreWebWorkerClient;\n worker: Worker;\n dispose(): void;\n}\n\n/**\n * Options for creating a worker-backed Syncore client in the browser.\n */\nexport interface CreateWebWorkerClientProviderOptions {\n /** The worker module URL passed to `new Worker(...)`. */\n workerUrl: URL | string;\n\n /** Optional worker type, defaults to `module`. */\n workerType?: WorkerOptions[\"type\"];\n\n /** Optional name shown in browser devtools. */\n workerName?: string;\n}\n\n/**\n * Create a web worker Syncore client from a low-level message endpoint.\n */\nexport function createWebWorkerClient(\n endpoint: SyncoreWorkerMessageEndpoint\n): SyncoreWebWorkerClient {\n return new SyncoreWebWorkerClient(endpoint);\n}\n\n/**\n * Create and manage both a browser Worker and the Syncore client that talks to it.\n */\nexport function createManagedWebWorkerClient(options: {\n createWorker: () => Worker;\n}): ManagedWebWorkerClient {\n const worker = options.createWorker();\n const client = createWebWorkerClient(worker);\n return {\n client,\n worker,\n dispose() {\n client.dispose();\n worker.terminate();\n }\n };\n}\n\n/**\n * Create a worker-backed Syncore client using the standard Worker constructor.\n */\nexport function createSyncoreWebWorkerClient(\n options: CreateWebWorkerClientProviderOptions\n): ManagedWebWorkerClient {\n return createManagedWebWorkerClient({\n createWorker: () =>\n new Worker(options.workerUrl, {\n type: options.workerType ?? \"module\",\n ...(options.workerName ? { name: options.workerName } : {})\n })\n });\n}\n\n/**\n * Attach a Syncore runtime implementation to a worker message endpoint.\n */\nexport function attachWebWorkerRuntime(\n options: AttachWebWorkerRuntimeOptions\n): AttachedWebWorkerRuntime {\n const subscriptions = new Map<\n string,\n {\n watch: SyncoreWatch<unknown>;\n unsubscribe: () => void;\n }\n >();\n\n const runtimePromise = Promise.resolve(options.createRuntime()).then(\n async (runtime) => {\n await runtime.start();\n return runtime;\n }\n );\n\n const clientPromise = runtimePromise.then((runtime) =>\n runtime.createClient()\n );\n\n const ready = clientPromise\n .then(() => {\n options.endpoint.postMessage({\n type: \"runtime.ready\"\n } satisfies SyncoreWorkerResponse);\n })\n .catch((error) => {\n options.endpoint.postMessage({\n type: \"runtime.error\",\n error: error instanceof Error ? error.message : String(error)\n } satisfies SyncoreWorkerResponse);\n throw error;\n });\n\n const handleMessage = (event: MessageEvent<unknown>) => {\n void (async () => {\n const message = event.data as SyncoreWorkerRequest;\n if (!message || typeof message !== \"object\" || !(\"type\" in message)) {\n return;\n }\n\n try {\n const client = await clientPromise;\n switch (message.type) {\n case \"invoke\": {\n const value =\n message.kind === \"query\"\n ? await client.query(message.reference, message.args)\n : message.kind === \"mutation\"\n ? await client.mutation(message.reference, message.args)\n : await client.action(message.reference, message.args);\n options.endpoint.postMessage({\n type: \"invoke.result\",\n requestId: message.requestId,\n success: true,\n value\n } satisfies SyncoreWorkerResponse);\n return;\n }\n case \"watch.subscribe\": {\n if (subscriptions.has(message.subscriptionId)) {\n return;\n }\n const watch = client.watchQuery(message.reference, message.args);\n const sendCurrentState = () => {\n const error = watch.localQueryError();\n if (error) {\n options.endpoint.postMessage({\n type: \"watch.update\",\n subscriptionId: message.subscriptionId,\n success: false,\n error: error.message\n } satisfies SyncoreWorkerResponse);\n return;\n }\n options.endpoint.postMessage({\n type: \"watch.update\",\n subscriptionId: message.subscriptionId,\n success: true,\n value: watch.localQueryResult()\n } satisfies SyncoreWorkerResponse);\n };\n const unsubscribe = watch.onUpdate(sendCurrentState);\n subscriptions.set(message.subscriptionId, { watch, unsubscribe });\n sendCurrentState();\n return;\n }\n case \"watch.unsubscribe\": {\n const subscription = subscriptions.get(message.subscriptionId);\n if (!subscription) {\n return;\n }\n subscription.unsubscribe();\n subscriptions.delete(message.subscriptionId);\n }\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n if (message.type === \"invoke\") {\n options.endpoint.postMessage({\n type: \"invoke.result\",\n requestId: message.requestId,\n success: false,\n error: errorMessage\n } satisfies SyncoreWorkerResponse);\n }\n if (message.type === \"watch.subscribe\") {\n options.endpoint.postMessage({\n type: \"watch.update\",\n subscriptionId: message.subscriptionId,\n success: false,\n error: errorMessage\n } satisfies SyncoreWorkerResponse);\n }\n }\n })();\n };\n\n options.endpoint.addEventListener(\"message\", handleMessage);\n\n return {\n ready,\n async dispose() {\n options.endpoint.removeEventListener(\"message\", handleMessage);\n for (const subscription of subscriptions.values()) {\n subscription.unsubscribe();\n }\n subscriptions.clear();\n const runtime = await runtimePromise;\n await runtime.stop();\n }\n };\n}\n\nfunction createWatchKey(\n reference: FunctionReference<\"query\", unknown, unknown>,\n args: JsonObject\n): string {\n return `${reference.name}:${stableStringify(args)}`;\n}\n\nfunction createInvokeRequest(\n requestId: string,\n kind: \"query\" | \"mutation\" | \"action\",\n reference:\n | FunctionReference<\"query\", unknown, unknown>\n | FunctionReference<\"mutation\", unknown, unknown>\n | FunctionReference<\"action\", unknown, unknown>,\n args: JsonObject\n): SyncoreWorkerRequest {\n switch (kind) {\n case \"query\":\n return {\n type: \"invoke\",\n requestId,\n kind,\n reference: reference as FunctionReference<\"query\">,\n args\n };\n case \"mutation\":\n return {\n type: \"invoke\",\n requestId,\n kind,\n reference: reference as FunctionReference<\"mutation\">,\n args\n };\n case \"action\":\n return {\n type: \"invoke\",\n requestId,\n kind,\n reference: reference as FunctionReference<\"action\">,\n args\n };\n }\n}\n\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortValue(value));\n}\n\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortValue);\n }\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, sortValue(nested)])\n );\n }\n return value;\n}\n\nfunction normalizeOptionalArgs<TArgs>(\n args: [] | [TArgs] | readonly unknown[]\n): TArgs {\n return (args[0] ?? {}) as TArgs;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","names":[],"sources":["../src/worker.ts"],"sourcesContent":["import {\n attachRuntimeBridge,\n type AttachRuntimeBridgeOptions,\n type AttachedRuntimeBridge,\n type BridgeQueryWatch,\n SyncoreBridgeClient,\n type SyncoreDataModel,\n type SyncoreBridgeMessageEndpoint,\n} from \"@syncore/core\";\n\nexport type WebWorkerSyncoreSchema<\n TSchema extends SyncoreDataModel = SyncoreDataModel\n> = TSchema;\nexport type SyncoreWorkerMessageEndpoint = SyncoreBridgeMessageEndpoint;\nexport type WorkerQueryWatch<TValue> = BridgeQueryWatch<TValue>;\n\nexport class SyncoreWebWorkerClient extends SyncoreBridgeClient {\n declare query: SyncoreBridgeClient[\"query\"];\n declare mutation: SyncoreBridgeClient[\"mutation\"];\n declare action: SyncoreBridgeClient[\"action\"];\n declare watchQuery: SyncoreBridgeClient[\"watchQuery\"];\n}\n\nexport type AttachWebWorkerRuntimeOptions<\n TSchema extends WebWorkerSyncoreSchema = WebWorkerSyncoreSchema\n> = AttachRuntimeBridgeOptions<TSchema>;\nexport type AttachedWebWorkerRuntime = AttachedRuntimeBridge;\n\n/**\n * A worker-backed browser client plus the Worker instance it owns.\n */\nexport interface ManagedWebWorkerClient {\n client: SyncoreWebWorkerClient;\n worker: Worker;\n dispose(): void;\n}\n\n/**\n * Options for creating a worker-backed Syncore client in the browser.\n */\nexport interface CreateWebWorkerClientProviderOptions {\n /** The worker module URL passed to `new Worker(...)`. */\n workerUrl: URL | string;\n\n /** Optional worker type, defaults to `module`. */\n workerType?: WorkerOptions[\"type\"];\n\n /** Optional name shown in browser devtools. */\n workerName?: string;\n}\n\n/**\n * Create a web worker Syncore client from a low-level message endpoint.\n */\nexport function createWebWorkerClient(\n endpoint: SyncoreWorkerMessageEndpoint\n): SyncoreWebWorkerClient {\n return new SyncoreWebWorkerClient(endpoint);\n}\n\n/**\n * Create and manage both a browser Worker and the Syncore client that talks to it.\n */\nexport function createManagedWebWorkerClient(options: {\n createWorker: () => Worker;\n}): ManagedWebWorkerClient {\n const worker = options.createWorker();\n const client = createWebWorkerClient(worker);\n return {\n client,\n worker,\n dispose() {\n client.dispose();\n worker.terminate();\n }\n };\n}\n\n/**\n * Create a worker-backed Syncore client using the standard Worker constructor.\n */\nexport function createSyncoreWebWorkerClient(\n options: CreateWebWorkerClientProviderOptions\n): ManagedWebWorkerClient {\n return createManagedWebWorkerClient({\n createWorker: () =>\n new Worker(options.workerUrl, {\n type: options.workerType ?? \"module\",\n ...(options.workerName ? { name: options.workerName } : {})\n })\n });\n}\n\n/**\n * Attach a Syncore runtime implementation to a worker message endpoint.\n */\nexport function attachWebWorkerRuntime(\n options: AttachWebWorkerRuntimeOptions\n): AttachedWebWorkerRuntime {\n return attachRuntimeBridge(options);\n}\n"],"mappings":";;AAgBA,IAAa,yBAAb,cAA4C,oBAAoB;;;;AAsChE,SAAgB,sBACd,UACwB;AACxB,QAAO,IAAI,uBAAuB,SAAS;;;;;AAM7C,SAAgB,6BAA6B,SAElB;CACzB,MAAM,SAAS,QAAQ,cAAc;CACrC,MAAM,SAAS,sBAAsB,OAAO;AAC5C,QAAO;EACL;EACA;EACA,UAAU;AACR,UAAO,SAAS;AAChB,UAAO,WAAW;;EAErB;;;;;AAMH,SAAgB,6BACd,SACwB;AACxB,QAAO,6BAA6B,EAClC,oBACE,IAAI,OAAO,QAAQ,WAAW;EAC5B,MAAM,QAAQ,cAAc;EAC5B,GAAI,QAAQ,aAAa,EAAE,MAAM,QAAQ,YAAY,GAAG,EAAE;EAC3D,CAAC,EACL,CAAC;;;;;AAMJ,SAAgB,uBACd,SAC0B;AAC1B,QAAO,oBAAoB,QAAQ"}
@@ -1,20 +1,32 @@
1
1
  import { ReactNode } from "react";
2
2
  import * as react_jsx_runtime0 from "react/jsx-runtime";
3
- import { FunctionReference, SyncoreClient } from "../core/index.d.mts";
3
+ import { FunctionArgs, FunctionReference, FunctionResult, PaginationOptions, PaginationResult, SyncoreClient, SyncoreQueryState, SyncoreRuntimeStatus, UsePaginatedQueryResult } from "../core/index.d.mts";
4
4
 
5
5
  //#region src/index.d.ts
6
6
  type OptionalArgsTuple<TArgs> = Record<never, never> extends TArgs ? [args?: TArgs] : [args: TArgs];
7
+ type QueryRequestInput<TReference extends FunctionReference<"query"> = FunctionReference<"query">> = Record<never, never> extends FunctionArgs<TReference> ? {
8
+ query: TReference;
9
+ args?: FunctionArgs<TReference> | Skip;
10
+ } : {
11
+ query: TReference;
12
+ args: FunctionArgs<TReference> | Skip;
13
+ };
14
+ type QueriesRequestInput = Record<string, QueryRequestInput>;
15
+ type QueryStateForEntry<TEntry> = TEntry extends QueryRequestInput<infer TReference> ? SyncoreQueryState<FunctionResult<TReference>> : never;
16
+ type UseQueriesResult<TEntries extends QueriesRequestInput> = { [TKey in keyof TEntries]: QueryStateForEntry<TEntries[TKey]> };
17
+ type PaginatedQueryReference = FunctionReference<"query", Record<string, unknown>, PaginationResult<unknown>>;
18
+ type PaginatedQueryArgs<TReference extends FunctionReference<"query">> = FunctionArgs<TReference> extends {
19
+ paginationOpts: PaginationOptions;
20
+ } ? Omit<FunctionArgs<TReference>, "paginationOpts"> : never;
21
+ type PaginatedQueryItem<TReference extends FunctionReference<"query">> = FunctionResult<TReference> extends PaginationResult<infer TItem> ? TItem : never;
7
22
  /**
8
- * Pass `"skip"` as the args argument to `useQuery` to suppress the subscription
9
- * entirely and return `undefined` without contacting the runtime.
23
+ * Pass `"skip"` as the args argument to `useQuery`, `useQueryState`,
24
+ * `useQueries`, or `usePaginatedQuery` to suppress the subscription entirely.
10
25
  */
11
26
  declare const skip: "skip";
12
27
  type Skip = typeof skip;
13
28
  /**
14
29
  * Provide a Syncore client to React descendants.
15
- *
16
- * Wrap your app with this component to use Syncore hooks like `useQuery` and
17
- * `useMutation`.
18
30
  */
19
31
  declare function SyncoreProvider({
20
32
  client,
@@ -25,18 +37,20 @@ declare function SyncoreProvider({
25
37
  }): react_jsx_runtime0.JSX.Element;
26
38
  /**
27
39
  * Read the active Syncore client from React context.
28
- *
29
- * Throws if used outside of {@link SyncoreProvider}.
30
40
  */
31
41
  declare function useSyncore(): SyncoreClient;
32
42
  /**
33
- * Load a reactive Syncore query within a React component.
34
- *
35
- * The hook subscribes automatically and re-renders whenever the local query
36
- * result changes. Pass `"skip"` as the second argument to suppress the
37
- * subscription entirely and return `undefined` without contacting the runtime.
43
+ * Subscribe to the active Syncore client's runtime lifecycle status.
44
+ */
45
+ declare function useSyncoreStatus(): SyncoreRuntimeStatus;
46
+ /**
47
+ * Load a reactive Syncore query and return only the data for the common case.
38
48
  */
39
49
  declare function useQuery<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs> | [Skip]): TResult | undefined;
50
+ /**
51
+ * Load a reactive Syncore query and keep the full local state.
52
+ */
53
+ declare function useQueryState<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs> | [Skip]): SyncoreQueryState<TResult>;
40
54
  /**
41
55
  * Construct a stable function that executes a Syncore mutation.
42
56
  */
@@ -46,13 +60,15 @@ declare function useMutation<TArgs, TResult>(reference: FunctionReference<"mutat
46
60
  */
47
61
  declare function useAction<TArgs, TResult>(reference: FunctionReference<"action", TArgs, TResult>): (...args: OptionalArgsTuple<TArgs>) => Promise<TResult>;
48
62
  /**
49
- * Load several Syncore queries at once using explicit keys.
63
+ * Load a keyed set of Syncore queries at once with per-entry state.
64
+ */
65
+ declare function useQueries<TEntries extends QueriesRequestInput>(entries: TEntries): UseQueriesResult<TEntries>;
66
+ /**
67
+ * Load a paginated Syncore query as a growing reactive list.
50
68
  */
51
- declare function useQueries<TResult>(entries: Array<{
52
- key: string;
53
- reference: FunctionReference<"query">;
54
- args?: Record<string, unknown>;
55
- }>): Record<string, TResult | undefined>;
69
+ declare function usePaginatedQuery<TReference extends PaginatedQueryReference>(reference: TReference, args: PaginatedQueryArgs<TReference> | Skip, options: {
70
+ initialNumItems: number;
71
+ }): UsePaginatedQueryResult<PaginatedQueryItem<TReference>>;
56
72
  //#endregion
57
- export { SyncoreProvider, skip, useAction, useMutation, useQueries, useQuery, useSyncore };
73
+ export { SyncoreProvider, UseQueriesResult, skip, useAction, useMutation, usePaginatedQuery, useQueries, useQuery, useQueryState, useSyncore, useSyncoreStatus };
58
74
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":";;;;;KAkBK,iBAAA,UACH,MAAA,uBAA6B,KAAA,IAAS,IAAA,GAAO,KAAA,KAAU,IAAA,EAAM,KAAA;;;AAPxC;;cAaV,IAAA;AAAA,KACR,IAAA,UAAc,IAAA;;;;;;;iBAUH,eAAA,CAAA;EACd,MAAA;EACA;AAAA;EAEA,MAAA,EAAQ,aAAA;EACR,QAAA,EAAU,SAAA;AAAA,IACX,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;;AAjBD;iBA4BgB,UAAA,CAAA,GAAc,aAAA;;;;AA5BM;;;;iBA2CpB,QAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,KAAU,IAAA,IACpC,OAAA;AAnCH;;;AAAA,iBAgFgB,WAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,aAA8B,KAAA,EAAO,OAAA,QAC3C,IAAA,EAAM,iBAAA,CAAkB,KAAA,MAAW,OAAA,CAAQ,OAAA;;;;iBAQlC,SAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,WAA4B,KAAA,EAAO,OAAA,QACzC,IAAA,EAAM,iBAAA,CAAkB,KAAA,MAAW,OAAA,CAAQ,OAAA;;;;iBAQlC,UAAA,SAAA,CACd,OAAA,EAAS,KAAA;EACP,GAAA;EACA,SAAA,EAAW,iBAAA;EACX,IAAA,GAAO,MAAA;AAAA,KAER,MAAA,SAAe,OAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":";;;;;KA0BK,iBAAA,UACH,MAAA,uBAA6B,KAAA,IAAS,IAAA,GAAO,KAAA,KAAU,IAAA,EAAM,KAAA;AAAA,KAE1D,iBAAA,oBACgB,iBAAA,YAA6B,iBAAA,aAC9C,MAAA,uBAA6B,YAAA,CAAa,UAAA;EAExC,KAAA,EAAO,UAAA;EACP,IAAA,GAAO,YAAA,CAAa,UAAA,IAAc,IAAA;AAAA;EAGlC,KAAA,EAAO,UAAA;EACP,IAAA,EAAM,YAAA,CAAa,UAAA,IAAc,IAAA;AAAA;AAAA,KAGlC,mBAAA,GAAsB,MAAA,SAAe,iBAAA;AAAA,KAErC,kBAAA,WAA6B,MAAA,SAAe,iBAAA,qBAG7C,iBAAA,CAAkB,cAAA,CAAe,UAAA;AAAA,KAGzB,gBAAA,kBAAkC,mBAAA,qBAC7B,QAAA,GAAW,kBAAA,CAAmB,QAAA,CAAS,IAAA;AAAA,KAGnD,uBAAA,GAA0B,iBAAA,UAE7B,MAAA,mBACA,gBAAA;AAAA,KAGG,kBAAA,oBAAsC,iBAAA,aACzC,YAAA,CAAa,UAAA;EAAsB,cAAA,EAAgB,iBAAA;AAAA,IAC/C,IAAA,CAAK,YAAA,CAAa,UAAA;AAAA,KAGnB,kBAAA,oBAAsC,iBAAA,aACzC,cAAA,CAAe,UAAA,UAAoB,gBAAA,gBAC/B,KAAA;;;;AAvC8D;cA2EvD,IAAA;AAAA,KACR,IAAA,UAAc,IAAA;;;;iBAYH,eAAA,CAAA;EACd,MAAA;EACA;AAAA;EAEA,MAAA,EAAQ,aAAA;EACR,QAAA,EAAU,SAAA;AAAA,IACX,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;iBASe,UAAA,CAAA,GAAc,aAAA;;;;iBAWd,gBAAA,CAAA,GAAoB,oBAAA;;;;iBA+BpB,QAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,KAAU,IAAA,IACpC,OAAA;;;;iBAWa,aAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,KAAU,IAAA,IACpC,iBAAA,CAAkB,OAAA;;;;iBAkCL,WAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,aAA8B,KAAA,EAAO,OAAA,QAC3C,IAAA,EAAM,iBAAA,CAAkB,KAAA,MAAW,OAAA,CAAQ,OAAA;;;;iBAQlC,SAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,WAA4B,KAAA,EAAO,OAAA,QACzC,IAAA,EAAM,iBAAA,CAAkB,KAAA,MAAW,OAAA,CAAQ,OAAA;;;;iBAQlC,UAAA,kBAA4B,mBAAA,CAAA,CAC1C,OAAA,EAAS,QAAA,GACR,gBAAA,CAAiB,QAAA;AA/MuB;;;AAAA,iBAuQ3B,iBAAA,oBAAqC,uBAAA,CAAA,CACnD,SAAA,EAAW,UAAA,EACX,IAAA,EAAM,kBAAA,CAAmB,UAAA,IAAc,IAAA,EACvC,OAAA;EACE,eAAA;AAAA,IAED,uBAAA,CAAwB,kBAAA,CAAmB,UAAA"}