ignotum 0.0.13 → 0.0.15
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 +6 -6
- package/dist/cli/bin.mjs +6111 -4448
- package/dist/cli/bin.mjs.map +1 -1
- package/dist/cli/emscripten-module-D5GzfUNv.mjs +533 -0
- package/dist/cli/emscripten-module-D5GzfUNv.mjs.map +1 -0
- package/dist/cli/ffi-7IElU4Co.mjs +148 -0
- package/dist/cli/ffi-7IElU4Co.mjs.map +1 -0
- package/dist/cli/managed-release-WHYLZwaS.mjs +10902 -0
- package/dist/cli/managed-release-WHYLZwaS.mjs.map +1 -0
- package/dist/cli/managed-release.d.mts +1 -0
- package/dist/cli/managed-release.mjs +14 -0
- package/dist/cli/managed-release.mjs.map +1 -0
- package/dist/cli/module-ES6BEMUI-D36I4NVn.mjs +1289 -0
- package/dist/cli/module-ES6BEMUI-D36I4NVn.mjs.map +1 -0
- package/dist/runtime/{api-Cv3hMbzo.d.ts → api-B4fwp5a2.d.ts} +4 -4
- package/dist/runtime/bootstrap-BISQSn_O.js +916 -0
- package/dist/runtime/bootstrap-BISQSn_O.js.map +1 -0
- package/dist/runtime/bootstrap-BTFScKAc.d.ts +545 -0
- package/dist/runtime/client.d.ts +50 -15
- package/dist/runtime/client.js +7 -1138
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/descriptor-CTY4mtwS-cS43EbwS.js +269 -0
- package/dist/runtime/descriptor-CTY4mtwS-cS43EbwS.js.map +1 -0
- package/dist/runtime/{id-Bt9XWRGL.js → id--1m0NuUL.js} +4 -4
- package/dist/runtime/id--1m0NuUL.js.map +1 -0
- package/dist/runtime/{id-BzFHf3Wo-DGPCjgrf.d.ts → id-7an3nxTu-DZJSM5xh.d.ts} +2 -2
- package/dist/runtime/id-CBOt2kDo.d.ts +1 -0
- package/dist/runtime/identity-QjtJRxBD.d.ts +2 -0
- package/dist/runtime/image-Djtjy4Z8.js +19 -0
- package/dist/runtime/image-Djtjy4Z8.js.map +1 -0
- package/dist/runtime/index-D4seNHlX.d.ts +184 -0
- package/dist/runtime/internal/api.d.ts +1 -1
- package/dist/runtime/internal/api.js +30 -1
- package/dist/runtime/internal/api.js.map +1 -0
- package/dist/runtime/internal/bootstrap.d.ts +2 -0
- package/dist/runtime/internal/bootstrap.js +2 -0
- package/dist/runtime/internal/client.d.ts +2 -0
- package/dist/runtime/internal/client.js +75 -0
- package/dist/runtime/internal/client.js.map +1 -0
- package/dist/runtime/internal/host.d.ts +25 -8
- package/dist/runtime/internal/host.js +27 -6
- package/dist/runtime/internal/host.js.map +1 -1
- package/dist/runtime/internal/routes.d.ts +2 -0
- package/dist/runtime/internal/routes.js +2 -0
- package/dist/runtime/internal/server.d.ts +1 -1
- package/dist/runtime/internal/server.js +1 -1
- package/dist/runtime/internal/types.d.ts +2 -1
- package/dist/runtime/internal/types.js +1 -1
- package/dist/runtime/pagination-CBOt2kDo.d.ts +1 -0
- package/dist/runtime/pagination-D3qd6s9N.js +33 -0
- package/dist/runtime/pagination-D3qd6s9N.js.map +1 -0
- package/dist/runtime/result-BkziOG1L.d.ts +1 -0
- package/dist/runtime/router-BSBI1oN1.js +2377 -0
- package/dist/runtime/router-BSBI1oN1.js.map +1 -0
- package/dist/runtime/routes-Ce8TVP-T.js +690 -0
- package/dist/runtime/routes-Ce8TVP-T.js.map +1 -0
- package/dist/runtime/{schema-1Zs03-iS.js → schema-D1wOqiNH.js} +40 -12
- package/dist/runtime/schema-D1wOqiNH.js.map +1 -0
- package/dist/runtime/server.d.ts +5 -5
- package/dist/runtime/server.js +2 -2
- package/dist/runtime/{sync-Bs8J3fIr.d.ts → sync-D-GK2sv9.d.ts} +3 -2
- package/dist/runtime/{api-CAgKDij7.js → sync-DzUwA8W9.js} +22 -41
- package/dist/runtime/sync-DzUwA8W9.js.map +1 -0
- package/dist/runtime/types-DeCCyqLU-BIm7rU-0.d.ts +341 -0
- package/package.json +29 -4
- package/src/cli/agent-files.ts +14 -8
- package/src/cli/build/managed-client.ts +411 -0
- package/src/cli/build/managed-server.ts +294 -0
- package/src/cli/build/managed.ts +67 -0
- package/src/cli/build/output.ts +47 -0
- package/src/cli/build/server.ts +51 -220
- package/src/cli/client-config.ts +1 -140
- package/src/cli/client-styles.ts +1 -0
- package/src/cli/codegen.ts +9 -4
- package/src/cli/command.ts +28 -5
- package/src/cli/control-client.ts +84 -101
- package/src/cli/deploy.ts +133 -177
- package/src/cli/dev.ts +506 -107
- package/src/cli/image-assets.ts +499 -0
- package/src/cli/managed-client-boundaries.ts +103 -0
- package/src/cli/managed-dev-platform.ts +118 -0
- package/src/cli/managed-exports.ts +219 -0
- package/src/cli/managed-release-bin.ts +13 -0
- package/src/cli/managed-release.ts +260 -0
- package/src/cli/module-boundaries.ts +11 -1
- package/src/cli/new-app.ts +111 -87
- package/src/cli/route-codegen.ts +311 -0
- package/src/cli/route-static.ts +710 -0
- package/src/client/bootstrap.ts +110 -0
- package/src/client/errors.ts +13 -7
- package/src/client/files.ts +64 -0
- package/src/client/id.ts +9 -5
- package/src/client/image.ts +28 -0
- package/src/client/index.ts +25 -2
- package/src/client/managed-client.ts +729 -0
- package/src/client/managed-upgrade.ts +283 -0
- package/src/client/recovery-journal.ts +195 -0
- package/src/client/route-boundaries.ts +184 -0
- package/src/client/router-history.ts +152 -0
- package/src/client/router-store.ts +644 -0
- package/src/client/router.ts +324 -0
- package/src/client/routes.ts +28 -0
- package/src/client/sync.ts +66 -592
- package/src/dev-runtime/database.ts +77 -2
- package/src/dev-runtime/functions.ts +3 -3
- package/src/dev-runtime/id.ts +19 -4
- package/src/dev-runtime/managed-functions.ts +255 -0
- package/src/dev-runtime/managed-sync.ts +263 -0
- package/src/dev-runtime/managed-websocket.ts +71 -0
- package/src/dev-runtime/migrations.ts +20 -0
- package/src/dev-runtime/sync.ts +236 -236
- package/src/image-assets.d.ts +36 -0
- package/src/internal/client.ts +186 -0
- package/src/internal/host.ts +1 -1
- package/src/internal/http-paths.ts +0 -3
- package/src/internal/routes.ts +45 -0
- package/dist/runtime/api-CAgKDij7.js.map +0 -1
- package/dist/runtime/descriptor-Cyo9FP9n-C0SRVXNW.js +0 -154
- package/dist/runtime/descriptor-Cyo9FP9n-C0SRVXNW.js.map +0 -1
- package/dist/runtime/id-Bt9XWRGL.js.map +0 -1
- package/dist/runtime/id-Dz0apuB3.d.ts +0 -1
- package/dist/runtime/index-D54flWtH.d.ts +0 -402
- package/dist/runtime/pagination-DnKg3dkI-r5ZUxBBx.d.ts +0 -112
- package/dist/runtime/pagination-Dz0apuB3.d.ts +0 -1
- package/dist/runtime/result-DKAA4gpS.d.ts +0 -1
- package/dist/runtime/schema-1Zs03-iS.js.map +0 -1
- package/src/cli/build/client.ts +0 -119
- package/src/cli/build/public.ts +0 -186
- package/src/cli/client-entry.ts +0 -152
- package/src/cli/client-plugin.ts +0 -136
- package/src/client/app.ts +0 -15
package/dist/runtime/client.js
CHANGED
|
@@ -1,335 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { D as encodeTransportObject, _ as Result$2, b as inspectResult, x as pending } from "./id--1m0NuUL.js";
|
|
2
|
+
import { C as Files, S as BrowserSession, a as url, b as syncClientInternals, c as useMatch, d as useRoute, l as useNavigate, n as NavLink, o as useBlocker, r as Redirect, s as useLocation, t as Link, u as useNavigation, v as SyncClient, w as ClientInfrastructureError, x as syncRuntime } from "./router-BSBI1oN1.js";
|
|
3
|
+
import { functionPathOf } from "./internal/api.js";
|
|
4
|
+
import { n as PaginationPageSize } from "./pagination-D3qd6s9N.js";
|
|
5
|
+
import { t as Image } from "./image-Djtjy4Z8.js";
|
|
6
|
+
import { Effect, Schema } from "effect";
|
|
7
7
|
import { useCallback, useCallback as useCallback$1, useContext, useDebugValue, useDebugValue as useDebugValue$1, useEffect, useEffect as useEffect$1, useErrorBoundary, useId as useElementId, useImperativeHandle, useLayoutEffect, useMemo, useMemo as useMemo$1, useReducer, useRef, useState, useState as useState$1 } from "preact/hooks";
|
|
8
|
-
import * as Socket from "effect/unstable/socket/Socket";
|
|
9
|
-
import * as BrowserCrypto from "@effect/platform-browser/BrowserCrypto";
|
|
10
8
|
import { Component, Fragment, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray } from "preact";
|
|
11
|
-
//#region ../shared/dist/id.js
|
|
12
|
-
const decodeGenerated = (definition, payload) => Schema.decodeSync(definition)(definition.idPrefix === void 0 ? payload : `${definition.idPrefix}_${payload}`);
|
|
13
|
-
var IdGenerator = class IdGenerator extends Context.Service()("@ignotum/shared/id/IdGenerator") {
|
|
14
|
-
static layer = Layer.sync(IdGenerator, () => {
|
|
15
|
-
const generatePayload = customAlphabet(IdAlphabet, 24);
|
|
16
|
-
return IdGenerator.of({ generate: (definition) => Effect.sync(() => decodeGenerated(definition, generatePayload())) });
|
|
17
|
-
});
|
|
18
|
-
static deterministic = (startAt = 1) => Layer.sync(IdGenerator, () => {
|
|
19
|
-
const counters = /* @__PURE__ */ new Map();
|
|
20
|
-
return IdGenerator.of({ generate: (definition) => Effect.sync(() => {
|
|
21
|
-
const counter = (counters.get(definition.idPrefix) ?? startAt - 1) + 1;
|
|
22
|
-
counters.set(definition.idPrefix, counter);
|
|
23
|
-
return decodeGenerated(definition, counter.toString(36).padStart(24, "0"));
|
|
24
|
-
}) });
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
//#endregion
|
|
28
|
-
//#region src/client/files.ts
|
|
29
|
-
const Files = { url: (file) => {
|
|
30
|
-
const url = fileGrantUrlOf(file);
|
|
31
|
-
if (url === void 0) throw new Error("This FileValue has no active query grant.");
|
|
32
|
-
return url;
|
|
33
|
-
} };
|
|
34
|
-
const formatByMime = {};
|
|
35
|
-
for (const format of fileFormats) formatByMime[fileMimeTypes[format]] = format;
|
|
36
|
-
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." }));
|
|
37
|
-
const collectNativeFiles = (value, files) => {
|
|
38
|
-
if (value instanceof File) {
|
|
39
|
-
files.add(value);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (isFileValue(value) || Predicate.isDate(value)) return;
|
|
43
|
-
if (globalThis.Array.isArray(value)) {
|
|
44
|
-
for (const child of value) collectNativeFiles(child, files);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (!Predicate.isObject(value)) return;
|
|
48
|
-
for (const child of Object.values(Schema.decodeSync(MutationObject)(value))) collectNativeFiles(child, files);
|
|
49
|
-
};
|
|
50
|
-
const replaceNativeFiles = (value, replacements) => {
|
|
51
|
-
if (value instanceof File) return replacements.get(value);
|
|
52
|
-
if (isFileValue(value) || Predicate.isDate(value)) return value;
|
|
53
|
-
if (globalThis.Array.isArray(value)) return value.map((child) => replaceNativeFiles(child, replacements));
|
|
54
|
-
if (!Predicate.isObject(value)) return value;
|
|
55
|
-
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, replaceNativeFiles(child, replacements)]));
|
|
56
|
-
};
|
|
57
|
-
const prepareMutationArguments = Effect.fn("SyncClient.prepareMutationArguments")(function* (input) {
|
|
58
|
-
const ids = yield* IdGenerator;
|
|
59
|
-
const unique = yield* Effect.try(() => {
|
|
60
|
-
const files = /* @__PURE__ */ new Set();
|
|
61
|
-
collectNativeFiles(input, files);
|
|
62
|
-
if (files.size > fileLimits.filesPerMutation) throw new Error(`A mutation may upload at most ${fileLimits.filesPerMutation} files.`);
|
|
63
|
-
if ([...files].reduce((total, file) => total + file.size, 0) > fileLimits.mutationBytes) throw new Error(`Mutation uploads may total at most ${fileLimits.mutationBytes} bytes.`);
|
|
64
|
-
return files;
|
|
65
|
-
});
|
|
66
|
-
const replacements = /* @__PURE__ */ new Map();
|
|
67
|
-
const nativeFiles = /* @__PURE__ */ new Map();
|
|
68
|
-
for (const file of unique) {
|
|
69
|
-
const format = yield* Effect.try(() => {
|
|
70
|
-
const format = formatByMime[file.type.toLowerCase()];
|
|
71
|
-
if (format === void 0) throw new Error(`File '${file.name}' has unsupported media type '${file.type || "unknown"}'.`);
|
|
72
|
-
if (file.size === 0 || file.size > fileLimits.fileBytes) throw new Error(`File '${file.name}' must be between 1 and ${fileLimits.fileBytes} bytes.`);
|
|
73
|
-
if (new TextEncoder().encode(file.name).byteLength > fileLimits.filenameBytes) throw new Error(`File '${file.name}' has a filename that is too long.`);
|
|
74
|
-
return format;
|
|
75
|
-
});
|
|
76
|
-
const id = yield* ids.generate(FileId);
|
|
77
|
-
replacements.set(file, makeFileValue(id, {
|
|
78
|
-
format,
|
|
79
|
-
name: file.name,
|
|
80
|
-
size: file.size
|
|
81
|
-
}));
|
|
82
|
-
nativeFiles.set(id, file);
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
value: unique.size === 0 ? input : yield* Effect.try(() => replaceNativeFiles(input, replacements)),
|
|
86
|
-
nativeFiles,
|
|
87
|
-
fileIds: Array.from(nativeFiles.keys())
|
|
88
|
-
};
|
|
89
|
-
});
|
|
90
|
-
const applyFileGrants = (value, grants) => {
|
|
91
|
-
if (grants.length === 0) return value;
|
|
92
|
-
const byId = /* @__PURE__ */ new Map();
|
|
93
|
-
for (const grant of grants) {
|
|
94
|
-
if (byId.has(grant.id)) throw new Error("A query file grant ID is duplicated.");
|
|
95
|
-
byId.set(grant.id, grant.url);
|
|
96
|
-
}
|
|
97
|
-
const matched = /* @__PURE__ */ new Set();
|
|
98
|
-
const visit = (current) => {
|
|
99
|
-
if (isFileValue(current)) {
|
|
100
|
-
const id = fileIdOf(current);
|
|
101
|
-
const url = byId.get(id);
|
|
102
|
-
if (url === void 0) return current;
|
|
103
|
-
matched.add(id);
|
|
104
|
-
return grantFileValue(current, url);
|
|
105
|
-
}
|
|
106
|
-
if (globalThis.Array.isArray(current)) return current.map(visit);
|
|
107
|
-
if (!Predicate.isObject(current) || Predicate.isDate(current)) return current;
|
|
108
|
-
return Object.fromEntries(Object.entries(current).map(([key, child]) => [key, visit(child)]));
|
|
109
|
-
};
|
|
110
|
-
const granted = visit(value);
|
|
111
|
-
if (matched.size !== byId.size) throw new Error("A query file grant has no result value.");
|
|
112
|
-
return granted;
|
|
113
|
-
};
|
|
114
|
-
//#endregion
|
|
115
|
-
//#region ../contracts/dist/json.js
|
|
116
|
-
const encodeJson = (value) => {
|
|
117
|
-
if (Array$1.isArray(value)) return `[${value.map(encodeJson).join(",")}]`;
|
|
118
|
-
if (value === null || Predicate.isString(value) || Predicate.isNumber(value) || Predicate.isBoolean(value)) return JSON.stringify(value);
|
|
119
|
-
return `{${Array$1.sortWith(Object.entries(value), ([key]) => key, String.Order).map(([key, field]) => `${JSON.stringify(key)}:${encodeJson(field)}`).join(",")}}`;
|
|
120
|
-
};
|
|
121
|
-
const encodeCanonicalJson = (value) => encodeJson(Schema.decodeSync(Schema.Json)(value));
|
|
122
|
-
//#endregion
|
|
123
|
-
//#region src/client/id.ts
|
|
124
|
-
var IdRequestError = class extends Schema.TaggedError()("IdRequestError", { message: Schema.String }) {};
|
|
125
|
-
const outcomeKey = "ignotum.id.outcome";
|
|
126
|
-
const selectionJson = Schema.fromJsonString(DevelopmentSelection);
|
|
127
|
-
var BrowserSession = class BrowserSession extends Context.Service()("ignotum/client/id/BrowserSession") {
|
|
128
|
-
static layer = Layer.effect(BrowserSession, Effect.gen(function* () {
|
|
129
|
-
const client = (yield* HttpClient.HttpClient).pipe(HttpClient.filterStatusOk);
|
|
130
|
-
const ids = yield* IdGenerator;
|
|
131
|
-
const bootstrapLock = yield* Semaphore.make(1);
|
|
132
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
133
|
-
let state = { status: "pending" };
|
|
134
|
-
let current;
|
|
135
|
-
let generation = 0;
|
|
136
|
-
let deadline = Infinity;
|
|
137
|
-
let development = false;
|
|
138
|
-
let selection;
|
|
139
|
-
let expiry;
|
|
140
|
-
const notify = () => {
|
|
141
|
-
for (const listener of listeners) listener();
|
|
142
|
-
};
|
|
143
|
-
const suspend = (error) => {
|
|
144
|
-
generation += 1;
|
|
145
|
-
deadline = Infinity;
|
|
146
|
-
if (expiry !== void 0) clearTimeout(expiry);
|
|
147
|
-
current = void 0;
|
|
148
|
-
state = error === void 0 ? {
|
|
149
|
-
status: "pending",
|
|
150
|
-
outcome: state.outcome
|
|
151
|
-
} : {
|
|
152
|
-
status: "error",
|
|
153
|
-
error,
|
|
154
|
-
outcome: state.outcome
|
|
155
|
-
};
|
|
156
|
-
notify();
|
|
157
|
-
};
|
|
158
|
-
const accept = (session, serverTime) => {
|
|
159
|
-
generation += 1;
|
|
160
|
-
if (expiry !== void 0) clearTimeout(expiry);
|
|
161
|
-
current = session;
|
|
162
|
-
state = session.user === null ? {
|
|
163
|
-
status: "signedOut",
|
|
164
|
-
outcome: state.outcome
|
|
165
|
-
} : {
|
|
166
|
-
status: "signedIn",
|
|
167
|
-
user: session.user,
|
|
168
|
-
outcome: state.outcome
|
|
169
|
-
};
|
|
170
|
-
const delay = Math.max(0, session.validUntil - serverTime);
|
|
171
|
-
deadline = performance.now() + delay;
|
|
172
|
-
if (delay < 2147483647) expiry = setTimeout(() => suspend(), delay);
|
|
173
|
-
notify();
|
|
174
|
-
};
|
|
175
|
-
const checkExpiry = () => {
|
|
176
|
-
if (current !== void 0 && performance.now() >= deadline) suspend();
|
|
177
|
-
};
|
|
178
|
-
globalThis.addEventListener?.("focus", checkExpiry);
|
|
179
|
-
globalThis.document?.addEventListener("visibilitychange", checkExpiry);
|
|
180
|
-
yield* Effect.addFinalizer(() => Effect.sync(() => {
|
|
181
|
-
if (expiry !== void 0) clearTimeout(expiry);
|
|
182
|
-
listeners.clear();
|
|
183
|
-
globalThis.removeEventListener?.("focus", checkExpiry);
|
|
184
|
-
globalThis.document?.removeEventListener("visibilitychange", checkExpiry);
|
|
185
|
-
}));
|
|
186
|
-
const readOutcome = () => {
|
|
187
|
-
const raw = globalThis.sessionStorage.getItem(outcomeKey);
|
|
188
|
-
if (raw !== null) {
|
|
189
|
-
const decoded = Schema.decodeUnknownOption(SessionOutcome)(raw);
|
|
190
|
-
if (Option.isSome(decoded)) state = {
|
|
191
|
-
...state,
|
|
192
|
-
outcome: decoded.value
|
|
193
|
-
};
|
|
194
|
-
globalThis.sessionStorage.removeItem(outcomeKey);
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
const parameters = () => {
|
|
198
|
-
if (!development || selection === void 0) return "";
|
|
199
|
-
const params = new URLSearchParams({ epoch: selection.epoch });
|
|
200
|
-
if (selection.username !== null) params.set("username", selection.username);
|
|
201
|
-
return `?${params}`;
|
|
202
|
-
};
|
|
203
|
-
const readSession = Effect.fn("BrowserSession.read")(function* () {
|
|
204
|
-
return yield* client.get(`${sessionPath}${parameters()}`, { headers: { "x-ignotum-request": "1" } }).pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(SessionResponse)));
|
|
205
|
-
});
|
|
206
|
-
let bootstrapGeneration = 0;
|
|
207
|
-
const bootstrap = bootstrapLock.withPermits(1)(Effect.gen(function* () {
|
|
208
|
-
const admittedGeneration = generation;
|
|
209
|
-
bootstrapGeneration = admittedGeneration;
|
|
210
|
-
const startedAt = performance.now();
|
|
211
|
-
let session = yield* readSession();
|
|
212
|
-
development = session.development === true;
|
|
213
|
-
if (development && selection === void 0) {
|
|
214
|
-
const saved = globalThis.sessionStorage.getItem(developmentSelectionKey);
|
|
215
|
-
const decoded = saved === null ? Option.none() : Schema.decodeOption(selectionJson)(saved);
|
|
216
|
-
selection = Option.getOrElse(decoded, () => ({
|
|
217
|
-
formatVersion: 1,
|
|
218
|
-
username: null,
|
|
219
|
-
epoch: ""
|
|
220
|
-
}));
|
|
221
|
-
if (selection.epoch === "") selection = {
|
|
222
|
-
...selection,
|
|
223
|
-
epoch: yield* ids.generate(SessionEpoch)
|
|
224
|
-
};
|
|
225
|
-
globalThis.sessionStorage.setItem(developmentSelectionKey, Schema.encodeSync(selectionJson)(selection));
|
|
226
|
-
session = yield* readSession();
|
|
227
|
-
}
|
|
228
|
-
if (generation !== admittedGeneration) {
|
|
229
|
-
if (current !== void 0) return current;
|
|
230
|
-
return yield* IdRequestError.make({ message: "Your ID session changed while loading." });
|
|
231
|
-
}
|
|
232
|
-
readOutcome();
|
|
233
|
-
if (session.outcome !== void 0) state = {
|
|
234
|
-
...state,
|
|
235
|
-
outcome: session.outcome
|
|
236
|
-
};
|
|
237
|
-
accept(session, session.serverTime + performance.now() - startedAt);
|
|
238
|
-
return session;
|
|
239
|
-
})).pipe(Effect.mapError(() => IdRequestError.make({ message: "Could not load your ID session." })), Effect.tapError((error) => Effect.sync(() => {
|
|
240
|
-
if (generation === bootstrapGeneration) suspend(error.message);
|
|
241
|
-
})));
|
|
242
|
-
const start = Effect.fn("BrowserSession.start")(function* (intent, profile, returnTo) {
|
|
243
|
-
const session = current ?? (yield* bootstrap);
|
|
244
|
-
if (intent === "requestProfile" && session.user === null) return yield* IdRequestError.make({ message: "Sign in before requesting profile information." });
|
|
245
|
-
const request = yield* Schema.decodeUnknownEffect(SessionRequest)({
|
|
246
|
-
intent,
|
|
247
|
-
profile,
|
|
248
|
-
sessionEpoch: session.sessionEpoch,
|
|
249
|
-
returnTo: returnTo ?? `${globalThis.location.pathname}${globalThis.location.search}${globalThis.location.hash}`
|
|
250
|
-
}).pipe(Effect.mapError(() => IdRequestError.make({ message: "The ID request is invalid." })));
|
|
251
|
-
const redirect = yield* HttpClientRequest.post(sessionRequestsPath).pipe(HttpClientRequest.setHeader("x-ignotum-request", "1"), HttpClientRequest.bodyJsonUnsafe(request), client.execute, Effect.flatMap(HttpClientResponse.schemaBodyJson(SessionRedirect)), Effect.mapError(() => IdRequestError.make({ message: "Could not start the ID request." })));
|
|
252
|
-
if (current?.sessionEpoch !== session.sessionEpoch) return yield* IdRequestError.make({ message: "Your ID session changed. Try again." });
|
|
253
|
-
globalThis.location.assign(redirect.redirectUrl);
|
|
254
|
-
});
|
|
255
|
-
const signOut = Effect.gen(function* () {
|
|
256
|
-
const session = current ?? (yield* bootstrap);
|
|
257
|
-
yield* HttpClientRequest.delete(sessionPath).pipe(HttpClientRequest.setHeader("x-ignotum-request", "1"), HttpClientRequest.bodyJsonUnsafe({ sessionEpoch: session.sessionEpoch }), client.execute, Effect.mapError(() => IdRequestError.make({ message: "Could not sign out." })));
|
|
258
|
-
suspend();
|
|
259
|
-
if (development) {
|
|
260
|
-
selection = {
|
|
261
|
-
formatVersion: 1,
|
|
262
|
-
username: null,
|
|
263
|
-
epoch: yield* ids.generate(SessionEpoch)
|
|
264
|
-
};
|
|
265
|
-
globalThis.sessionStorage.setItem(developmentSelectionKey, Schema.encodeSync(selectionJson)(selection));
|
|
266
|
-
}
|
|
267
|
-
globalThis.location.reload();
|
|
268
|
-
});
|
|
269
|
-
return BrowserSession.of({
|
|
270
|
-
snapshot: () => {
|
|
271
|
-
checkExpiry();
|
|
272
|
-
return state;
|
|
273
|
-
},
|
|
274
|
-
current: () => {
|
|
275
|
-
checkExpiry();
|
|
276
|
-
return current;
|
|
277
|
-
},
|
|
278
|
-
subscribe: (listener) => {
|
|
279
|
-
listeners.add(listener);
|
|
280
|
-
return () => {
|
|
281
|
-
listeners.delete(listener);
|
|
282
|
-
};
|
|
283
|
-
},
|
|
284
|
-
accept,
|
|
285
|
-
suspend,
|
|
286
|
-
bootstrap,
|
|
287
|
-
start,
|
|
288
|
-
signOut,
|
|
289
|
-
socketParameters: parameters
|
|
290
|
-
});
|
|
291
|
-
})).pipe(Layer.provide(FetchHttpClient.layer));
|
|
292
|
-
};
|
|
293
|
-
//#endregion
|
|
294
|
-
//#region src/client/errors.ts
|
|
295
|
-
/** @effect-diagnostics globalConsole:skip-file */
|
|
296
|
-
var ConnectionUnavailable = class extends Schema.TaggedError()("ConnectionUnavailable", {
|
|
297
|
-
cause: Schema.optional(Schema.Defect()),
|
|
298
|
-
message: Schema.String
|
|
299
|
-
}) {};
|
|
300
|
-
var InvalidClientMessage = class extends Schema.TaggedError()("InvalidClientMessage", {
|
|
301
|
-
cause: Schema.Defect(),
|
|
302
|
-
message: Schema.String
|
|
303
|
-
}) {};
|
|
304
|
-
var InvalidMutationArguments = class extends Schema.TaggedError()("InvalidMutationArguments", {
|
|
305
|
-
cause: Schema.Defect(),
|
|
306
|
-
function: FunctionAddress,
|
|
307
|
-
message: Schema.String
|
|
308
|
-
}) {};
|
|
309
|
-
var InvalidServerMessage = class extends Schema.TaggedError()("InvalidServerMessage", {
|
|
310
|
-
cause: Schema.Defect(),
|
|
311
|
-
message: Schema.String
|
|
312
|
-
}) {};
|
|
313
|
-
var ServerError = class extends Schema.TaggedError()("ServerError", {
|
|
314
|
-
code: ErrorCode,
|
|
315
|
-
message: Schema.String,
|
|
316
|
-
operation: Schema.optional(Operation)
|
|
317
|
-
}) {};
|
|
318
|
-
const ClientInfrastructureError = Schema.Union([
|
|
319
|
-
ConnectionUnavailable,
|
|
320
|
-
InvalidClientMessage,
|
|
321
|
-
InvalidMutationArguments,
|
|
322
|
-
InvalidServerMessage,
|
|
323
|
-
ServerError
|
|
324
|
-
]);
|
|
325
|
-
const browserErrorReporter = ErrorReporter.make(({ attributes, error }) => {
|
|
326
|
-
globalThis.console.error("Ignotum infrastructure error", error, attributes);
|
|
327
|
-
});
|
|
328
|
-
const clientErrorReporterLayer = ErrorReporter.layer([browserErrorReporter]);
|
|
329
|
-
const reportClientError = Effect.fn("ClientErrorReporter.report")(function* (error) {
|
|
330
|
-
yield* ErrorReporter.report(Cause.fail(error));
|
|
331
|
-
});
|
|
332
|
-
//#endregion
|
|
333
9
|
//#region src/client/query.ts
|
|
334
10
|
const QuerySkipTypeId = Symbol.for("ignotum/client/QuerySkip");
|
|
335
11
|
var QuerySkipToken = class {
|
|
@@ -339,807 +15,6 @@ const skip = Object.freeze(new QuerySkipToken());
|
|
|
339
15
|
const Query = { skip };
|
|
340
16
|
const isQuerySkip = (value) => value === skip;
|
|
341
17
|
//#endregion
|
|
342
|
-
//#region ../contracts/dist/runtime/index.js
|
|
343
|
-
const IndexIdentity = Schema.String.pipe(Schema.brand("ignotum/runtime/IndexIdentity"));
|
|
344
|
-
const EncodedIndexKey = Schema.String.check(Schema.isPattern(/^(?:[0-9a-f]{2})*$/)).pipe(Schema.brand("ignotum/runtime/EncodedIndexKey"));
|
|
345
|
-
Schema.Union([
|
|
346
|
-
Schema.Boolean,
|
|
347
|
-
Schema.Finite,
|
|
348
|
-
Schema.String
|
|
349
|
-
]);
|
|
350
|
-
Schema.String.pipe(Schema.brand("ignotum/hosted/QueryKey"));
|
|
351
|
-
const TableDependency = Schema.Struct({
|
|
352
|
-
type: Schema.Literal("Table"),
|
|
353
|
-
tableId: TableId
|
|
354
|
-
});
|
|
355
|
-
const DocumentDependency = Schema.Struct({
|
|
356
|
-
type: Schema.Literal("Document"),
|
|
357
|
-
tableId: TableId,
|
|
358
|
-
id: GeneratedId
|
|
359
|
-
});
|
|
360
|
-
const IndexRangeDependency = Schema.Struct({
|
|
361
|
-
type: Schema.Literal("IndexRange"),
|
|
362
|
-
tableId: TableId,
|
|
363
|
-
index: IndexIdentity,
|
|
364
|
-
lower: Schema.optional(EncodedIndexKey),
|
|
365
|
-
upper: Schema.optional(EncodedIndexKey)
|
|
366
|
-
});
|
|
367
|
-
const IndexPointInvalidation = Schema.Struct({
|
|
368
|
-
type: Schema.Literal("IndexPoint"),
|
|
369
|
-
tableId: TableId,
|
|
370
|
-
index: IndexIdentity,
|
|
371
|
-
key: EncodedIndexKey
|
|
372
|
-
});
|
|
373
|
-
const IdDependency = Schema.Struct({ type: Schema.Literal("Id") });
|
|
374
|
-
const ReadDependency = Schema.Union([
|
|
375
|
-
IdDependency,
|
|
376
|
-
TableDependency,
|
|
377
|
-
DocumentDependency,
|
|
378
|
-
IndexRangeDependency
|
|
379
|
-
]);
|
|
380
|
-
const WriteInvalidation = Schema.Union([
|
|
381
|
-
TableDependency,
|
|
382
|
-
DocumentDependency,
|
|
383
|
-
IndexPointInvalidation
|
|
384
|
-
]);
|
|
385
|
-
Schema.Union([ReadDependency, IndexPointInvalidation]);
|
|
386
|
-
const DependencySet = Schema.Array(ReadDependency);
|
|
387
|
-
const InvalidationSet = Schema.Array(WriteInvalidation);
|
|
388
|
-
const RuntimeQueryResult = Schema.Struct({
|
|
389
|
-
type: Schema.Literal("Query"),
|
|
390
|
-
result: WireResult,
|
|
391
|
-
dependencies: DependencySet,
|
|
392
|
-
observedRevision: AppStateRevision,
|
|
393
|
-
files: Schema.optional(Schema.Array(RuntimeFileOccurrence))
|
|
394
|
-
});
|
|
395
|
-
const FileReferenceAdded = Schema.Struct({
|
|
396
|
-
type: Schema.Literal("AddReference"),
|
|
397
|
-
file: RuntimeFileMetadata,
|
|
398
|
-
tableId: TableId,
|
|
399
|
-
documentId: GeneratedId
|
|
400
|
-
});
|
|
401
|
-
const FileReferenceRemoved = Schema.Struct({
|
|
402
|
-
type: Schema.Literal("RemoveReference"),
|
|
403
|
-
fileId: FileId,
|
|
404
|
-
tableId: TableId,
|
|
405
|
-
documentId: GeneratedId
|
|
406
|
-
});
|
|
407
|
-
const FileReferenceEffect = Schema.Union([FileReferenceAdded, FileReferenceRemoved]);
|
|
408
|
-
const FileEffectBatch = Schema.Struct({
|
|
409
|
-
id: InvocationId,
|
|
410
|
-
committedRevision: AppStateRevision,
|
|
411
|
-
effects: Schema.Array(FileReferenceEffect)
|
|
412
|
-
});
|
|
413
|
-
Schema.Struct({ appId: AppId });
|
|
414
|
-
Schema.Struct({ batches: Schema.Array(FileEffectBatch) });
|
|
415
|
-
Schema.Struct({
|
|
416
|
-
appId: AppId,
|
|
417
|
-
invocationId: InvocationId,
|
|
418
|
-
acknowledgedAt: Schema.Int
|
|
419
|
-
});
|
|
420
|
-
Schema.Struct({ completed: Schema.Literal(true) });
|
|
421
|
-
const RuntimeMutationSuccess = Schema.Struct({
|
|
422
|
-
type: Schema.Literal("Mutation"),
|
|
423
|
-
result: WireSuccess,
|
|
424
|
-
invalidations: InvalidationSet,
|
|
425
|
-
committedRevision: AppStateRevision,
|
|
426
|
-
fileEffects: Schema.optional(FileEffectBatch)
|
|
427
|
-
});
|
|
428
|
-
const RuntimeMutationFailure = Schema.Struct({
|
|
429
|
-
type: Schema.Literal("Mutation"),
|
|
430
|
-
result: WireFailure
|
|
431
|
-
});
|
|
432
|
-
const RuntimeMutationResult = Schema.Union([RuntimeMutationSuccess, RuntimeMutationFailure]);
|
|
433
|
-
Schema.Union([RuntimeQueryResult, RuntimeMutationResult]);
|
|
434
|
-
const InvocationBase = {
|
|
435
|
-
appId: AppId,
|
|
436
|
-
deploymentId: DeploymentId,
|
|
437
|
-
generation: DeploymentGeneration,
|
|
438
|
-
invocationKey: InvocationKey,
|
|
439
|
-
function: FunctionAddress,
|
|
440
|
-
args: Schema.Json,
|
|
441
|
-
identity: Schema.optional(SessionState)
|
|
442
|
-
};
|
|
443
|
-
const QueryInvocation = Schema.Struct({
|
|
444
|
-
...InvocationBase,
|
|
445
|
-
type: Schema.Literal("Query")
|
|
446
|
-
});
|
|
447
|
-
const MutationInvocation = Schema.Struct({
|
|
448
|
-
...InvocationBase,
|
|
449
|
-
type: Schema.Literal("Mutation"),
|
|
450
|
-
invocationId: InvocationId,
|
|
451
|
-
files: Schema.optional(Schema.Array(RuntimeFileOccurrence))
|
|
452
|
-
});
|
|
453
|
-
Schema.Union([QueryInvocation, MutationInvocation]);
|
|
454
|
-
Schema.Struct({
|
|
455
|
-
appId: AppId,
|
|
456
|
-
expectedRevision: AppStateRevision
|
|
457
|
-
});
|
|
458
|
-
Schema.Struct({ currentRevision: AppStateRevision });
|
|
459
|
-
var RuntimeDeploymentUnavailable = class extends Schema.TaggedError()("RuntimeDeploymentUnavailable", {
|
|
460
|
-
deploymentId: DeploymentId,
|
|
461
|
-
message: Schema.String
|
|
462
|
-
}) {};
|
|
463
|
-
const RuntimeInvocationRejectionCode = Schema.Literals([
|
|
464
|
-
"SessionExpired",
|
|
465
|
-
"FunctionUnavailable",
|
|
466
|
-
"InvalidArguments",
|
|
467
|
-
"InvocationIdConflict",
|
|
468
|
-
"ResourceLimitExceeded",
|
|
469
|
-
"UnknownFunction",
|
|
470
|
-
"WrongFunctionKind"
|
|
471
|
-
]);
|
|
472
|
-
var RuntimeInvocationRejected = class extends Schema.TaggedError()("RuntimeInvocationRejected", {
|
|
473
|
-
code: RuntimeInvocationRejectionCode,
|
|
474
|
-
invocationKey: InvocationKey,
|
|
475
|
-
message: Schema.String
|
|
476
|
-
}) {};
|
|
477
|
-
var RuntimeInvocationUnavailable = class extends Schema.TaggedError()("RuntimeInvocationUnavailable", {
|
|
478
|
-
invocationKey: InvocationKey,
|
|
479
|
-
message: Schema.String
|
|
480
|
-
}) {};
|
|
481
|
-
Schema.TaggedError()("RuntimeRevisionRejected", {
|
|
482
|
-
appId: AppId,
|
|
483
|
-
message: Schema.String
|
|
484
|
-
});
|
|
485
|
-
Schema.Union([
|
|
486
|
-
RuntimeDeploymentUnavailable,
|
|
487
|
-
RuntimeInvocationRejected,
|
|
488
|
-
RuntimeInvocationUnavailable
|
|
489
|
-
]);
|
|
490
|
-
//#endregion
|
|
491
|
-
//#region ../contracts/dist/runtime/functions.js
|
|
492
|
-
const FunctionKind = Schema.Literals(["Mutation", "Query"]);
|
|
493
|
-
Schema.TaggedError()("UnknownFunction", {
|
|
494
|
-
function: FunctionAddress,
|
|
495
|
-
message: Schema.String
|
|
496
|
-
});
|
|
497
|
-
Schema.TaggedError()("WrongFunctionKind", {
|
|
498
|
-
actual: FunctionKind,
|
|
499
|
-
expected: FunctionKind,
|
|
500
|
-
function: FunctionAddress,
|
|
501
|
-
message: Schema.String
|
|
502
|
-
});
|
|
503
|
-
Schema.TaggedError()("InvalidArguments", {
|
|
504
|
-
function: FunctionAddress,
|
|
505
|
-
message: Schema.String
|
|
506
|
-
});
|
|
507
|
-
Schema.TaggedError()("FunctionUnavailable", {
|
|
508
|
-
cause: Schema.Defect(),
|
|
509
|
-
function: FunctionAddress,
|
|
510
|
-
message: Schema.String
|
|
511
|
-
});
|
|
512
|
-
//#endregion
|
|
513
|
-
//#region ../contracts/dist/deployment.js
|
|
514
|
-
const ArtifactPath = Schema.String.check(Schema.isPattern(/^(?!\/)(?![A-Za-z]:\/)(?!.*(?:^|\/)\.\.(?:\/|$))(?!.*(?:^|\/)\.(?:\/|$))(?!.*\/\/)[^\\\0]+$/)).pipe(Schema.brand("ignotum/deployment/ArtifactPath"));
|
|
515
|
-
const ClientPath = Schema.String.check(Schema.isPattern(/^\/(?!_ignotum(?:\/|$))(?:(?:[A-Za-z0-9._~-]+\/)*[A-Za-z0-9._~-]+\/?)?$/)).pipe(Schema.brand("ignotum/deployment/ClientPath"));
|
|
516
|
-
const Sha256 = Schema.String.check(Schema.isPattern(/^[0-9a-f]{64}$/)).pipe(Schema.brand("ignotum/deployment/Sha256"));
|
|
517
|
-
const ArtifactKind = Schema.Literals([
|
|
518
|
-
"ClientAsset",
|
|
519
|
-
"ClientDocument",
|
|
520
|
-
"ClientManifest",
|
|
521
|
-
"ClientPublicFile",
|
|
522
|
-
"ClientShell",
|
|
523
|
-
"FunctionBundle",
|
|
524
|
-
"ServerManifest",
|
|
525
|
-
"ServerEnvironment",
|
|
526
|
-
"SourceMap",
|
|
527
|
-
"SchemaSnapshot"
|
|
528
|
-
]);
|
|
529
|
-
const ArtifactReference = Schema.Struct({
|
|
530
|
-
path: ArtifactPath,
|
|
531
|
-
size: Schema.Natural,
|
|
532
|
-
sha256: Sha256
|
|
533
|
-
});
|
|
534
|
-
const ArtifactFile = Schema.Struct({
|
|
535
|
-
path: ArtifactPath,
|
|
536
|
-
size: Schema.Natural,
|
|
537
|
-
sha256: Sha256,
|
|
538
|
-
kind: ArtifactKind,
|
|
539
|
-
contentType: Schema.String,
|
|
540
|
-
contentEncoding: Schema.optional(Schema.String)
|
|
541
|
-
});
|
|
542
|
-
const ClientRoute = Schema.Struct({
|
|
543
|
-
pathname: ClientPath,
|
|
544
|
-
artifact: ArtifactReference
|
|
545
|
-
});
|
|
546
|
-
const DeploymentInventoryV1 = Schema.Struct({
|
|
547
|
-
formatVersion: Schema.Literal(1),
|
|
548
|
-
files: Schema.Array(ArtifactFile)
|
|
549
|
-
});
|
|
550
|
-
const DeploymentInventoryV2 = Schema.Struct({
|
|
551
|
-
formatVersion: Schema.Literal(2),
|
|
552
|
-
files: Schema.Array(ArtifactFile)
|
|
553
|
-
});
|
|
554
|
-
upgrade(initial(DeploymentInventoryV1), DeploymentInventoryV2, (inventory) => ({
|
|
555
|
-
formatVersion: 2,
|
|
556
|
-
files: inventory.files
|
|
557
|
-
}));
|
|
558
|
-
const ClientManifestV1 = Schema.Struct({
|
|
559
|
-
formatVersion: Schema.Literal(1),
|
|
560
|
-
shell: ArtifactReference,
|
|
561
|
-
routes: Schema.Array(ClientRoute)
|
|
562
|
-
});
|
|
563
|
-
initial(ClientManifestV1);
|
|
564
|
-
const ClientRoutingRoute = Schema.Struct({
|
|
565
|
-
pathname: ClientPath,
|
|
566
|
-
artifact: ArtifactPath
|
|
567
|
-
});
|
|
568
|
-
const ClientRoutingV1 = Schema.Struct({
|
|
569
|
-
formatVersion: Schema.Literal(1),
|
|
570
|
-
shell: ArtifactPath,
|
|
571
|
-
routes: Schema.Array(ClientRoutingRoute)
|
|
572
|
-
});
|
|
573
|
-
initial(ClientRoutingV1);
|
|
574
|
-
const SchemaSnapshotField = Schema.Struct({
|
|
575
|
-
name: Schema.String,
|
|
576
|
-
value: ValueDescriptor
|
|
577
|
-
});
|
|
578
|
-
const EnvironmentArtifactV1 = Schema.Struct({
|
|
579
|
-
formatVersion: Schema.Literal(1),
|
|
580
|
-
nonce: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9_-]{43}$/)),
|
|
581
|
-
values: Schema.Record(Schema.String, Schema.String)
|
|
582
|
-
});
|
|
583
|
-
initial(EnvironmentArtifactV1);
|
|
584
|
-
const ServerEnvironmentArtifact = Schema.Struct({
|
|
585
|
-
artifact: ArtifactReference,
|
|
586
|
-
fields: Schema.Array(SchemaSnapshotField)
|
|
587
|
-
});
|
|
588
|
-
const SchemaSnapshotIndex = Schema.Struct({
|
|
589
|
-
name: Schema.String,
|
|
590
|
-
fields: Schema.Array(Schema.String)
|
|
591
|
-
});
|
|
592
|
-
const SchemaSnapshotTableV1 = Schema.Struct({
|
|
593
|
-
name: Schema.String,
|
|
594
|
-
fields: Schema.Array(SchemaSnapshotField)
|
|
595
|
-
});
|
|
596
|
-
const SchemaSnapshotV1 = Schema.Struct({
|
|
597
|
-
formatVersion: Schema.Literal(1),
|
|
598
|
-
tables: Schema.Array(SchemaSnapshotTableV1)
|
|
599
|
-
});
|
|
600
|
-
const SchemaSnapshotTable = Schema.Struct({
|
|
601
|
-
name: Schema.String,
|
|
602
|
-
fields: Schema.Array(SchemaSnapshotField),
|
|
603
|
-
indexes: Schema.Array(SchemaSnapshotIndex)
|
|
604
|
-
});
|
|
605
|
-
const SchemaSnapshotV2 = Schema.Struct({
|
|
606
|
-
formatVersion: Schema.Literal(2),
|
|
607
|
-
tables: Schema.Array(SchemaSnapshotTable)
|
|
608
|
-
});
|
|
609
|
-
upgrade(initial(SchemaSnapshotV1), SchemaSnapshotV2, (snapshot) => ({
|
|
610
|
-
formatVersion: 2,
|
|
611
|
-
tables: snapshot.tables.map((table) => ({
|
|
612
|
-
...table,
|
|
613
|
-
indexes: []
|
|
614
|
-
}))
|
|
615
|
-
}));
|
|
616
|
-
const ServerFunctionArtifactV1 = Schema.Struct({
|
|
617
|
-
address: FunctionAddress,
|
|
618
|
-
kind: FunctionKind,
|
|
619
|
-
bundle: ArtifactReference,
|
|
620
|
-
sourceMap: ArtifactReference
|
|
621
|
-
});
|
|
622
|
-
const ServerFunctionArtifact = Schema.Struct({
|
|
623
|
-
address: FunctionAddress,
|
|
624
|
-
kind: FunctionKind,
|
|
625
|
-
args: Schema.optional(ValueDescriptor),
|
|
626
|
-
returns: Schema.optional(ValueDescriptor),
|
|
627
|
-
errors: Schema.optional(ValueDescriptor),
|
|
628
|
-
bundle: ArtifactReference,
|
|
629
|
-
sourceMap: ArtifactReference
|
|
630
|
-
});
|
|
631
|
-
const ServerBuildManifestV1 = Schema.Struct({
|
|
632
|
-
formatVersion: Schema.Literal(1),
|
|
633
|
-
schema: ArtifactReference,
|
|
634
|
-
functions: Schema.Array(ServerFunctionArtifactV1)
|
|
635
|
-
});
|
|
636
|
-
const ServerBuildManifestV2 = Schema.Struct({
|
|
637
|
-
formatVersion: Schema.Literal(2),
|
|
638
|
-
schema: ArtifactReference,
|
|
639
|
-
functions: Schema.Array(ServerFunctionArtifact)
|
|
640
|
-
});
|
|
641
|
-
const ServerBuildManifestThroughV2 = upgrade(initial(ServerBuildManifestV1), ServerBuildManifestV2, (manifest) => ({
|
|
642
|
-
formatVersion: 2,
|
|
643
|
-
schema: manifest.schema,
|
|
644
|
-
functions: manifest.functions
|
|
645
|
-
}));
|
|
646
|
-
const ServerBuildManifestV3 = Schema.Struct({
|
|
647
|
-
formatVersion: Schema.Literal(3),
|
|
648
|
-
schema: ArtifactReference,
|
|
649
|
-
environment: Schema.optional(ServerEnvironmentArtifact),
|
|
650
|
-
functions: Schema.Array(ServerFunctionArtifact)
|
|
651
|
-
});
|
|
652
|
-
upgrade(ServerBuildManifestThroughV2, ServerBuildManifestV3, (manifest) => ({
|
|
653
|
-
formatVersion: 3,
|
|
654
|
-
schema: manifest.schema,
|
|
655
|
-
functions: manifest.functions
|
|
656
|
-
}));
|
|
657
|
-
ArtifactPath.make("inventory.json");
|
|
658
|
-
ArtifactPath.make("client/manifest.json");
|
|
659
|
-
ArtifactPath.make("client/shell.html");
|
|
660
|
-
`${ArtifactPath.make("client/assets")}`;
|
|
661
|
-
`${ArtifactPath.make("client/routes")}`;
|
|
662
|
-
ArtifactPath.make("server/manifest.json");
|
|
663
|
-
ArtifactPath.make("server/schema.json");
|
|
664
|
-
ArtifactPath.make("server/environment.json");
|
|
665
|
-
//#endregion
|
|
666
|
-
//#region ../contracts/dist/runtime/transport.js
|
|
667
|
-
const runtimeInvocationPath = "/v1/invoke";
|
|
668
|
-
const runtimeRevisionPath = "/v1/revision";
|
|
669
|
-
const runtimeIndexPreparePath = "/v1/indexes/prepare";
|
|
670
|
-
const runtimeIndexCommitPath = "/v1/indexes/commit";
|
|
671
|
-
const runtimeFileEffectsPath = "/v1/files/effects";
|
|
672
|
-
const runtimeFileEffectsAcknowledgePath = "/v1/files/effects/acknowledge";
|
|
673
|
-
const appSyncPath = `/_ignotum/v1/sync`;
|
|
674
|
-
const RuntimeRequestPath = Schema.Literals([
|
|
675
|
-
runtimeInvocationPath,
|
|
676
|
-
runtimeRevisionPath,
|
|
677
|
-
runtimeIndexPreparePath,
|
|
678
|
-
runtimeIndexCommitPath,
|
|
679
|
-
runtimeFileEffectsPath,
|
|
680
|
-
runtimeFileEffectsAcknowledgePath
|
|
681
|
-
]);
|
|
682
|
-
const RuntimeRequestTimestamp = Schema.FiniteFromString.pipe(Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0)), Schema.brand("ignotum/runtime/RequestTimestamp"));
|
|
683
|
-
const RuntimeRequestSignature = Sha256.pipe(Schema.brand("ignotum/runtime/RequestSignature"));
|
|
684
|
-
Schema.Struct({
|
|
685
|
-
appId: AppId,
|
|
686
|
-
deploymentId: Schema.optional(DeploymentId),
|
|
687
|
-
nonce: RuntimeRequestNonce,
|
|
688
|
-
timestamp: RuntimeRequestTimestamp,
|
|
689
|
-
signature: RuntimeRequestSignature
|
|
690
|
-
});
|
|
691
|
-
Schema.Struct({
|
|
692
|
-
method: Schema.Literal("POST"),
|
|
693
|
-
path: RuntimeRequestPath,
|
|
694
|
-
timestamp: RuntimeRequestTimestamp,
|
|
695
|
-
nonce: RuntimeRequestNonce,
|
|
696
|
-
appId: AppId,
|
|
697
|
-
deploymentId: Schema.optional(DeploymentId),
|
|
698
|
-
bodySha256: Sha256
|
|
699
|
-
});
|
|
700
|
-
Schema.Struct({
|
|
701
|
-
appId: AppId,
|
|
702
|
-
deploymentId: DeploymentId
|
|
703
|
-
});
|
|
704
|
-
Schema.Struct({ completed: Schema.Literal(true) });
|
|
705
|
-
const RuntimeErrorCode = Schema.Literals([
|
|
706
|
-
"InvalidRequest",
|
|
707
|
-
"InvalidSignature",
|
|
708
|
-
"RequestExpired",
|
|
709
|
-
"RequestReplay",
|
|
710
|
-
"InvocationRejected",
|
|
711
|
-
"RuntimeUnavailable"
|
|
712
|
-
]);
|
|
713
|
-
Schema.Struct({
|
|
714
|
-
code: RuntimeErrorCode,
|
|
715
|
-
message: Schema.String,
|
|
716
|
-
rejectionCode: Schema.optional(RuntimeInvocationRejectionCode)
|
|
717
|
-
});
|
|
718
|
-
//#endregion
|
|
719
|
-
//#region src/internal/http-paths.ts
|
|
720
|
-
const syncPath = appSyncPath;
|
|
721
|
-
//#endregion
|
|
722
|
-
//#region src/client/sync.ts
|
|
723
|
-
const queryKey = (functionAddress, args) => encodeCanonicalJson([functionAddress, args]);
|
|
724
|
-
const subscribeMessage = (entry) => ({
|
|
725
|
-
type: "Subscribe",
|
|
726
|
-
id: entry.subscriptionId,
|
|
727
|
-
function: entry.function,
|
|
728
|
-
args: entry.args
|
|
729
|
-
});
|
|
730
|
-
const makeQueryCache = (allocateId, sendLifecycleMessage) => {
|
|
731
|
-
const queries = /* @__PURE__ */ new Map();
|
|
732
|
-
const queriesById = /* @__PURE__ */ new Map();
|
|
733
|
-
const observe = Effect.fn("SyncClient.QueryCache.observe")(function* (functionAddress, args) {
|
|
734
|
-
const key = queryKey(functionAddress, args);
|
|
735
|
-
let entry = queries.get(key);
|
|
736
|
-
if (entry === void 0) {
|
|
737
|
-
const created = {
|
|
738
|
-
args,
|
|
739
|
-
function: functionAddress,
|
|
740
|
-
generation: 0,
|
|
741
|
-
listeners: /* @__PURE__ */ new Set(),
|
|
742
|
-
revision: void 0,
|
|
743
|
-
references: 0,
|
|
744
|
-
result: pending(),
|
|
745
|
-
subscriptionId: yield* allocateId
|
|
746
|
-
};
|
|
747
|
-
queries.set(key, created);
|
|
748
|
-
queriesById.set(created.subscriptionId, created);
|
|
749
|
-
yield* sendLifecycleMessage(subscribeMessage(created));
|
|
750
|
-
entry = created;
|
|
751
|
-
}
|
|
752
|
-
const observed = entry;
|
|
753
|
-
observed.references += 1;
|
|
754
|
-
observed.generation += 1;
|
|
755
|
-
let released = false;
|
|
756
|
-
return {
|
|
757
|
-
getSnapshot: () => observed.result,
|
|
758
|
-
subscribe: (listener) => {
|
|
759
|
-
observed.listeners.add(listener);
|
|
760
|
-
return () => observed.listeners.delete(listener);
|
|
761
|
-
},
|
|
762
|
-
release: Effect.gen(function* () {
|
|
763
|
-
if (released) return;
|
|
764
|
-
released = true;
|
|
765
|
-
observed.references -= 1;
|
|
766
|
-
if (observed.references !== 0) return;
|
|
767
|
-
const generation = ++observed.generation;
|
|
768
|
-
yield* Effect.sleep("25 millis");
|
|
769
|
-
if (observed.references !== 0 || observed.generation !== generation || queries.get(key) !== observed) return;
|
|
770
|
-
queries.delete(key);
|
|
771
|
-
queriesById.delete(observed.subscriptionId);
|
|
772
|
-
yield* sendLifecycleMessage({
|
|
773
|
-
type: "Unsubscribe",
|
|
774
|
-
id: observed.subscriptionId
|
|
775
|
-
});
|
|
776
|
-
})
|
|
777
|
-
};
|
|
778
|
-
});
|
|
779
|
-
const clear = (entry) => {
|
|
780
|
-
entry.result = pending();
|
|
781
|
-
entry.revision = void 0;
|
|
782
|
-
for (const listener of entry.listeners) listener();
|
|
783
|
-
};
|
|
784
|
-
return {
|
|
785
|
-
invalidate: (ids) => {
|
|
786
|
-
for (const entry of queries.values()) if (ids === void 0 || ids.includes(entry.subscriptionId)) clear(entry);
|
|
787
|
-
},
|
|
788
|
-
invalidatePrivate: () => {
|
|
789
|
-
for (const entry of queries.values()) if (entry.dependsOnId !== false) clear(entry);
|
|
790
|
-
},
|
|
791
|
-
entries: () => queries.values(),
|
|
792
|
-
getById: (id) => queriesById.get(id),
|
|
793
|
-
observe,
|
|
794
|
-
setResult: (id, result, revision) => {
|
|
795
|
-
const entry = queriesById.get(id);
|
|
796
|
-
if (entry === void 0) return;
|
|
797
|
-
if (revision !== void 0) {
|
|
798
|
-
if (entry.revision !== void 0 && revision < entry.revision) return;
|
|
799
|
-
entry.revision = revision;
|
|
800
|
-
}
|
|
801
|
-
entry.result = result;
|
|
802
|
-
for (const listener of entry.listeners) listener();
|
|
803
|
-
}
|
|
804
|
-
};
|
|
805
|
-
};
|
|
806
|
-
const resultFromWire = Effect.fn("SyncClient.resultFromWire")((wire, files = []) => Effect.try({
|
|
807
|
-
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),
|
|
808
|
-
catch: (cause) => InvalidServerMessage.make({
|
|
809
|
-
cause,
|
|
810
|
-
message: "The server returned an invalid function result."
|
|
811
|
-
})
|
|
812
|
-
}));
|
|
813
|
-
const shouldReloadForCloseCode = (code) => code === DeploymentCloseCode;
|
|
814
|
-
const handshakesMatch = (first, next) => first.appId === next.appId && first.deploymentId === next.deploymentId && first.generation === next.generation;
|
|
815
|
-
const handshakeDecision = (remembered, acceptedOnConnection, next) => {
|
|
816
|
-
if (remembered !== void 0 && !handshakesMatch(remembered, next)) return "Reload";
|
|
817
|
-
return acceptedOnConnection ? "Ignore" : "Accept";
|
|
818
|
-
};
|
|
819
|
-
const syncClientInternals = {
|
|
820
|
-
makeQueryCache,
|
|
821
|
-
handshakeDecision,
|
|
822
|
-
queryIdentity: queryKey,
|
|
823
|
-
resultFromWire,
|
|
824
|
-
handshakesMatch,
|
|
825
|
-
shouldReloadForCloseCode
|
|
826
|
-
};
|
|
827
|
-
const socketUrl = () => {
|
|
828
|
-
const url = new URL(syncPath, globalThis.location.href);
|
|
829
|
-
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
830
|
-
return url.href;
|
|
831
|
-
};
|
|
832
|
-
var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync/SyncClient") {
|
|
833
|
-
static layer = Layer.effect(SyncClient, Effect.gen(function* () {
|
|
834
|
-
const ids = yield* IdGenerator;
|
|
835
|
-
const session = yield* BrowserSession;
|
|
836
|
-
let invocations = HashMap.empty();
|
|
837
|
-
let rememberedHandshake;
|
|
838
|
-
let reloadRequested = false;
|
|
839
|
-
let writer;
|
|
840
|
-
let sessionSuspended;
|
|
841
|
-
const encode = (message) => Schema.encodeEffect(ClientMessageJson)(message).pipe(Effect.mapError((cause) => InvalidClientMessage.make({
|
|
842
|
-
cause,
|
|
843
|
-
message: "Could not encode an Ignotum sync message."
|
|
844
|
-
})));
|
|
845
|
-
const sendWith = (write, message) => encode(message).pipe(Effect.flatMap(write), Effect.mapError((cause) => Schema.is(InvalidClientMessage)(cause) ? cause : ConnectionUnavailable.make({
|
|
846
|
-
cause,
|
|
847
|
-
message: "The sync connection was lost."
|
|
848
|
-
})));
|
|
849
|
-
const send = (message) => writer === void 0 ? Effect.fail(ConnectionUnavailable.make({ message: "The sync connection is not ready." })) : sendWith(writer, message);
|
|
850
|
-
const queryCache = makeQueryCache(ids.generate(SubscriptionId), (message) => writer === void 0 ? Effect.void : send(message).pipe(Effect.catchTags({
|
|
851
|
-
ConnectionUnavailable: reportClientError,
|
|
852
|
-
InvalidClientMessage: reportClientError
|
|
853
|
-
})));
|
|
854
|
-
const unsubscribeSession = session.subscribe(() => {
|
|
855
|
-
if (session.current() === void 0) {
|
|
856
|
-
queryCache.invalidatePrivate();
|
|
857
|
-
writer = void 0;
|
|
858
|
-
if (sessionSuspended !== void 0) Deferred.doneUnsafe(sessionSuspended, Effect.void);
|
|
859
|
-
}
|
|
860
|
-
});
|
|
861
|
-
yield* Effect.addFinalizer(() => Effect.sync(unsubscribeSession));
|
|
862
|
-
const rejectInvocation = (id, error) => {
|
|
863
|
-
const pendingInvocation = Option.getOrUndefined(HashMap.get(invocations, id));
|
|
864
|
-
if (pendingInvocation === void 0) return Effect.void;
|
|
865
|
-
invocations = HashMap.remove(invocations, id);
|
|
866
|
-
return reportClientError(error).pipe(Effect.andThen(Deferred.fail(pendingInvocation.prepared, error)), Effect.andThen(Deferred.fail(pendingInvocation.deferred, error)), Effect.asVoid);
|
|
867
|
-
};
|
|
868
|
-
const handleMessage = Effect.fn("SyncClient.handleMessage")(function* (message) {
|
|
869
|
-
switch (message.type) {
|
|
870
|
-
case "Session":
|
|
871
|
-
if (message.event === "Updated") {
|
|
872
|
-
const previous = session.current();
|
|
873
|
-
if (previous !== void 0 && previous.sessionEpoch !== message.session.sessionEpoch) return;
|
|
874
|
-
if (previous?.viewRevision !== message.session.viewRevision) queryCache.invalidatePrivate();
|
|
875
|
-
session.accept(message.session, message.serverTime);
|
|
876
|
-
} else {
|
|
877
|
-
if (rememberedHandshake?.session?.sessionEpoch !== message.sessionEpoch) return;
|
|
878
|
-
session.suspend(message.event === "Unavailable" ? "Your ID session is temporarily unavailable." : void 0);
|
|
879
|
-
if (message.event !== "Unavailable") yield* Effect.forEach(HashMap.keys(invocations), (id) => rejectInvocation(id, ServerError.make({
|
|
880
|
-
code: "SessionChanged",
|
|
881
|
-
message: "The session changed. This operation may already have completed."
|
|
882
|
-
})));
|
|
883
|
-
}
|
|
884
|
-
return;
|
|
885
|
-
case "Invalidate":
|
|
886
|
-
if (message.sessionEpoch === session.current()?.sessionEpoch) queryCache.invalidate(message.ids);
|
|
887
|
-
return;
|
|
888
|
-
case "Snapshot": {
|
|
889
|
-
const current = session.current();
|
|
890
|
-
if (current === void 0 || message.identity?.sessionEpoch !== current.sessionEpoch) return;
|
|
891
|
-
if (message.identity.dependsOnId && message.identity.viewRevision !== current.viewRevision) return;
|
|
892
|
-
const entry = queryCache.getById(message.id);
|
|
893
|
-
if (entry === void 0) return;
|
|
894
|
-
entry.dependsOnId = message.identity.dependsOnId;
|
|
895
|
-
if (entry.revision !== void 0 && message.revision < entry.revision) return;
|
|
896
|
-
yield* resultFromWire(message.result, message.files ?? []).pipe(Effect.tap((result) => Effect.sync(() => queryCache.setResult(message.id, result, message.revision))), Effect.catchTags({ InvalidServerMessage: (error) => {
|
|
897
|
-
queryCache.setResult(message.id, error, message.revision);
|
|
898
|
-
return reportClientError(error);
|
|
899
|
-
} }));
|
|
900
|
-
return;
|
|
901
|
-
}
|
|
902
|
-
case "Preparation": {
|
|
903
|
-
if (message.sessionEpoch !== session.current()?.sessionEpoch) return;
|
|
904
|
-
const pendingInvocation = Option.getOrUndefined(HashMap.get(invocations, message.id));
|
|
905
|
-
if (pendingInvocation !== void 0) yield* Deferred.succeed(pendingInvocation.prepared, message.uploads);
|
|
906
|
-
return;
|
|
907
|
-
}
|
|
908
|
-
case "Result": {
|
|
909
|
-
if (message.sessionEpoch !== session.current()?.sessionEpoch) return;
|
|
910
|
-
const pendingInvocation = Option.getOrUndefined(HashMap.get(invocations, message.id));
|
|
911
|
-
if (pendingInvocation === void 0) return;
|
|
912
|
-
yield* resultFromWire(message.result).pipe(Effect.flatMap((result) => {
|
|
913
|
-
invocations = HashMap.remove(invocations, message.id);
|
|
914
|
-
return Deferred.succeed(pendingInvocation.deferred, result);
|
|
915
|
-
}), Effect.catchTags({ InvalidServerMessage: (error) => rejectInvocation(message.id, error) }));
|
|
916
|
-
return;
|
|
917
|
-
}
|
|
918
|
-
case "Error": {
|
|
919
|
-
if (message.sessionEpoch !== session.current()?.sessionEpoch) return;
|
|
920
|
-
const error = message.operation === void 0 ? ServerError.make({
|
|
921
|
-
code: message.code,
|
|
922
|
-
message: message.message
|
|
923
|
-
}) : ServerError.make({
|
|
924
|
-
code: message.code,
|
|
925
|
-
message: message.message,
|
|
926
|
-
operation: message.operation
|
|
927
|
-
});
|
|
928
|
-
if (message.operation?.type === "Invocation") yield* rejectInvocation(message.operation.id, error);
|
|
929
|
-
else if (message.operation?.type === "Subscription") {
|
|
930
|
-
queryCache.setResult(message.operation.id, error);
|
|
931
|
-
yield* reportClientError(error);
|
|
932
|
-
} else yield* reportClientError(error);
|
|
933
|
-
return;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
});
|
|
937
|
-
const requestReload = () => {
|
|
938
|
-
if (reloadRequested) return;
|
|
939
|
-
reloadRequested = true;
|
|
940
|
-
writer = void 0;
|
|
941
|
-
globalThis.location.reload();
|
|
942
|
-
};
|
|
943
|
-
const disconnect = Effect.sync(() => {
|
|
944
|
-
writer = void 0;
|
|
945
|
-
});
|
|
946
|
-
const connect = Effect.scoped(Effect.gen(function* () {
|
|
947
|
-
if (reloadRequested) return yield* Effect.never;
|
|
948
|
-
yield* session.bootstrap.pipe(Effect.mapError((error) => ConnectionUnavailable.make({ message: error.message })));
|
|
949
|
-
const socket = yield* Socket.makeWebSocket(`${socketUrl()}${session.socketParameters()}`, { closeCodeIsError: (code) => {
|
|
950
|
-
if (shouldReloadForCloseCode(code)) requestReload();
|
|
951
|
-
return false;
|
|
952
|
-
} });
|
|
953
|
-
const write = yield* socket.writer;
|
|
954
|
-
const handshakeReceived = yield* Deferred.make();
|
|
955
|
-
let handshakeAccepted = false;
|
|
956
|
-
const acceptHandshake = Effect.fn("SyncClient.acceptHandshake")(function* (handshake) {
|
|
957
|
-
const decision = handshakeDecision(rememberedHandshake, handshakeAccepted, handshake);
|
|
958
|
-
if (decision === "Reload") {
|
|
959
|
-
requestReload();
|
|
960
|
-
return;
|
|
961
|
-
}
|
|
962
|
-
if (decision === "Ignore") return;
|
|
963
|
-
if (handshake.session === void 0 || handshake.serverTime === void 0) {
|
|
964
|
-
requestReload();
|
|
965
|
-
return;
|
|
966
|
-
}
|
|
967
|
-
if (rememberedHandshake?.session !== void 0 && rememberedHandshake.session.sessionEpoch !== handshake.session.sessionEpoch) {
|
|
968
|
-
queryCache.invalidatePrivate();
|
|
969
|
-
yield* Effect.forEach(HashMap.keys(invocations), (id) => rejectInvocation(id, ServerError.make({
|
|
970
|
-
code: "SessionChanged",
|
|
971
|
-
message: "The session changed. This operation may already have completed."
|
|
972
|
-
})));
|
|
973
|
-
} else if (rememberedHandshake?.session?.viewRevision !== handshake.session.viewRevision) queryCache.invalidatePrivate();
|
|
974
|
-
yield* Effect.forEach(HashMap.entries(invocations), ([id, pending]) => pending.sessionEpoch === handshake.session.sessionEpoch ? Effect.void : rejectInvocation(id, ServerError.make({
|
|
975
|
-
code: "SessionChanged",
|
|
976
|
-
message: "The session changed. This operation may already have completed."
|
|
977
|
-
})));
|
|
978
|
-
session.accept(handshake.session, handshake.serverTime);
|
|
979
|
-
rememberedHandshake = handshake;
|
|
980
|
-
handshakeAccepted = true;
|
|
981
|
-
writer = write;
|
|
982
|
-
yield* Deferred.succeed(handshakeReceived, void 0);
|
|
983
|
-
yield* Effect.gen(function* () {
|
|
984
|
-
yield* Effect.forEach(queryCache.entries(), (entry) => sendWith(write, subscribeMessage(entry)));
|
|
985
|
-
yield* Effect.forEach(HashMap.values(invocations), (pendingInvocation) => sendWith(write, pendingInvocation.message));
|
|
986
|
-
}).pipe(Effect.tapError(reportClientError), Effect.ignore);
|
|
987
|
-
});
|
|
988
|
-
const handleText = Effect.fn("SyncClient.handleText")(function* (text) {
|
|
989
|
-
const message = yield* Schema.decodeEffect(ServerMessageJson)(text).pipe(Effect.mapError((cause) => InvalidServerMessage.make({
|
|
990
|
-
cause,
|
|
991
|
-
message: "The server returned an invalid sync message."
|
|
992
|
-
})));
|
|
993
|
-
if (message.type === "Handshake") return yield* acceptHandshake(message);
|
|
994
|
-
if (message.type === "Deployment") {
|
|
995
|
-
requestReload();
|
|
996
|
-
return;
|
|
997
|
-
}
|
|
998
|
-
if (!handshakeAccepted) return yield* InvalidServerMessage.make({
|
|
999
|
-
cause: /* @__PURE__ */ new Error("The server sent a sync message before the handshake."),
|
|
1000
|
-
message: "The server returned a sync message before the handshake."
|
|
1001
|
-
});
|
|
1002
|
-
return yield* handleMessage(message);
|
|
1003
|
-
});
|
|
1004
|
-
const suspended = yield* Deferred.make();
|
|
1005
|
-
sessionSuspended = suspended;
|
|
1006
|
-
yield* Effect.addFinalizer(() => Effect.sync(() => {
|
|
1007
|
-
if (sessionSuspended === suspended) sessionSuspended = void 0;
|
|
1008
|
-
}));
|
|
1009
|
-
const run = yield* socket.runString(handleText).pipe(Effect.forkChild);
|
|
1010
|
-
yield* Effect.raceFirst(Deferred.await(handshakeReceived).pipe(Effect.timeout("10 seconds")), Fiber.join(run));
|
|
1011
|
-
yield* Effect.raceFirst(Fiber.join(run), Deferred.await(suspended));
|
|
1012
|
-
})).pipe(Effect.mapError((cause) => Schema.is(ClientInfrastructureError)(cause) ? cause : ConnectionUnavailable.make({
|
|
1013
|
-
cause,
|
|
1014
|
-
message: "The sync connection was lost."
|
|
1015
|
-
})), Effect.ensuring(disconnect));
|
|
1016
|
-
const reconnectSchedule = Schedule.exponential("250 millis").pipe(Schedule.modifyDelay(({ duration }) => Effect.succeed(Duration.min(duration, Duration.seconds(5)))), Schedule.jittered);
|
|
1017
|
-
yield* connect.pipe(Effect.andThen(Effect.fail(ConnectionUnavailable.make({ message: "The sync connection closed; reconnecting." }))), Effect.tapError(reportClientError), Effect.retry(reconnectSchedule), Effect.forkScoped);
|
|
1018
|
-
const observe = Effect.fn("SyncClient.observe")(function* (functionAddress, args) {
|
|
1019
|
-
return yield* queryCache.observe(functionAddress, args);
|
|
1020
|
-
});
|
|
1021
|
-
const mutate = Effect.fn("SyncClient.mutate")(function* (functionAddress, args) {
|
|
1022
|
-
const admittedSession = session.current() ?? rememberedHandshake?.session ?? (yield* session.bootstrap.pipe(Effect.mapError((error) => ConnectionUnavailable.make({ message: error.message }))));
|
|
1023
|
-
const invocationId = yield* ids.generate(InvocationId);
|
|
1024
|
-
const preparedArguments = yield* prepareMutationArguments(args).pipe(Effect.provideService(IdGenerator, ids), Effect.mapError((cause) => InvalidMutationArguments.make({
|
|
1025
|
-
cause,
|
|
1026
|
-
function: functionAddress,
|
|
1027
|
-
message: `Mutation arguments for ${functionAddress} contain an unsupported file or value.`
|
|
1028
|
-
})), Effect.tapError(reportClientError));
|
|
1029
|
-
const jsonArgs = yield* Effect.try({
|
|
1030
|
-
try: () => encodeTransportObject(preparedArguments.value),
|
|
1031
|
-
catch: (cause) => InvalidMutationArguments.make({
|
|
1032
|
-
cause,
|
|
1033
|
-
function: functionAddress,
|
|
1034
|
-
message: `Mutation arguments for ${functionAddress} contain an unsupported value.`
|
|
1035
|
-
})
|
|
1036
|
-
}).pipe(Effect.tapError(reportClientError));
|
|
1037
|
-
const deferred = yield* Deferred.make();
|
|
1038
|
-
const prepared = yield* Deferred.make();
|
|
1039
|
-
const invokeMessage = {
|
|
1040
|
-
type: "Invoke",
|
|
1041
|
-
id: invocationId,
|
|
1042
|
-
kind: "Mutation",
|
|
1043
|
-
function: functionAddress,
|
|
1044
|
-
args: jsonArgs
|
|
1045
|
-
};
|
|
1046
|
-
const message = preparedArguments.fileIds.length === 0 ? invokeMessage : {
|
|
1047
|
-
type: "Prepare",
|
|
1048
|
-
id: invocationId,
|
|
1049
|
-
kind: "Mutation",
|
|
1050
|
-
function: functionAddress,
|
|
1051
|
-
args: jsonArgs,
|
|
1052
|
-
files: preparedArguments.fileIds
|
|
1053
|
-
};
|
|
1054
|
-
invocations = HashMap.set(invocations, invocationId, {
|
|
1055
|
-
sessionEpoch: admittedSession.sessionEpoch,
|
|
1056
|
-
deferred,
|
|
1057
|
-
function: functionAddress,
|
|
1058
|
-
message,
|
|
1059
|
-
prepared
|
|
1060
|
-
});
|
|
1061
|
-
return yield* Effect.gen(function* () {
|
|
1062
|
-
if (writer !== void 0) yield* sendWith(writer, message).pipe(Effect.catchTags({
|
|
1063
|
-
ConnectionUnavailable: reportClientError,
|
|
1064
|
-
InvalidClientMessage: (error) => rejectInvocation(invocationId, error)
|
|
1065
|
-
}));
|
|
1066
|
-
if (message.type === "Prepare") {
|
|
1067
|
-
const uploads = yield* Deferred.await(prepared);
|
|
1068
|
-
const expected = new Set(message.files);
|
|
1069
|
-
const received = /* @__PURE__ */ new Set();
|
|
1070
|
-
const transfers = [];
|
|
1071
|
-
for (const upload of uploads) {
|
|
1072
|
-
if (!expected.has(upload.id) || received.has(upload.id)) return yield* InvalidServerMessage.make({
|
|
1073
|
-
cause: /* @__PURE__ */ new Error(`Unexpected prepared file '${upload.id}'.`),
|
|
1074
|
-
message: "The server returned invalid application file preparation data."
|
|
1075
|
-
});
|
|
1076
|
-
received.add(upload.id);
|
|
1077
|
-
const file = preparedArguments.nativeFiles.get(upload.id);
|
|
1078
|
-
if (file === void 0) return yield* InvalidServerMessage.make({
|
|
1079
|
-
cause: /* @__PURE__ */ new Error(`Missing native file '${upload.id}'.`),
|
|
1080
|
-
message: "The server prepared an unknown application file."
|
|
1081
|
-
});
|
|
1082
|
-
if (upload.url === void 0) continue;
|
|
1083
|
-
transfers.push({
|
|
1084
|
-
file,
|
|
1085
|
-
url: upload.url
|
|
1086
|
-
});
|
|
1087
|
-
}
|
|
1088
|
-
if (received.size !== expected.size) return yield* InvalidServerMessage.make({
|
|
1089
|
-
cause: /* @__PURE__ */ new Error("The server omitted a prepared file."),
|
|
1090
|
-
message: "The server returned incomplete application file preparation data."
|
|
1091
|
-
});
|
|
1092
|
-
yield* Effect.forEach(transfers, Effect.fn("SyncClient.uploadFile")(function* ({ file, url }) {
|
|
1093
|
-
const response = yield* Effect.tryPromise({
|
|
1094
|
-
try: (signal) => fetch(url, {
|
|
1095
|
-
method: "PUT",
|
|
1096
|
-
body: file,
|
|
1097
|
-
headers: { "content-type": file.type },
|
|
1098
|
-
signal
|
|
1099
|
-
}),
|
|
1100
|
-
catch: (cause) => ConnectionUnavailable.make({
|
|
1101
|
-
cause,
|
|
1102
|
-
message: `File '${file.name}' could not be uploaded.`
|
|
1103
|
-
})
|
|
1104
|
-
});
|
|
1105
|
-
if (!response.ok) {
|
|
1106
|
-
const detail = yield* Effect.promise(() => response.text());
|
|
1107
|
-
return yield* InvalidMutationArguments.make({
|
|
1108
|
-
cause: new Error(detail),
|
|
1109
|
-
function: functionAddress,
|
|
1110
|
-
message: `File '${file.name}' was rejected by application storage.`
|
|
1111
|
-
});
|
|
1112
|
-
}
|
|
1113
|
-
}), {
|
|
1114
|
-
concurrency: 3,
|
|
1115
|
-
discard: true
|
|
1116
|
-
});
|
|
1117
|
-
const pendingInvocation = Option.getOrUndefined(HashMap.get(invocations, invocationId));
|
|
1118
|
-
if (pendingInvocation === void 0) return yield* Deferred.await(deferred);
|
|
1119
|
-
invocations = HashMap.set(invocations, invocationId, {
|
|
1120
|
-
...pendingInvocation,
|
|
1121
|
-
message: invokeMessage
|
|
1122
|
-
});
|
|
1123
|
-
if (writer !== void 0) yield* sendWith(writer, invokeMessage).pipe(Effect.catchTags({
|
|
1124
|
-
ConnectionUnavailable: reportClientError,
|
|
1125
|
-
InvalidClientMessage: (error) => rejectInvocation(invocationId, error)
|
|
1126
|
-
}));
|
|
1127
|
-
}
|
|
1128
|
-
return yield* Deferred.await(deferred);
|
|
1129
|
-
}).pipe(Effect.tapError(() => Effect.sync(() => {
|
|
1130
|
-
invocations = HashMap.remove(invocations, invocationId);
|
|
1131
|
-
})));
|
|
1132
|
-
});
|
|
1133
|
-
return SyncClient.of({
|
|
1134
|
-
mutate,
|
|
1135
|
-
observe
|
|
1136
|
-
});
|
|
1137
|
-
})).pipe(Layer.provide(Layer.merge(Socket.layerWebSocketConstructorGlobal, BrowserCrypto.layer)));
|
|
1138
|
-
};
|
|
1139
|
-
const syncRuntime = ManagedRuntime.make(SyncClient.layer.pipe(Layer.provideMerge(BrowserSession.layer), Layer.provideMerge(clientErrorReporterLayer), Layer.provideMerge(IdGenerator.layer)));
|
|
1140
|
-
const hot = import.meta.hot;
|
|
1141
|
-
if (hot !== void 0) hot.dispose(() => void syncRuntime.dispose());
|
|
1142
|
-
//#endregion
|
|
1143
18
|
//#region src/client/page-observers.ts
|
|
1144
19
|
const makePageObservers = (onChange, releaseObserver) => {
|
|
1145
20
|
const pages = /* @__PURE__ */ new Map();
|
|
@@ -1415,15 +290,9 @@ function useId() {
|
|
|
1415
290
|
};
|
|
1416
291
|
}
|
|
1417
292
|
//#endregion
|
|
1418
|
-
//#region src/client/app.ts
|
|
1419
|
-
const app = (definition) => {
|
|
1420
|
-
if (definition.title.trim().length === 0) throw new Error("The app title must contain a non-whitespace character.");
|
|
1421
|
-
return definition;
|
|
1422
|
-
};
|
|
1423
|
-
//#endregion
|
|
1424
293
|
//#region src/client/index.ts
|
|
1425
294
|
const Result = { match: Result$2.match };
|
|
1426
295
|
//#endregion
|
|
1427
|
-
export { Component, Files, Fragment, Query,
|
|
296
|
+
export { Component, Files, Fragment, Image, Link, NavLink, Query, Redirect, Result, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray, url, useBlocker, useCallback, useContext, useDebugValue, useEffect, useElementId, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useLocation, useMatch, useMemo, useMutation, useNavigate, useNavigation, usePaginatedQuery, useQuery, useReducer, useRef, useRoute, useState };
|
|
1428
297
|
|
|
1429
298
|
//# sourceMappingURL=client.js.map
|