ignotum 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -3
- package/dist/cli/bin.mjs +563 -104
- package/dist/cli/bin.mjs.map +1 -1
- package/dist/runtime/{api-jCl8Hzry.d.ts → api-5XSrIeqW.d.ts} +4 -3
- package/dist/runtime/client.d.ts +6 -5
- package/dist/runtime/client.js +170 -75
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/{descriptor-C5VA9qRl-BhD-WQeO.js → descriptor-XzDX2JDw-j3O6YHgW.js} +26 -6
- package/dist/runtime/descriptor-XzDX2JDw-j3O6YHgW.js.map +1 -0
- package/dist/runtime/{id-Cs82tq9Q-Caqfx54f.d.ts → id-Cs82tq9Q-CK-maMgN.d.ts} +13 -13
- package/dist/runtime/{index-D6VLTbDB.d.ts → index-CrWg4Z0y.d.ts} +132 -76
- package/dist/runtime/internal/api.d.ts +1 -1
- package/dist/runtime/internal/host.d.ts +18 -17
- package/dist/runtime/internal/host.js +11 -6
- package/dist/runtime/internal/host.js.map +1 -1
- package/dist/runtime/internal/server.d.ts +1 -1
- package/dist/runtime/internal/server.js +1 -1
- package/dist/runtime/internal/types.d.ts +1 -1
- package/dist/runtime/internal/types.js +1 -1
- package/dist/runtime/pagination-CX5IPbEi.d.ts +1 -0
- package/dist/runtime/{pagination-Bt3l7QaC-D_zI5zsu.d.ts → pagination-D-R9NR61-CpIoHFoI.d.ts} +8 -5
- package/dist/runtime/result-DIjKM-p4.d.ts +1 -0
- package/dist/runtime/{schema-C00wobuy.js → schema-B9XxyRO8.js} +132 -16
- package/dist/runtime/schema-B9XxyRO8.js.map +1 -0
- package/dist/runtime/server.d.ts +7 -3
- package/dist/runtime/server.js +5 -3
- package/dist/runtime/server.js.map +1 -1
- package/dist/runtime/{sync-bMQq9tXx.d.ts → sync-avN7NkcU.d.ts} +2 -2
- package/package.json +1 -1
- package/src/cli/agent-files.ts +2 -0
- package/src/cli/auth-client.ts +1 -1
- package/src/cli/bin.ts +13 -3
- package/src/cli/build/server.ts +102 -13
- package/src/cli/codegen.ts +7 -4
- package/src/cli/control-client.ts +30 -8
- package/src/cli/deploy.ts +7 -2
- package/src/cli/environment.ts +133 -0
- package/src/client/files.ts +43 -27
- package/src/client/hooks.ts +26 -17
- package/src/client/page-observers.ts +77 -0
- package/src/client/sync.ts +71 -59
- package/src/dev-runtime/functions.ts +127 -4
- package/src/dev-runtime/sync.ts +38 -9
- package/src/server/index.ts +11 -1
- package/dist/runtime/descriptor-C5VA9qRl-BhD-WQeO.js.map +0 -1
- package/dist/runtime/pagination-DcIkTOFs.d.ts +0 -1
- package/dist/runtime/schema-C00wobuy.js.map +0 -1
- package/src/dev-runtime/id.ts +0 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as InternalServerError, g as FileValue, i as ErrorValue } from "./id-Cs82tq9Q-
|
|
2
|
-
import
|
|
1
|
+
import { a as InternalServerError, g as FileValue, i as ErrorValue } from "./id-Cs82tq9Q-CK-maMgN.js";
|
|
2
|
+
import "./result-DIjKM-p4.js";
|
|
3
|
+
import { t as FunctionAddress } from "./sync-avN7NkcU.js";
|
|
3
4
|
import { Effect } from "effect";
|
|
4
5
|
//#region src/internal/api.d.ts
|
|
5
6
|
declare const FunctionReferenceTypeId: unique symbol;
|
|
@@ -42,4 +43,4 @@ declare const functionPathOf: <Kind extends FunctionKind, Args, Success, Failure
|
|
|
42
43
|
declare function createApi<Modules>(): Api<Modules>;
|
|
43
44
|
//#endregion
|
|
44
45
|
export { functionPathOf as a, createApi as i, FunctionReference as n, MutationInput as r, Api as t };
|
|
45
|
-
//# sourceMappingURL=api-
|
|
46
|
+
//# sourceMappingURL=api-5XSrIeqW.d.ts.map
|
package/dist/runtime/client.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { a as InternalServerError, g as FileValue, h as FileMimeType, i as ErrorValue, l as SettledResult, m as FileMetadata, o as Match, p as FileFormat, s as QueryResult$1 } from "./id-Cs82tq9Q-
|
|
2
|
-
import "./
|
|
3
|
-
import
|
|
4
|
-
import { n as
|
|
5
|
-
import "./pagination-
|
|
1
|
+
import { a as InternalServerError, g as FileValue, h as FileMimeType, i as ErrorValue, l as SettledResult, m as FileMetadata, o as Match, p as FileFormat, s as QueryResult$1 } from "./id-Cs82tq9Q-CK-maMgN.js";
|
|
2
|
+
import "./result-DIjKM-p4.js";
|
|
3
|
+
import "./sync-avN7NkcU.js";
|
|
4
|
+
import { n as FunctionReference } from "./api-5XSrIeqW.js";
|
|
5
|
+
import { n as PaginationPage, t as PaginationOptions } from "./pagination-D-R9NR61-CpIoHFoI.js";
|
|
6
|
+
import "./pagination-CX5IPbEi.js";
|
|
6
7
|
import { Context as Context$1, Effect, Layer } from "effect";
|
|
7
8
|
import { Dispatch, Reducer, StateUpdater, useCallback, useContext, useDebugValue, useEffect, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState } from "preact/hooks";
|
|
8
9
|
import { AnyComponent, Attributes, ClassAttributes, Component, ComponentChild, ComponentChildren, ComponentClass, ComponentConstructor, ComponentFactory, ComponentProps, ComponentType, ComponentType as ComponentType$1, Consumer, Context, ContextType, ErrorInfo, Fragment, FunctionComponent, FunctionalComponent, JSX, Key, PreactConsumer, PreactContext, PreactDOMAttributes, PreactProvider, Provider, Ref, RefCallback, RefObject, RenderableProps, TargetedAnimationEvent, TargetedClipboardEvent, TargetedCommandEvent, TargetedCompositionEvent, TargetedDragEvent, TargetedEvent, TargetedFocusEvent, TargetedInputEvent, TargetedKeyboardEvent, TargetedMouseEvent, TargetedPictureInPictureEvent, TargetedPointerEvent, TargetedSnapEvent, TargetedSubmitEvent, TargetedToggleEvent, TargetedTouchEvent, TargetedTransitionEvent, TargetedUIEvent, TargetedWheelEvent, VNode, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray } from "preact";
|
package/dist/runtime/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { C as RuntimeRequestNonce, T as TableId, _ as AppId, a as RuntimeFileMetadata, b as IdAlphabet, c as fileFormats, d as fileLimits, f as fileMimeTypes, h as makeFileValue, l as fileGrantUrlOf, m as isFileValue, o as RuntimeFileOccurrence, p as grantFileValue, r as FileId, u as fileIdOf, v as DeploymentId, w as SubscriptionId, x as InvocationId, y as GeneratedId } from "./file-C1abuMgd.js";
|
|
2
|
-
import {
|
|
2
|
+
import { S as encodeTransportObject, c as initial, f as Result$2, g as pending, h as inspectResult, l as upgrade, m as failureFromWire, s as PaginationPageSize, t as ValueDescriptor, x as decodeTransportValue } from "./descriptor-XzDX2JDw-j3O6YHgW.js";
|
|
3
3
|
import { a as ErrorCode, c as ServerMessageJson, d as WireSuccess, f as AppStateRevision, i as DeploymentCloseCode, l as WireFailure, m as InvocationKey, n as functionPathOf, o as FunctionAddress, p as DeploymentGeneration, r as ClientMessageJson, s as Operation, u as WireResult } from "./api-DzcR7spt.js";
|
|
4
4
|
import { Array as Array$1, Cause, Context, Deferred, Duration, Effect, ErrorReporter, Fiber, HashMap, Layer, ManagedRuntime, Predicate, Schedule, Schema, String } from "effect";
|
|
5
5
|
import { customAlphabet } from "nanoid";
|
|
@@ -32,9 +32,10 @@ const Files = { url: (file) => {
|
|
|
32
32
|
} };
|
|
33
33
|
const formatByMime = {};
|
|
34
34
|
for (const format of fileFormats) formatByMime[fileMimeTypes[format]] = format;
|
|
35
|
+
const MutationObject = Schema.ObjectKeyword.check(Schema.makeFilter((value) => Object.prototype.toString.call(value) === "[object Object]", { message: "Mutation objects must contain ordinary fields; built-in collections are unsupported." }));
|
|
35
36
|
const collectNativeFiles = (value, files) => {
|
|
36
37
|
if (value instanceof File) {
|
|
37
|
-
files.
|
|
38
|
+
files.add(value);
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
40
41
|
if (isFileValue(value) || Predicate.isDate(value)) return;
|
|
@@ -43,7 +44,7 @@ const collectNativeFiles = (value, files) => {
|
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
if (!Predicate.isObject(value)) return;
|
|
46
|
-
for (const child of Object.values(value)) collectNativeFiles(child, files);
|
|
47
|
+
for (const child of Object.values(Schema.decodeSync(MutationObject)(value))) collectNativeFiles(child, files);
|
|
47
48
|
};
|
|
48
49
|
const replaceNativeFiles = (value, replacements) => {
|
|
49
50
|
if (value instanceof File) return replacements.get(value);
|
|
@@ -54,18 +55,23 @@ const replaceNativeFiles = (value, replacements) => {
|
|
|
54
55
|
};
|
|
55
56
|
const prepareMutationArguments = Effect.fn("SyncClient.prepareMutationArguments")(function* (input) {
|
|
56
57
|
const ids = yield* IdGenerator;
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
const unique = yield* Effect.try(() => {
|
|
59
|
+
const files = /* @__PURE__ */ new Set();
|
|
60
|
+
collectNativeFiles(input, files);
|
|
61
|
+
if (files.size > fileLimits.filesPerMutation) throw new Error(`A mutation may upload at most ${fileLimits.filesPerMutation} files.`);
|
|
62
|
+
if ([...files].reduce((total, file) => total + file.size, 0) > fileLimits.mutationBytes) throw new Error(`Mutation uploads may total at most ${fileLimits.mutationBytes} bytes.`);
|
|
63
|
+
return files;
|
|
64
|
+
});
|
|
62
65
|
const replacements = /* @__PURE__ */ new Map();
|
|
63
66
|
const nativeFiles = /* @__PURE__ */ new Map();
|
|
64
67
|
for (const file of unique) {
|
|
65
|
-
const format =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
const format = yield* Effect.try(() => {
|
|
69
|
+
const format = formatByMime[file.type.toLowerCase()];
|
|
70
|
+
if (format === void 0) throw new Error(`File '${file.name}' has unsupported media type '${file.type || "unknown"}'.`);
|
|
71
|
+
if (file.size === 0 || file.size > fileLimits.fileBytes) throw new Error(`File '${file.name}' must be between 1 and ${fileLimits.fileBytes} bytes.`);
|
|
72
|
+
if (new TextEncoder().encode(file.name).byteLength > fileLimits.filenameBytes) throw new Error(`File '${file.name}' has a filename that is too long.`);
|
|
73
|
+
return format;
|
|
74
|
+
});
|
|
69
75
|
const id = yield* ids.generate(FileId);
|
|
70
76
|
replacements.set(file, makeFileValue(id, {
|
|
71
77
|
format,
|
|
@@ -75,12 +81,13 @@ const prepareMutationArguments = Effect.fn("SyncClient.prepareMutationArguments"
|
|
|
75
81
|
nativeFiles.set(id, file);
|
|
76
82
|
}
|
|
77
83
|
return {
|
|
78
|
-
value: replaceNativeFiles(input, replacements),
|
|
84
|
+
value: unique.size === 0 ? input : yield* Effect.try(() => replaceNativeFiles(input, replacements)),
|
|
79
85
|
nativeFiles,
|
|
80
86
|
fileIds: Array.from(nativeFiles.keys())
|
|
81
87
|
};
|
|
82
88
|
});
|
|
83
89
|
const applyFileGrants = (value, grants) => {
|
|
90
|
+
if (grants.length === 0) return value;
|
|
84
91
|
const byId = /* @__PURE__ */ new Map();
|
|
85
92
|
for (const grant of grants) {
|
|
86
93
|
if (byId.has(grant.id)) throw new Error("A query file grant ID is duplicated.");
|
|
@@ -105,15 +112,12 @@ const applyFileGrants = (value, grants) => {
|
|
|
105
112
|
};
|
|
106
113
|
//#endregion
|
|
107
114
|
//#region ../contracts/dist/json.js
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
if (value === null || Predicate.isString(value) || Predicate.isNumber(value) || Predicate.isBoolean(value)) return
|
|
111
|
-
|
|
112
|
-
const field = Schema.decodeUnknownSync(Schema.Json)(value[key]);
|
|
113
|
-
return `${encodeScalar(key)}:${encodeCanonicalJson(field)}`;
|
|
114
|
-
}).join(",")}}`;
|
|
115
|
-
return `[${Schema.decodeUnknownSync(Schema.Array(Schema.Json))(value).map(encodeCanonicalJson).join(",")}]`;
|
|
115
|
+
const encodeJson = (value) => {
|
|
116
|
+
if (Array$1.isArray(value)) return `[${value.map(encodeJson).join(",")}]`;
|
|
117
|
+
if (value === null || Predicate.isString(value) || Predicate.isNumber(value) || Predicate.isBoolean(value)) return JSON.stringify(value);
|
|
118
|
+
return `{${Array$1.sortWith(Object.entries(value), ([key]) => key, String.Order).map(([key, field]) => `${JSON.stringify(key)}:${encodeJson(field)}`).join(",")}}`;
|
|
116
119
|
};
|
|
120
|
+
const encodeCanonicalJson = (value) => encodeJson(Schema.decodeSync(Schema.Json)(value));
|
|
117
121
|
//#endregion
|
|
118
122
|
//#region src/client/errors.ts
|
|
119
123
|
/** @effect-diagnostics globalConsole:skip-file */
|
|
@@ -342,6 +346,7 @@ const ArtifactKind = Schema.Literals([
|
|
|
342
346
|
"ClientShell",
|
|
343
347
|
"FunctionBundle",
|
|
344
348
|
"ServerManifest",
|
|
349
|
+
"ServerEnvironment",
|
|
345
350
|
"SourceMap",
|
|
346
351
|
"SchemaSnapshot"
|
|
347
352
|
]);
|
|
@@ -366,7 +371,14 @@ const DeploymentInventoryV1 = Schema.Struct({
|
|
|
366
371
|
formatVersion: Schema.Literal(1),
|
|
367
372
|
files: Schema.Array(ArtifactFile)
|
|
368
373
|
});
|
|
369
|
-
|
|
374
|
+
const DeploymentInventoryV2 = Schema.Struct({
|
|
375
|
+
formatVersion: Schema.Literal(2),
|
|
376
|
+
files: Schema.Array(ArtifactFile)
|
|
377
|
+
});
|
|
378
|
+
upgrade(initial(DeploymentInventoryV1), DeploymentInventoryV2, (inventory) => ({
|
|
379
|
+
formatVersion: 2,
|
|
380
|
+
files: inventory.files
|
|
381
|
+
}));
|
|
370
382
|
const ClientManifestV1 = Schema.Struct({
|
|
371
383
|
formatVersion: Schema.Literal(1),
|
|
372
384
|
shell: ArtifactReference,
|
|
@@ -387,6 +399,16 @@ const SchemaSnapshotField = Schema.Struct({
|
|
|
387
399
|
name: Schema.String,
|
|
388
400
|
value: ValueDescriptor
|
|
389
401
|
});
|
|
402
|
+
const EnvironmentArtifactV1 = Schema.Struct({
|
|
403
|
+
formatVersion: Schema.Literal(1),
|
|
404
|
+
nonce: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9_-]{43}$/)),
|
|
405
|
+
values: Schema.Record(Schema.String, Schema.String)
|
|
406
|
+
});
|
|
407
|
+
initial(EnvironmentArtifactV1);
|
|
408
|
+
const ServerEnvironmentArtifact = Schema.Struct({
|
|
409
|
+
artifact: ArtifactReference,
|
|
410
|
+
fields: Schema.Array(SchemaSnapshotField)
|
|
411
|
+
});
|
|
390
412
|
const SchemaSnapshotIndex = Schema.Struct({
|
|
391
413
|
name: Schema.String,
|
|
392
414
|
fields: Schema.Array(Schema.String)
|
|
@@ -440,11 +462,22 @@ const ServerBuildManifestV2 = Schema.Struct({
|
|
|
440
462
|
schema: ArtifactReference,
|
|
441
463
|
functions: Schema.Array(ServerFunctionArtifact)
|
|
442
464
|
});
|
|
443
|
-
upgrade(initial(ServerBuildManifestV1), ServerBuildManifestV2, (manifest) => ({
|
|
465
|
+
const ServerBuildManifestThroughV2 = upgrade(initial(ServerBuildManifestV1), ServerBuildManifestV2, (manifest) => ({
|
|
444
466
|
formatVersion: 2,
|
|
445
467
|
schema: manifest.schema,
|
|
446
468
|
functions: manifest.functions
|
|
447
469
|
}));
|
|
470
|
+
const ServerBuildManifestV3 = Schema.Struct({
|
|
471
|
+
formatVersion: Schema.Literal(3),
|
|
472
|
+
schema: ArtifactReference,
|
|
473
|
+
environment: Schema.optional(ServerEnvironmentArtifact),
|
|
474
|
+
functions: Schema.Array(ServerFunctionArtifact)
|
|
475
|
+
});
|
|
476
|
+
upgrade(ServerBuildManifestThroughV2, ServerBuildManifestV3, (manifest) => ({
|
|
477
|
+
formatVersion: 3,
|
|
478
|
+
schema: manifest.schema,
|
|
479
|
+
functions: manifest.functions
|
|
480
|
+
}));
|
|
448
481
|
ArtifactPath.make("inventory.json");
|
|
449
482
|
ArtifactPath.make("client/manifest.json");
|
|
450
483
|
ArtifactPath.make("client/shell.html");
|
|
@@ -452,6 +485,7 @@ ArtifactPath.make("client/shell.html");
|
|
|
452
485
|
`${ArtifactPath.make("client/routes")}`;
|
|
453
486
|
ArtifactPath.make("server/manifest.json");
|
|
454
487
|
ArtifactPath.make("server/schema.json");
|
|
488
|
+
ArtifactPath.make("server/environment.json");
|
|
455
489
|
//#endregion
|
|
456
490
|
//#region ../contracts/dist/runtime/transport.js
|
|
457
491
|
const runtimeInvocationPath = "/v1/invoke";
|
|
@@ -519,13 +553,10 @@ const subscribeMessage = (entry) => ({
|
|
|
519
553
|
});
|
|
520
554
|
const makeQueryCache = (allocateId, sendLifecycleMessage) => {
|
|
521
555
|
const queries = /* @__PURE__ */ new Map();
|
|
522
|
-
const
|
|
556
|
+
const queriesById = /* @__PURE__ */ new Map();
|
|
523
557
|
return {
|
|
524
558
|
entries: () => queries.values(),
|
|
525
|
-
getById: (id) =>
|
|
526
|
-
const key = queryKeysById.get(id);
|
|
527
|
-
return key === void 0 ? void 0 : queries.get(key);
|
|
528
|
-
},
|
|
559
|
+
getById: (id) => queriesById.get(id),
|
|
529
560
|
observe: Effect.fn("SyncClient.QueryCache.observe")(function* (functionAddress, args) {
|
|
530
561
|
const key = queryKey(functionAddress, args);
|
|
531
562
|
let entry = queries.get(key);
|
|
@@ -541,7 +572,7 @@ const makeQueryCache = (allocateId, sendLifecycleMessage) => {
|
|
|
541
572
|
subscriptionId: yield* allocateId
|
|
542
573
|
};
|
|
543
574
|
queries.set(key, created);
|
|
544
|
-
|
|
575
|
+
queriesById.set(created.subscriptionId, created);
|
|
545
576
|
yield* sendLifecycleMessage(subscribeMessage(created));
|
|
546
577
|
entry = created;
|
|
547
578
|
}
|
|
@@ -564,7 +595,7 @@ const makeQueryCache = (allocateId, sendLifecycleMessage) => {
|
|
|
564
595
|
yield* Effect.sleep("25 millis");
|
|
565
596
|
if (observed.references !== 0 || observed.generation !== generation || queries.get(key) !== observed) return;
|
|
566
597
|
queries.delete(key);
|
|
567
|
-
|
|
598
|
+
queriesById.delete(observed.subscriptionId);
|
|
568
599
|
yield* sendLifecycleMessage({
|
|
569
600
|
type: "Unsubscribe",
|
|
570
601
|
id: observed.subscriptionId
|
|
@@ -572,25 +603,25 @@ const makeQueryCache = (allocateId, sendLifecycleMessage) => {
|
|
|
572
603
|
})
|
|
573
604
|
};
|
|
574
605
|
}),
|
|
575
|
-
setError: (id, error) => {
|
|
576
|
-
const key = queryKeysById.get(id);
|
|
577
|
-
const entry = key === void 0 ? void 0 : queries.get(key);
|
|
578
|
-
if (entry === void 0) return;
|
|
579
|
-
entry.result = error;
|
|
580
|
-
for (const listener of entry.listeners) listener();
|
|
581
|
-
},
|
|
582
606
|
setResult: (id, result, revision) => {
|
|
583
|
-
const
|
|
584
|
-
const entry = key === void 0 ? void 0 : queries.get(key);
|
|
607
|
+
const entry = queriesById.get(id);
|
|
585
608
|
if (entry === void 0) return;
|
|
586
|
-
if (
|
|
587
|
-
|
|
609
|
+
if (revision !== void 0) {
|
|
610
|
+
if (entry.revision !== void 0 && revision < entry.revision) return;
|
|
611
|
+
entry.revision = revision;
|
|
612
|
+
}
|
|
588
613
|
entry.result = result;
|
|
589
614
|
for (const listener of entry.listeners) listener();
|
|
590
615
|
}
|
|
591
616
|
};
|
|
592
617
|
};
|
|
593
|
-
const resultFromWire = Effect.fn("SyncClient.resultFromWire")((wire, files = []) => Effect.
|
|
618
|
+
const resultFromWire = Effect.fn("SyncClient.resultFromWire")((wire, files = []) => Effect.try({
|
|
619
|
+
try: () => wire.type === "Success" ? Result$2.succeed(wire.value === void 0 ? void 0 : applyFileGrants(decodeTransportValue(wire.value, wire.dates ?? []), files)) : failureFromWire(wire.error, wire.dates),
|
|
620
|
+
catch: (cause) => InvalidServerMessage.make({
|
|
621
|
+
cause,
|
|
622
|
+
message: "The server returned an invalid function result."
|
|
623
|
+
})
|
|
624
|
+
}));
|
|
594
625
|
const shouldReloadForCloseCode = (code) => code === DeploymentCloseCode;
|
|
595
626
|
const handshakesMatch = (first, next) => first.appId === next.appId && first.deploymentId === next.deploymentId && first.generation === next.generation;
|
|
596
627
|
const handshakeDecision = (remembered, acceptedOnConnection, next) => {
|
|
@@ -638,10 +669,16 @@ var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync
|
|
|
638
669
|
};
|
|
639
670
|
const handleMessage = Effect.fn("SyncClient.handleMessage")(function* (message) {
|
|
640
671
|
switch (message.type) {
|
|
641
|
-
case "Snapshot":
|
|
642
|
-
|
|
643
|
-
|
|
672
|
+
case "Snapshot": {
|
|
673
|
+
const entry = queryCache.getById(message.id);
|
|
674
|
+
if (entry === void 0) return;
|
|
675
|
+
if (entry.revision !== void 0 && message.revision < entry.revision) return;
|
|
676
|
+
yield* resultFromWire(message.result, message.files ?? []).pipe(Effect.tap((result) => Effect.sync(() => queryCache.setResult(message.id, result, message.revision))), Effect.catchTags({ InvalidServerMessage: (error) => {
|
|
677
|
+
queryCache.setResult(message.id, error, message.revision);
|
|
678
|
+
return reportClientError(error);
|
|
679
|
+
} }));
|
|
644
680
|
return;
|
|
681
|
+
}
|
|
645
682
|
case "Preparation": {
|
|
646
683
|
const pendingInvocation = HashMap.getUnsafe(invocations, message.id);
|
|
647
684
|
if (pendingInvocation !== void 0) yield* Deferred.succeed(pendingInvocation.prepared, message.uploads);
|
|
@@ -650,8 +687,10 @@ var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync
|
|
|
650
687
|
case "Result": {
|
|
651
688
|
const pendingInvocation = HashMap.getUnsafe(invocations, message.id);
|
|
652
689
|
if (pendingInvocation === void 0) return;
|
|
653
|
-
|
|
654
|
-
|
|
690
|
+
yield* resultFromWire(message.result).pipe(Effect.flatMap((result) => {
|
|
691
|
+
invocations = HashMap.remove(invocations, message.id);
|
|
692
|
+
return Deferred.succeed(pendingInvocation.deferred, result);
|
|
693
|
+
}), Effect.catchTags({ InvalidServerMessage: (error) => rejectInvocation(message.id, error) }));
|
|
655
694
|
return;
|
|
656
695
|
}
|
|
657
696
|
case "Error": {
|
|
@@ -665,7 +704,7 @@ var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync
|
|
|
665
704
|
});
|
|
666
705
|
if (message.operation?.type === "Invocation") yield* rejectInvocation(message.operation.id, error);
|
|
667
706
|
else if (message.operation?.type === "Subscription") {
|
|
668
|
-
queryCache.
|
|
707
|
+
queryCache.setResult(message.operation.id, error);
|
|
669
708
|
yield* reportClientError(error);
|
|
670
709
|
} else yield* reportClientError(error);
|
|
671
710
|
return;
|
|
@@ -781,6 +820,7 @@ var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync
|
|
|
781
820
|
const uploads = yield* Deferred.await(prepared);
|
|
782
821
|
const expected = new Set(message.files);
|
|
783
822
|
const received = /* @__PURE__ */ new Set();
|
|
823
|
+
const transfers = [];
|
|
784
824
|
for (const upload of uploads) {
|
|
785
825
|
if (!expected.has(upload.id) || received.has(upload.id)) return yield* InvalidServerMessage.make({
|
|
786
826
|
cause: /* @__PURE__ */ new Error(`Unexpected prepared file '${upload.id}'.`),
|
|
@@ -793,12 +833,22 @@ var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync
|
|
|
793
833
|
message: "The server prepared an unknown application file."
|
|
794
834
|
});
|
|
795
835
|
if (upload.url === void 0) continue;
|
|
796
|
-
|
|
836
|
+
transfers.push({
|
|
837
|
+
file,
|
|
838
|
+
url: upload.url
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
if (received.size !== expected.size) return yield* InvalidServerMessage.make({
|
|
842
|
+
cause: /* @__PURE__ */ new Error("The server omitted a prepared file."),
|
|
843
|
+
message: "The server returned incomplete application file preparation data."
|
|
844
|
+
});
|
|
845
|
+
yield* Effect.forEach(transfers, Effect.fn("SyncClient.uploadFile")(function* ({ file, url }) {
|
|
797
846
|
const response = yield* Effect.tryPromise({
|
|
798
|
-
try: () => fetch(
|
|
847
|
+
try: (signal) => fetch(url, {
|
|
799
848
|
method: "PUT",
|
|
800
849
|
body: file,
|
|
801
|
-
headers: { "content-type": file.type }
|
|
850
|
+
headers: { "content-type": file.type },
|
|
851
|
+
signal
|
|
802
852
|
}),
|
|
803
853
|
catch: (cause) => ConnectionUnavailable.make({
|
|
804
854
|
cause,
|
|
@@ -813,10 +863,9 @@ var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync
|
|
|
813
863
|
message: `File '${file.name}' was rejected by application storage.`
|
|
814
864
|
});
|
|
815
865
|
}
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
message: "The server returned incomplete application file preparation data."
|
|
866
|
+
}), {
|
|
867
|
+
concurrency: 3,
|
|
868
|
+
discard: true
|
|
820
869
|
});
|
|
821
870
|
const pendingInvocation = HashMap.getUnsafe(invocations, invocationId);
|
|
822
871
|
if (pendingInvocation === void 0) return yield* Deferred.await(deferred);
|
|
@@ -844,6 +893,56 @@ const syncRuntime = ManagedRuntime.make(SyncClient.layer.pipe(Layer.provideMerge
|
|
|
844
893
|
const hot = import.meta.hot;
|
|
845
894
|
if (hot !== void 0) hot.dispose(() => void syncRuntime.dispose());
|
|
846
895
|
//#endregion
|
|
896
|
+
//#region src/client/page-observers.ts
|
|
897
|
+
const makePageObservers = (onChange, releaseObserver) => {
|
|
898
|
+
const pages = /* @__PURE__ */ new Map();
|
|
899
|
+
let disposed = false;
|
|
900
|
+
const releaseEntry = (entry) => {
|
|
901
|
+
entry.released = true;
|
|
902
|
+
entry.release?.();
|
|
903
|
+
};
|
|
904
|
+
return {
|
|
905
|
+
observe: Effect.fn("PageObservers.observe")(function* (functionAddress, args) {
|
|
906
|
+
if (disposed) return;
|
|
907
|
+
const key = syncClientInternals.queryIdentity(functionAddress, args);
|
|
908
|
+
const existing = pages.get(key);
|
|
909
|
+
if (existing !== void 0) return yield* existing.acquire;
|
|
910
|
+
const entry = {
|
|
911
|
+
acquire: yield* Effect.cached(Effect.gen(function* () {
|
|
912
|
+
const observer = yield* (yield* SyncClient).observe(functionAddress, args);
|
|
913
|
+
if (entry.released) {
|
|
914
|
+
releaseObserver(observer.release);
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
const unsubscribe = observer.subscribe(onChange);
|
|
918
|
+
entry.release = () => {
|
|
919
|
+
unsubscribe();
|
|
920
|
+
releaseObserver(observer.release);
|
|
921
|
+
};
|
|
922
|
+
return observer;
|
|
923
|
+
})),
|
|
924
|
+
release: void 0,
|
|
925
|
+
released: false
|
|
926
|
+
};
|
|
927
|
+
pages.set(key, entry);
|
|
928
|
+
return yield* entry.acquire;
|
|
929
|
+
}),
|
|
930
|
+
retain: (keys) => {
|
|
931
|
+
for (const [key, entry] of pages) {
|
|
932
|
+
if (keys.has(key)) continue;
|
|
933
|
+
pages.delete(key);
|
|
934
|
+
releaseEntry(entry);
|
|
935
|
+
}
|
|
936
|
+
},
|
|
937
|
+
release: () => {
|
|
938
|
+
if (disposed) return;
|
|
939
|
+
disposed = true;
|
|
940
|
+
for (const entry of pages.values()) releaseEntry(entry);
|
|
941
|
+
pages.clear();
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
};
|
|
945
|
+
//#endregion
|
|
847
946
|
//#region src/client/hooks.ts
|
|
848
947
|
function useQuery(reference, args) {
|
|
849
948
|
const functionPath = functionPathOf(reference);
|
|
@@ -916,6 +1015,10 @@ function usePaginatedQuery(reference, args, options = {}) {
|
|
|
916
1015
|
result: pending()
|
|
917
1016
|
}));
|
|
918
1017
|
const loadMore = useCallback$1(() => setRequestedPages((count) => count + 1), []);
|
|
1018
|
+
const pages = useMemo$1(() => makePageObservers(() => setRefresh((version) => version + 1), (release) => {
|
|
1019
|
+
syncRuntime.runFork(release);
|
|
1020
|
+
}), [identity, pageSize]);
|
|
1021
|
+
useEffect$1(() => () => pages.release(), [pages]);
|
|
919
1022
|
useDebugValue$1({
|
|
920
1023
|
args: input,
|
|
921
1024
|
function: functionPath,
|
|
@@ -931,9 +1034,8 @@ function usePaginatedQuery(reference, args, options = {}) {
|
|
|
931
1034
|
useEffect$1(() => {
|
|
932
1035
|
if (skipped) return;
|
|
933
1036
|
let active = true;
|
|
934
|
-
const
|
|
1037
|
+
const usedPages = /* @__PURE__ */ new Set();
|
|
935
1038
|
syncRuntime.runPromise(Effect.gen(function* () {
|
|
936
|
-
const client = yield* SyncClient;
|
|
937
1039
|
const items = [];
|
|
938
1040
|
let cursor = null;
|
|
939
1041
|
for (let pageNumber = 0; pageNumber < requestedPages; pageNumber += 1) {
|
|
@@ -944,18 +1046,9 @@ function usePaginatedQuery(reference, args, options = {}) {
|
|
|
944
1046
|
pageSize
|
|
945
1047
|
}
|
|
946
1048
|
});
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
return;
|
|
951
|
-
}
|
|
952
|
-
const releaseSubscription = observer.subscribe(() => {
|
|
953
|
-
if (active) setRefresh((version) => version + 1);
|
|
954
|
-
});
|
|
955
|
-
releases.push(() => {
|
|
956
|
-
releaseSubscription();
|
|
957
|
-
syncRuntime.runFork(observer.release);
|
|
958
|
-
});
|
|
1049
|
+
usedPages.add(syncClientInternals.queryIdentity(functionPath, pageArgs));
|
|
1050
|
+
const observer = yield* pages.observe(functionPath, pageArgs);
|
|
1051
|
+
if (!active || observer === void 0) return;
|
|
959
1052
|
const snapshot = observer.getSnapshot();
|
|
960
1053
|
if (Schema.is(ClientInfrastructureError)(snapshot)) {
|
|
961
1054
|
setState({
|
|
@@ -968,7 +1061,7 @@ function usePaginatedQuery(reference, args, options = {}) {
|
|
|
968
1061
|
if (inspected === void 0) {
|
|
969
1062
|
setState({
|
|
970
1063
|
identity,
|
|
971
|
-
result: items.length === 0 ? pending() : Result$
|
|
1064
|
+
result: items.length === 0 ? pending() : Result$2.succeed({
|
|
972
1065
|
items,
|
|
973
1066
|
loadMore,
|
|
974
1067
|
status: "LoadingMore"
|
|
@@ -989,7 +1082,7 @@ function usePaginatedQuery(reference, args, options = {}) {
|
|
|
989
1082
|
if (cursor === null) {
|
|
990
1083
|
setState({
|
|
991
1084
|
identity,
|
|
992
|
-
result: Result$
|
|
1085
|
+
result: Result$2.succeed({
|
|
993
1086
|
items,
|
|
994
1087
|
loadMore,
|
|
995
1088
|
status: "Exhausted"
|
|
@@ -1000,13 +1093,15 @@ function usePaginatedQuery(reference, args, options = {}) {
|
|
|
1000
1093
|
}
|
|
1001
1094
|
setState({
|
|
1002
1095
|
identity,
|
|
1003
|
-
result: Result$
|
|
1096
|
+
result: Result$2.succeed({
|
|
1004
1097
|
items,
|
|
1005
1098
|
loadMore,
|
|
1006
1099
|
status: "CanLoadMore"
|
|
1007
1100
|
})
|
|
1008
1101
|
});
|
|
1009
|
-
})
|
|
1102
|
+
}).pipe(Effect.ensuring(Effect.sync(() => {
|
|
1103
|
+
if (active) pages.retain(usedPages);
|
|
1104
|
+
})))).catch((error) => {
|
|
1010
1105
|
if (active && Schema.is(ClientInfrastructureError)(error)) setState({
|
|
1011
1106
|
identity,
|
|
1012
1107
|
result: error
|
|
@@ -1014,13 +1109,13 @@ function usePaginatedQuery(reference, args, options = {}) {
|
|
|
1014
1109
|
});
|
|
1015
1110
|
return () => {
|
|
1016
1111
|
active = false;
|
|
1017
|
-
for (const release of releases) release();
|
|
1018
1112
|
};
|
|
1019
1113
|
}, [
|
|
1020
1114
|
functionPath,
|
|
1021
1115
|
identity,
|
|
1022
1116
|
loadMore,
|
|
1023
1117
|
pageSize,
|
|
1118
|
+
pages,
|
|
1024
1119
|
refresh,
|
|
1025
1120
|
requestedPages,
|
|
1026
1121
|
skipped
|
|
@@ -1048,7 +1143,7 @@ const app = (definition) => {
|
|
|
1048
1143
|
};
|
|
1049
1144
|
//#endregion
|
|
1050
1145
|
//#region src/client/index.ts
|
|
1051
|
-
const Result = { match: Result$
|
|
1146
|
+
const Result = { match: Result$2.match };
|
|
1052
1147
|
//#endregion
|
|
1053
1148
|
export { Component, Files, Fragment, Query, Result, app, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray, useCallback, useContext, useDebugValue, useEffect, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useMemo, useMutation, usePaginatedQuery, useQuery, useReducer, useRef, useState };
|
|
1054
1149
|
|