@oddington/sdk 0.1.12 → 0.1.14
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 +18 -9
- package/dist/browser.js +597 -189
- package/dist/index.js +16 -16
- package/dist/types/packages/sdk/src/public.d.ts +4 -0
- package/dist/types/shared/inbox-member-contract.d.ts +19 -0
- package/dist/types/shared/inbox-member-types.d.ts +174 -0
- package/dist/types/shared/record-selection.d.ts +21 -0
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -269,8 +269,8 @@ function presentation(source) {
|
|
|
269
269
|
});
|
|
270
270
|
new Set(views.map((view) => view.id)).size !== views.length && fail("Duplicate view ID");
|
|
271
271
|
let body2 = source.body === void 0 ? [] : array(source.body, "body").map(validateBlock);
|
|
272
|
-
for (let
|
|
273
|
-
let targets =
|
|
272
|
+
for (let block2 of body2) {
|
|
273
|
+
let targets = block2.kind === "record" ? [block2.view] : block2.kind === "records" ? [block2.view, ...block2.records.map((record3) => record3.view)] : [];
|
|
274
274
|
for (let target of targets) target !== void 0 && !views.some((view) => view.id === target) && fail(`Unknown Block View target: ${target}`);
|
|
275
275
|
}
|
|
276
276
|
return { title: text(source.title, "title"), description: text(source.description, "description"), views, body: body2 };
|
|
@@ -287,13 +287,13 @@ function validatePublication(value) {
|
|
|
287
287
|
"notifyImmediately",
|
|
288
288
|
...source.kind === "ask" ? ["questions"] : []
|
|
289
289
|
], "publication"), source.notifyImmediately !== void 0 && typeof source.notifyImmediately != "boolean" && fail("notifyImmediately must be a boolean");
|
|
290
|
-
let itemPresentation = { ...presentation(source), ...source.notifyImmediately === void 0 ? {} : { notifyImmediately: source.notifyImmediately } }, linkedAsks = (itemPresentation.body ?? []).flatMap((
|
|
290
|
+
let itemPresentation = { ...presentation(source), ...source.notifyImmediately === void 0 ? {} : { notifyImmediately: source.notifyImmediately } }, linkedAsks = (itemPresentation.body ?? []).flatMap((block2) => block2.kind === "asks" ? block2.asks : []);
|
|
291
291
|
if (new Set(linkedAsks).size !== linkedAsks.length && fail("Ask belongs to more than one problem"), source.kind === "digest") return {
|
|
292
292
|
kind: "digest",
|
|
293
293
|
...itemPresentation,
|
|
294
294
|
recipients: distinctPeople(source.recipients, "digest recipients")
|
|
295
295
|
};
|
|
296
|
-
itemPresentation.body?.some((
|
|
296
|
+
itemPresentation.body?.some((block2) => block2.kind === "asks") && fail("Asks Blocks belong to Digests");
|
|
297
297
|
let questions = array(source.questions === void 0 ? [] : source.questions, "questions").map((value2) => question(value2));
|
|
298
298
|
new Set(questions.map((entry) => entry.id)).size !== questions.length && fail("Duplicate question ID");
|
|
299
299
|
let extra = source.recipients === void 0 ? [] : distinctPeople(source.recipients, "recipients", !1);
|
|
@@ -583,13 +583,13 @@ function freeze(value) {
|
|
|
583
583
|
function json(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
584
584
|
if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return;
|
|
585
585
|
if (!value || typeof value != "object" || ancestors.has(value)) return invalid();
|
|
586
|
-
let
|
|
587
|
-
if (!
|
|
588
|
-
let
|
|
589
|
-
if (
|
|
586
|
+
let array3 = Array.isArray(value);
|
|
587
|
+
if (!array3 && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return invalid();
|
|
588
|
+
let keys5 = Reflect.ownKeys(value);
|
|
589
|
+
if (array3 && (keys5.length !== value.length + 1 || !Array.from({ length: value.length }, (_, index) => Object.hasOwn(value, index)).every(Boolean))) return invalid();
|
|
590
590
|
ancestors.add(value);
|
|
591
|
-
for (let key of
|
|
592
|
-
if (
|
|
591
|
+
for (let key of keys5) {
|
|
592
|
+
if (array3 && key === "length") continue;
|
|
593
593
|
if (typeof key != "string") return invalid();
|
|
594
594
|
let descriptor2 = Object.getOwnPropertyDescriptor(value, key);
|
|
595
595
|
if (!descriptor2.enumerable || !Object.hasOwn(descriptor2, "value")) return invalid();
|
|
@@ -638,7 +638,7 @@ var schema = {
|
|
|
638
638
|
return invalidContract2();
|
|
639
639
|
}
|
|
640
640
|
if (definition.steps !== void 0 && (!definition.steps || typeof definition.steps != "object" || Array.isArray(definition.steps))) return invalidContract2();
|
|
641
|
-
let steps = definition.steps === void 0 ? [] : Object.entries(definition.steps).map(([
|
|
641
|
+
let steps = definition.steps === void 0 ? [] : Object.entries(definition.steps).map(([id3, summary]) => ({ id: id3, ...summary === null ? {} : { summary } })), parsed = parseAppRoutineContract({
|
|
642
642
|
routine: "definition",
|
|
643
643
|
input: definition.input === void 0 ? empty : definition.input,
|
|
644
644
|
steps: steps.length ? steps : [{ id: "inspect" }],
|
|
@@ -669,12 +669,12 @@ async function executeRoutineDefinition(definition, input, runtime) {
|
|
|
669
669
|
let captured = captureRoutineInput(definition, input), { contract, run } = definitions.get(definition), active2 = !0, broken = !1, reports = Promise.resolve(), os2 = Object.freeze({
|
|
670
670
|
...runtime,
|
|
671
671
|
run: freeze({ ...runtime.run }),
|
|
672
|
-
step(
|
|
672
|
+
step(id3, ...summary) {
|
|
673
673
|
if (!active2 || broken || summary.length > 1)
|
|
674
674
|
return broken = !0, Promise.reject(new AppRoutineContractError("invalid_value"));
|
|
675
675
|
let value;
|
|
676
676
|
try {
|
|
677
|
-
let step = contract.steps.find((step2) => step2.id ===
|
|
677
|
+
let step = contract.steps.find((step2) => step2.id === id3);
|
|
678
678
|
if (!step) return invalid();
|
|
679
679
|
if (step.summary === void 0) {
|
|
680
680
|
if (summary.length) return invalid();
|
|
@@ -682,7 +682,7 @@ async function executeRoutineDefinition(definition, input, runtime) {
|
|
|
682
682
|
} catch (error) {
|
|
683
683
|
return broken = !0, Promise.reject(error);
|
|
684
684
|
}
|
|
685
|
-
let report = reports.then(() => broken ? invalid() : runtime.step(
|
|
685
|
+
let report = reports.then(() => broken ? invalid() : runtime.step(id3, value));
|
|
686
686
|
return reports = report.catch(() => {
|
|
687
687
|
broken = !0;
|
|
688
688
|
}), report;
|
|
@@ -821,8 +821,8 @@ function captureDataDelete(record3) {
|
|
|
821
821
|
return !validRecordRef(identity.$ref) || typeof identity.$version != "string" || !identity.$version.length || identity.$version.length > 512 ? invalidChange() : { ref: identity.$ref, expectedVersion: identity.$version };
|
|
822
822
|
}
|
|
823
823
|
function captureDataUpdate(record3, set) {
|
|
824
|
-
let identity = captureDataDelete(record3),
|
|
825
|
-
return !Object.keys(
|
|
824
|
+
let identity = captureDataDelete(record3), fields5 = mapping(set);
|
|
825
|
+
return !Object.keys(fields5).length || Object.keys(fields5).some((key) => key.startsWith("$") || ["id", "type"].includes(key)) ? invalidChange() : { ...identity, set: captureValue(fields5) };
|
|
826
826
|
}
|
|
827
827
|
function captureIdentities(value, update, allowEmpty = !0) {
|
|
828
828
|
if (!Array.isArray(value) || !allowEmpty && !value.length || value.length > 1e4) return invalidChange();
|
|
@@ -841,14 +841,14 @@ function captureDataCreate(value) {
|
|
|
841
841
|
let row = mapping(value);
|
|
842
842
|
if (!validRecordRef(row.$ref) || Object.keys(row).some((key) => key.startsWith("$") && !["$ref", "$filing"].includes(key)))
|
|
843
843
|
return invalidChange();
|
|
844
|
-
let { $ref: ref, $filing, ...
|
|
844
|
+
let { $ref: ref, $filing, ...fields5 } = row, filing;
|
|
845
845
|
if ($filing !== void 0) {
|
|
846
846
|
let components = mapping($filing);
|
|
847
847
|
if (Object.entries(components).some(([name, value2]) => !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) || ["constructor", "prototype"].includes(name) || typeof value2 != "string" || !/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(value2)))
|
|
848
848
|
return invalidChange();
|
|
849
849
|
filing = { ...components };
|
|
850
850
|
}
|
|
851
|
-
return { ref, fields: captureValue(
|
|
851
|
+
return { ref, fields: captureValue(fields5), ...filing ? { filing } : {} };
|
|
852
852
|
}
|
|
853
853
|
function captureDataChanges(updatesValue, createsValue = [], deletesValue = []) {
|
|
854
854
|
let updates = captureDataUpdates(updatesValue, !0);
|
|
@@ -856,8 +856,8 @@ function captureDataChanges(updatesValue, createsValue = [], deletesValue = [])
|
|
|
856
856
|
let creates = createsValue.map((item) => {
|
|
857
857
|
let row = mapping(item);
|
|
858
858
|
if (Object.keys(row).some((key) => !["ref", "fields", "filing"].includes(key)) || !Object.hasOwn(row, "ref") || !Object.hasOwn(row, "fields")) return invalidChange();
|
|
859
|
-
let
|
|
860
|
-
return Object.keys(
|
|
859
|
+
let fields5 = mapping(row.fields);
|
|
860
|
+
return Object.keys(fields5).some((key) => key.startsWith("$")) ? invalidChange() : captureDataCreate({ ...fields5, $ref: row.ref, ...Object.hasOwn(row, "filing") ? { $filing: row.filing } : {} });
|
|
861
861
|
}), deletes = captureIdentities(deletesValue, !1), refs = [...updates, ...creates, ...deletes].map((item) => item.ref);
|
|
862
862
|
return !refs.length || refs.length > 1e4 || new Set(refs).size !== refs.length ? invalidChange() : { updates, creates, deletes };
|
|
863
863
|
}
|
|
@@ -953,20 +953,20 @@ function checked(workspace, endpoint, headers) {
|
|
|
953
953
|
|
|
954
954
|
var data = {
|
|
955
955
|
repository(repository) {
|
|
956
|
-
async function
|
|
956
|
+
async function send3(input) {
|
|
957
957
|
let context2 = await resolveDataContext();
|
|
958
958
|
try {
|
|
959
959
|
let envelope = { repository, ...input };
|
|
960
960
|
if (checkDataRequestSize(envelope), "local" in context2) return await context2.local("data/query", envelope);
|
|
961
|
-
let
|
|
961
|
+
let response2 = await fetch(context2.url, {
|
|
962
962
|
method: "POST",
|
|
963
963
|
redirect: "error",
|
|
964
964
|
cache: "no-store",
|
|
965
965
|
headers: { "content-type": "application/json", ...context2.headers },
|
|
966
966
|
body: JSON.stringify(envelope)
|
|
967
|
-
}), result2 = await
|
|
968
|
-
if (!
|
|
969
|
-
throw dataTransportError(
|
|
967
|
+
}), result2 = await response2.json();
|
|
968
|
+
if (!response2.ok)
|
|
969
|
+
throw dataTransportError(response2.status, result2);
|
|
970
970
|
return result2;
|
|
971
971
|
} catch (error) {
|
|
972
972
|
throw error instanceof DataOperationError ? error : new DataOperationError("unavailable", !0);
|
|
@@ -974,17 +974,17 @@ var data = {
|
|
|
974
974
|
}
|
|
975
975
|
return {
|
|
976
976
|
collections: {
|
|
977
|
-
list: () =>
|
|
978
|
-
schema: (name) =>
|
|
977
|
+
list: () => send3({ operation: "collections.list" }),
|
|
978
|
+
schema: (name) => send3({ operation: "collections.schema", name })
|
|
979
979
|
},
|
|
980
980
|
records: {
|
|
981
|
-
select: (query) =>
|
|
982
|
-
search: async (query, options) =>
|
|
981
|
+
select: (query) => send3({ operation: "records.select", query }),
|
|
982
|
+
search: async (query, options) => send3({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
|
|
983
983
|
},
|
|
984
984
|
history: {
|
|
985
|
-
list: async (options) =>
|
|
986
|
-
at: async (instant) =>
|
|
987
|
-
changes: async (options) =>
|
|
985
|
+
list: async (options) => send3({ operation: "history.list", options: captureHistoryListOptions(options) }),
|
|
986
|
+
at: async (instant) => send3({ operation: "history.at", instant: captureHistoryInstant(instant) }),
|
|
987
|
+
changes: async (options) => send3({ operation: "history.changes", options: captureHistoryChangesOptions(options) })
|
|
988
988
|
},
|
|
989
989
|
changes() {
|
|
990
990
|
let updates = [], creates = [], deletes = [], publicationId, pending, confirmed, assertMutable = () => {
|
|
@@ -1015,7 +1015,7 @@ var data = {
|
|
|
1015
1015
|
snapshot(updates, creates, next), deletes = next;
|
|
1016
1016
|
},
|
|
1017
1017
|
async validate() {
|
|
1018
|
-
await
|
|
1018
|
+
await send3({ operation: "changes.validate", ...snapshot() });
|
|
1019
1019
|
},
|
|
1020
1020
|
publish() {
|
|
1021
1021
|
if (confirmed) return Promise.resolve(structuredClone(confirmed));
|
|
@@ -1026,7 +1026,7 @@ var data = {
|
|
|
1026
1026
|
} catch (error) {
|
|
1027
1027
|
return Promise.reject(error);
|
|
1028
1028
|
}
|
|
1029
|
-
publicationId ??= crypto.randomUUID(), pending =
|
|
1029
|
+
publicationId ??= crypto.randomUUID(), pending = send3({ operation: "changes.publish", ...captured, publicationId }).then((result2) => (confirmed = structuredClone(result2), result2)).catch((error) => {
|
|
1030
1030
|
throw error instanceof DataOperationError ? new DataOperationError(
|
|
1031
1031
|
error.code,
|
|
1032
1032
|
error.retryable,
|
|
@@ -1083,9 +1083,9 @@ async function timed(work, parent, timeout = TIMEOUT_MS) {
|
|
|
1083
1083
|
clearTimeout(timer), parent?.removeEventListener("abort", abort);
|
|
1084
1084
|
}
|
|
1085
1085
|
}
|
|
1086
|
-
async function result(
|
|
1086
|
+
async function result(response2, maximum = RESULT_BYTES) {
|
|
1087
1087
|
try {
|
|
1088
|
-
let bytes = await boundedBytes(
|
|
1088
|
+
let bytes = await boundedBytes(response2.body, maximum);
|
|
1089
1089
|
return JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes));
|
|
1090
1090
|
} catch {
|
|
1091
1091
|
throw unavailable();
|
|
@@ -1096,13 +1096,13 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1096
1096
|
parent.addEventListener("abort", abort, { once: !0 }), parent.aborted && abort();
|
|
1097
1097
|
let detach = () => parent.removeEventListener("abort", abort);
|
|
1098
1098
|
try {
|
|
1099
|
-
let
|
|
1099
|
+
let response2 = await upstream(url, { ...init2, signal: delivery.signal });
|
|
1100
1100
|
if (delivery.signal.aborted)
|
|
1101
|
-
throw
|
|
1101
|
+
throw response2.body?.cancel().catch(() => {
|
|
1102
1102
|
}), unavailable();
|
|
1103
|
-
if (!
|
|
1104
|
-
return detach(),
|
|
1105
|
-
let source =
|
|
1103
|
+
if (!response2.body)
|
|
1104
|
+
return detach(), response2;
|
|
1105
|
+
let source = response2.body, reader, settled = !1, cancel = async (reason) => {
|
|
1106
1106
|
if (!settled) {
|
|
1107
1107
|
settled = !0, detach(), delivery.abort(reason);
|
|
1108
1108
|
try {
|
|
@@ -1127,9 +1127,9 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1127
1127
|
}
|
|
1128
1128
|
},
|
|
1129
1129
|
cancel
|
|
1130
|
-
}, { highWaterMark: 0 }), wrapped = new Response(body2, { status:
|
|
1130
|
+
}, { highWaterMark: 0 }), wrapped = new Response(body2, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
|
|
1131
1131
|
for (let key of ["url", "redirected", "type"])
|
|
1132
|
-
Object.defineProperty(wrapped, key, { value:
|
|
1132
|
+
Object.defineProperty(wrapped, key, { value: response2[key] });
|
|
1133
1133
|
return wrapped;
|
|
1134
1134
|
} catch (error) {
|
|
1135
1135
|
throw detach(), delivery.abort(error), error;
|
|
@@ -1145,7 +1145,7 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1145
1145
|
let context2 = await resolveFilesContext();
|
|
1146
1146
|
checkCurrent(context2);
|
|
1147
1147
|
try {
|
|
1148
|
-
let
|
|
1148
|
+
let response2 = await (async () => {
|
|
1149
1149
|
let url = `${context2.url}${suffix}`, request = {
|
|
1150
1150
|
...init2,
|
|
1151
1151
|
signal: parent,
|
|
@@ -1155,22 +1155,22 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1155
1155
|
};
|
|
1156
1156
|
return descriptor2 ? fetch(url, request) : hostedContent(url, request, parent);
|
|
1157
1157
|
})();
|
|
1158
|
-
if (!
|
|
1159
|
-
let value2 = await result(
|
|
1160
|
-
throw code ? new FileOperationError(code,
|
|
1158
|
+
if (!response2.ok) {
|
|
1159
|
+
let value2 = await result(response2), error = value2 && typeof value2 == "object" && "error" in value2 ? value2.error : void 0, received = error && typeof error == "object" && "code" in error ? error.code : void 0, code = failures[response2.status]?.find((code2) => code2 === received);
|
|
1160
|
+
throw code ? new FileOperationError(code, response2.status, code === "capacity" || code === "unavailable") : unavailable();
|
|
1161
1161
|
}
|
|
1162
|
-
if (
|
|
1163
|
-
throw
|
|
1162
|
+
if (response2.status !== (descriptor2 === 204 ? 204 : 200) || descriptor2 === 204 && response2.body !== null)
|
|
1163
|
+
throw response2.body?.cancel().catch(() => {
|
|
1164
1164
|
}), unavailable();
|
|
1165
1165
|
try {
|
|
1166
1166
|
checkCurrent();
|
|
1167
1167
|
} catch (error) {
|
|
1168
|
-
throw
|
|
1168
|
+
throw response2.body?.cancel().catch(() => {
|
|
1169
1169
|
}), error;
|
|
1170
1170
|
}
|
|
1171
1171
|
if (descriptor2 === 204) return;
|
|
1172
|
-
if (!descriptor2) return
|
|
1173
|
-
let value = await result(
|
|
1172
|
+
if (!descriptor2) return response2;
|
|
1173
|
+
let value = await result(response2, descriptor2 === "control" ? CONTROL_RESULT_BYTES : RESULT_BYTES);
|
|
1174
1174
|
if (descriptor2 === "control")
|
|
1175
1175
|
return checkCurrent(), value;
|
|
1176
1176
|
let parsed;
|
|
@@ -1188,9 +1188,9 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1188
1188
|
}
|
|
1189
1189
|
throw unavailable();
|
|
1190
1190
|
}
|
|
1191
|
-
function idPath(
|
|
1192
|
-
if (typeof
|
|
1193
|
-
return `/${
|
|
1191
|
+
function idPath(id3) {
|
|
1192
|
+
if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw invalid4();
|
|
1193
|
+
return `/${id3}`;
|
|
1194
1194
|
}
|
|
1195
1195
|
async function multipartCreate(input, metadata, exchange, release = () => {
|
|
1196
1196
|
active--;
|
|
@@ -1292,16 +1292,16 @@ async function operation(work, initial, parent) {
|
|
|
1292
1292
|
throw error instanceof FileOperationError ? error : unavailable();
|
|
1293
1293
|
});
|
|
1294
1294
|
}
|
|
1295
|
-
function contentPath(
|
|
1296
|
-
let path = idPath(
|
|
1295
|
+
function contentPath(id3, name) {
|
|
1296
|
+
let path = idPath(id3);
|
|
1297
1297
|
if (name === void 0) return `${path}/content`;
|
|
1298
1298
|
if (!safeEnrichmentName(name)) throw invalid4();
|
|
1299
1299
|
return `${path}/enrichments/${encodeURIComponent(name)}/content`;
|
|
1300
1300
|
}
|
|
1301
|
-
async function read(
|
|
1301
|
+
async function read(id3, names) {
|
|
1302
1302
|
let context2 = await resolveFilesContext();
|
|
1303
|
-
if (idPath(
|
|
1304
|
-
let path = contentPath(
|
|
1303
|
+
if (idPath(id3), names === void 0 || typeof names == "string") {
|
|
1304
|
+
let path = contentPath(id3, names);
|
|
1305
1305
|
return operation((context3, signal) => send(path, { method: "GET" }, !1, context3, signal), context2);
|
|
1306
1306
|
}
|
|
1307
1307
|
if (!Array.isArray(names)) throw invalid4();
|
|
@@ -1313,31 +1313,31 @@ async function read(id2, names) {
|
|
|
1313
1313
|
seen.add(name), distinct.push(name);
|
|
1314
1314
|
}
|
|
1315
1315
|
}
|
|
1316
|
-
let paths = distinct.map((name) => contentPath(
|
|
1316
|
+
let paths = distinct.map((name) => contentPath(id3, name));
|
|
1317
1317
|
return timed(async (parent) => {
|
|
1318
1318
|
let responses = {};
|
|
1319
1319
|
try {
|
|
1320
1320
|
for (let i = 0; i < paths.length; i++) {
|
|
1321
|
-
let
|
|
1322
|
-
Object.defineProperty(responses, distinct[i], { value:
|
|
1321
|
+
let response2 = await operation((context3, signal) => send(paths[i], { method: "GET" }, !1, context3, signal), context2, parent);
|
|
1322
|
+
Object.defineProperty(responses, distinct[i], { value: response2, enumerable: !0 });
|
|
1323
1323
|
}
|
|
1324
1324
|
if (!context2.isCurrent()) throw new FileOperationError("unsupported_context", 400);
|
|
1325
1325
|
return responses;
|
|
1326
1326
|
} catch (error) {
|
|
1327
|
-
for (let
|
|
1327
|
+
for (let response2 of Object.values(responses)) response2.body?.cancel().catch(() => {
|
|
1328
1328
|
});
|
|
1329
1329
|
throw error;
|
|
1330
1330
|
}
|
|
1331
1331
|
});
|
|
1332
1332
|
}
|
|
1333
1333
|
var files = {
|
|
1334
|
-
delete(
|
|
1335
|
-
return operation((context2, signal) => send(idPath(
|
|
1334
|
+
delete(id3) {
|
|
1335
|
+
return operation((context2, signal) => send(idPath(id3), { method: "DELETE" }, 204, context2, signal));
|
|
1336
1336
|
},
|
|
1337
|
-
async upload(
|
|
1337
|
+
async upload(id3) {
|
|
1338
1338
|
return operation(async (context2, signal) => {
|
|
1339
|
-
let file2 = await send(`${idPath(
|
|
1340
|
-
if (file2.id !==
|
|
1339
|
+
let file2 = await send(`${idPath(id3)}/upload`, { method: "POST" }, !0, context2, signal);
|
|
1340
|
+
if (file2.id !== id3) throw unavailable();
|
|
1341
1341
|
return file2;
|
|
1342
1342
|
});
|
|
1343
1343
|
},
|
|
@@ -1345,9 +1345,9 @@ var files = {
|
|
|
1345
1345
|
let context2 = await resolveFilesContext();
|
|
1346
1346
|
if (!input || typeof input != "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "size", "path", "name", "storage", "csv"].includes(key)) || options !== void 0 && (!options || typeof options != "object" || Array.isArray(options) || Object.keys(options).some((key) => key !== "requestKey")))
|
|
1347
1347
|
throw invalid4();
|
|
1348
|
-
let blob = input.file instanceof Blob,
|
|
1349
|
-
if (!blob && !
|
|
1350
|
-
let intrinsic = blob ? input.file.size :
|
|
1348
|
+
let blob = input.file instanceof Blob, array3 = input.file instanceof Uint8Array, stream = input.file instanceof ReadableStream;
|
|
1349
|
+
if (!blob && !array3 && !stream) throw invalid4();
|
|
1350
|
+
let intrinsic = blob ? input.file.size : array3 ? input.file.byteLength : void 0;
|
|
1351
1351
|
if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw invalid4();
|
|
1352
1352
|
let name = input.name;
|
|
1353
1353
|
name === void 0 && blob && "name" in input.file && typeof input.file.name == "string" && (name = typeof globalThis.File < "u" && input.file instanceof globalThis.File ? input.file.name : input.file.name.split(/[\\/]/).at(-1));
|
|
@@ -1366,7 +1366,7 @@ var files = {
|
|
|
1366
1366
|
if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
|
|
1367
1367
|
return active++, metadata.size > MAX_BYTES ? multipartCreate(input, metadata, (suffix, init2, kind, signal) => kind === !0 ? send(suffix, init2, !0, context2, signal) : send(suffix, init2, "control", context2, signal)) : timed(async (signal) => {
|
|
1368
1368
|
try {
|
|
1369
|
-
let bytes =
|
|
1369
|
+
let bytes = array3 ? input.file.slice() : await boundedBytes(
|
|
1370
1370
|
blob ? input.file.stream() : input.file,
|
|
1371
1371
|
metadata.size
|
|
1372
1372
|
);
|
|
@@ -1412,8 +1412,8 @@ var files = {
|
|
|
1412
1412
|
return result2;
|
|
1413
1413
|
}, context2);
|
|
1414
1414
|
},
|
|
1415
|
-
async get(
|
|
1416
|
-
return operation((context2, signal) => send(idPath(
|
|
1415
|
+
async get(id3) {
|
|
1416
|
+
return operation((context2, signal) => send(idPath(id3), { method: "GET" }, !0, context2, signal));
|
|
1417
1417
|
},
|
|
1418
1418
|
read
|
|
1419
1419
|
};
|
|
@@ -1515,12 +1515,12 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1515
1515
|
baseId,
|
|
1516
1516
|
table: input.table,
|
|
1517
1517
|
operation: operation2.slice(8),
|
|
1518
|
-
records: ids2.map((
|
|
1518
|
+
records: ids2.map((id3) => ({ id: id3 }))
|
|
1519
1519
|
});
|
|
1520
1520
|
async function request(path2, init2 = {}, write = !1) {
|
|
1521
|
-
let
|
|
1521
|
+
let response2;
|
|
1522
1522
|
try {
|
|
1523
|
-
|
|
1523
|
+
response2 = await (options.fetch ?? fetch)(`https://api.airtable.com/v0/${path2}`, {
|
|
1524
1524
|
...init2,
|
|
1525
1525
|
headers: { authorization: `Bearer ${accessToken}`, "content-type": "application/json" },
|
|
1526
1526
|
redirect: "manual",
|
|
@@ -1529,12 +1529,12 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1529
1529
|
} catch {
|
|
1530
1530
|
throw new AirtableOperationError("Airtable request acknowledgment unavailable", write ? "uncertain" : "unapplied");
|
|
1531
1531
|
}
|
|
1532
|
-
if (!
|
|
1533
|
-
throw await
|
|
1534
|
-
}), new AirtableOperationError("Airtable request rejected", write && (
|
|
1532
|
+
if (!response2.ok)
|
|
1533
|
+
throw await response2.body?.cancel().catch(() => {
|
|
1534
|
+
}), new AirtableOperationError("Airtable request rejected", write && (response2.status >= 500 || response2.status === 408 || response2.status < 400) ? "uncertain" : "unapplied");
|
|
1535
1535
|
try {
|
|
1536
|
-
if (!
|
|
1537
|
-
let value = object2(await
|
|
1536
|
+
if (!response2.headers.get("content-type")?.toLowerCase().includes("application/json")) throw new Error();
|
|
1537
|
+
let value = object2(await response2.json()), safe = serializable(value);
|
|
1538
1538
|
if (Object.hasOwn(value, "error") || JSON.stringify(safe).includes(accessToken)) throw new Error();
|
|
1539
1539
|
return value;
|
|
1540
1540
|
} catch {
|
|
@@ -1601,7 +1601,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1601
1601
|
}
|
|
1602
1602
|
await options.beforeMutation?.();
|
|
1603
1603
|
let query = new URLSearchParams();
|
|
1604
|
-
if (kind === "delete") for (let
|
|
1604
|
+
if (kind === "delete") for (let id3 of ids) query.append("records[]", id3);
|
|
1605
1605
|
let result2 = await request(`${path}${kind === "delete" ? `?${query}` : ""}`, {
|
|
1606
1606
|
method: kind === "create" ? "POST" : kind === "update" ? "PATCH" : "DELETE",
|
|
1607
1607
|
...kind === "delete" ? {} : { body: JSON.stringify({ records: records.map((r) => "id" in r ? { id: r.id, fields: r.set } : r) }) }
|
|
@@ -1640,14 +1640,14 @@ function managedConnections(capability) {
|
|
|
1640
1640
|
safeInput = null;
|
|
1641
1641
|
}
|
|
1642
1642
|
try {
|
|
1643
|
-
let
|
|
1643
|
+
let response2 = await fetch(new URL("airtable", endpoint), {
|
|
1644
1644
|
method: "POST",
|
|
1645
1645
|
redirect: "error",
|
|
1646
1646
|
headers: { authorization: `Bearer ${capability.token}`, "content-type": "application/json" },
|
|
1647
1647
|
body: JSON.stringify({ name, operation: operation2, input: safeInput }),
|
|
1648
1648
|
signal: AbortSignal.timeout(125e3)
|
|
1649
|
-
}), value = await
|
|
1650
|
-
if (!
|
|
1649
|
+
}), value = await response2.json();
|
|
1650
|
+
if (!response2.ok) throw new AirtableOperationError(
|
|
1651
1651
|
"Airtable operation failed; the execution retains its evidence",
|
|
1652
1652
|
value.effect === "partial" || value.effect === "uncertain" ? value.effect : "unapplied",
|
|
1653
1653
|
value.receipts ?? []
|
|
@@ -1770,6 +1770,411 @@ function validCreatePath(value) {
|
|
|
1770
1770
|
return value === value.trim() && value.endsWith(".md") && !value.startsWith("/") && value.split("/").every((segment) => !!segment && ![".", ".."].includes(segment) && /^[a-zA-Z0-9_.-]+$/.test(segment));
|
|
1771
1771
|
}
|
|
1772
1772
|
|
|
1773
|
+
var InboxOperationError = class extends Error {
|
|
1774
|
+
constructor(status, reason) {
|
|
1775
|
+
super(reason === "conflict" ? "This question already has an accepted answer" : reason === "unavailable" ? "Inbox request unavailable. Retry the same action." : reason === "invalid_input" ? "Invalid Inbox request" : "Inbox access unavailable");
|
|
1776
|
+
this.status = status;
|
|
1777
|
+
this.reason = reason;
|
|
1778
|
+
}
|
|
1779
|
+
status;
|
|
1780
|
+
reason;
|
|
1781
|
+
}, INBOX_RESULT_BYTES = 8 * 1024 * 1024, INBOX_INPUT_BYTES = 8192, INBOX_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, operations = {
|
|
1782
|
+
current: [],
|
|
1783
|
+
"items.list": [],
|
|
1784
|
+
"items.read": ["itemId"],
|
|
1785
|
+
"items.see": ["itemId"],
|
|
1786
|
+
"items.markDigestRead": ["itemId"],
|
|
1787
|
+
"items.rename": ["itemId", "revision", "title"],
|
|
1788
|
+
"items.setLifecycle": ["itemId", "revision", "lifecycle"],
|
|
1789
|
+
"items.listRecipientCandidates": ["itemId"],
|
|
1790
|
+
"items.addRecipient": ["itemId", "personId"],
|
|
1791
|
+
"questions.answer": ["itemId", "revision", "questionId", "response"],
|
|
1792
|
+
"questions.searchRecords": ["itemId", "revision", "questionId", "query"],
|
|
1793
|
+
"files.read": ["itemId", "fileId"]
|
|
1794
|
+
};
|
|
1795
|
+
function assert(value) {
|
|
1796
|
+
if (!value) throw new Error("Invalid Inbox result");
|
|
1797
|
+
}
|
|
1798
|
+
function object3(value) {
|
|
1799
|
+
return assert(value && typeof value == "object" && !Array.isArray(value) && [Object.prototype, null].includes(Object.getPrototypeOf(value)) && Reflect.ownKeys(value).every((key) => {
|
|
1800
|
+
let descriptor2 = typeof key == "string" ? Object.getOwnPropertyDescriptor(value, key) : void 0;
|
|
1801
|
+
return !!descriptor2?.enumerable && "value" in descriptor2;
|
|
1802
|
+
})), value;
|
|
1803
|
+
}
|
|
1804
|
+
function keys3(value, allowed, required = allowed) {
|
|
1805
|
+
assert(Object.keys(value).every((key) => allowed.includes(key)) && required.every((key) => Object.hasOwn(value, key)));
|
|
1806
|
+
}
|
|
1807
|
+
function text3(value, empty2 = !1) {
|
|
1808
|
+
return typeof value == "string" && (empty2 || !!value.trim());
|
|
1809
|
+
}
|
|
1810
|
+
function id2(value) {
|
|
1811
|
+
return typeof value == "string" && INBOX_UUID.test(value);
|
|
1812
|
+
}
|
|
1813
|
+
function integer(value, minimum = 1) {
|
|
1814
|
+
return Number.isSafeInteger(value) && Number(value) >= minimum;
|
|
1815
|
+
}
|
|
1816
|
+
function date(value) {
|
|
1817
|
+
return text3(value) && Number.isFinite(Date.parse(value));
|
|
1818
|
+
}
|
|
1819
|
+
function optionalDate(value) {
|
|
1820
|
+
return value === null || date(value);
|
|
1821
|
+
}
|
|
1822
|
+
function array2(value) {
|
|
1823
|
+
return assert(Array.isArray(value) && Object.getPrototypeOf(value) === Array.prototype && Reflect.ownKeys(value).length === value.length + 1 && value.every((_entry, index) => {
|
|
1824
|
+
let descriptor2 = Object.getOwnPropertyDescriptor(value, String(index));
|
|
1825
|
+
return !!descriptor2?.enumerable && "value" in descriptor2;
|
|
1826
|
+
})), value;
|
|
1827
|
+
}
|
|
1828
|
+
function json2(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
1829
|
+
if (value === null || typeof value == "boolean" || typeof value == "string" || typeof value == "number" && Number.isFinite(value)) return value;
|
|
1830
|
+
assert(value && typeof value == "object" && !ancestors.has(value)), ancestors.add(value);
|
|
1831
|
+
try {
|
|
1832
|
+
return Array.isArray(value) ? array2(value).map((entry) => json2(entry, ancestors)) : Object.fromEntries(Object.entries(object3(value)).map(([key, entry]) => [key, json2(entry, ancestors)]));
|
|
1833
|
+
} finally {
|
|
1834
|
+
ancestors.delete(value);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
function recordReference(value) {
|
|
1838
|
+
let record3 = object3(value);
|
|
1839
|
+
return keys3(record3, ["repository", "ref"]), assert(text3(record3.repository) && record3.repository === record3.repository.trim() && /^[a-z0-9][a-z0-9._/-]{0,127}$/.test(record3.repository) && !/\.\.|\/\//.test(record3.repository) && text3(record3.ref) && record3.ref === record3.ref.trim() && record3.ref.length <= 512 && /^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)+$/.test(record3.ref)), record3;
|
|
1840
|
+
}
|
|
1841
|
+
function responseDefinition(value) {
|
|
1842
|
+
let definition = object3(value);
|
|
1843
|
+
keys3(definition, ["type", "source"]), assert(definition.type === "selection");
|
|
1844
|
+
let source = object3(definition.source);
|
|
1845
|
+
if (source.type === "authored") {
|
|
1846
|
+
keys3(source, ["type", "options", "suggestions", "search"], ["type", "options"]);
|
|
1847
|
+
let options = array2(source.options);
|
|
1848
|
+
assert(options.length > 0);
|
|
1849
|
+
let values = options.map((value2) => {
|
|
1850
|
+
let option = object3(value2);
|
|
1851
|
+
if (keys3(option, ["value", "label", "description", "note"], ["value", "label"]), assert(text3(option.value) && option.value === option.value.trim() && text3(option.label)), "description" in option && assert(text3(option.description)), "note" in option) {
|
|
1852
|
+
let note = object3(option.note);
|
|
1853
|
+
keys3(note, ["placeholder"]), assert(text3(note.placeholder));
|
|
1854
|
+
}
|
|
1855
|
+
return option.value;
|
|
1856
|
+
});
|
|
1857
|
+
if (assert(new Set(values).size === values.length), "search" in source || "suggestions" in source) {
|
|
1858
|
+
let search = object3(source.search);
|
|
1859
|
+
keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text3(search.triggerLabel) && text3(search.placeholder) && text3(search.emptyLabel));
|
|
1860
|
+
let suggestions2 = array2(source.suggestions);
|
|
1861
|
+
assert(suggestions2.length <= 8 && suggestions2.every((value2) => text3(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
|
|
1862
|
+
} else assert(options.length <= 9);
|
|
1863
|
+
return;
|
|
1864
|
+
}
|
|
1865
|
+
assert(source.type === "records"), keys3(source, ["type", "collection", "refPrefix", "where", "display", "suggestions"], ["type", "collection", "display"]);
|
|
1866
|
+
let collection = object3(source.collection);
|
|
1867
|
+
keys3(collection, ["repository", "name"]), recordReference({ repository: collection.repository, ref: "records/example" }), assert(text3(collection.name) && /^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(collection.name)), "refPrefix" in source && assert(text3(source.refPrefix) && source.refPrefix.length <= 512 && /^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)*\/$/.test(source.refPrefix));
|
|
1868
|
+
let where = object3(source.where ?? {});
|
|
1869
|
+
assert(Object.entries(where).every(([name, value2]) => /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) && !["constructor", "prototype"].includes(name) && (value2 === null || typeof value2 == "string" || typeof value2 == "boolean" || typeof value2 == "number" && Number.isFinite(value2))));
|
|
1870
|
+
let display = object3(source.display);
|
|
1871
|
+
keys3(display, ["labelFields"]);
|
|
1872
|
+
let labels = array2(display.labelFields);
|
|
1873
|
+
assert(labels.length > 0 && labels.length <= 2 && new Set(labels).size === labels.length && labels.every((value2) => text3(value2) && /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(value2)));
|
|
1874
|
+
let suggestions = array2(source.suggestions ?? []), refs = suggestions.map((value2) => {
|
|
1875
|
+
let suggestion = object3(value2);
|
|
1876
|
+
keys3(suggestion, ["record", "reason"], ["record"]);
|
|
1877
|
+
let record3 = recordReference(suggestion.record);
|
|
1878
|
+
return assert(record3.repository === collection.repository), "reason" in suggestion && assert(text3(suggestion.reason)), record3.ref;
|
|
1879
|
+
});
|
|
1880
|
+
assert(suggestions.length <= 8 && new Set(refs).size === refs.length);
|
|
1881
|
+
}
|
|
1882
|
+
function inboxFile(value) {
|
|
1883
|
+
let file2 = object3(value);
|
|
1884
|
+
keys3(file2, ["id", "name", "mediaType", "size", "sha256", "details"]), assert(id2(file2.id) && text3(file2.name) && !/[\x00-\x1f\x7f/\\]/.test(file2.name) && text3(file2.mediaType) && /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/.test(file2.mediaType) && integer(file2.size, 0) && file2.size <= 25 * 1024 * 1024 && typeof file2.sha256 == "string" && /^[0-9a-f]{64}$/.test(file2.sha256));
|
|
1885
|
+
let details = object3(file2.details);
|
|
1886
|
+
details.kind === "csv" ? (keys3(details, ["kind", "encoding", "delimiter", "headerRow", "dataRows"]), assert(file2.mediaType === "text/csv" && ["utf-8", "windows-1252"].includes(String(details.encoding)) && [",", ";", " "].includes(String(details.delimiter)) && integer(details.headerRow, 0) && integer(details.dataRows, 0))) : details.kind === "pdf" ? (keys3(details, ["kind", "pages"], ["kind"]), assert(file2.mediaType === "application/pdf" && (!("pages" in details) || integer(details.pages)))) : (keys3(details, ["kind"]), assert(details.kind === "other" && !["text/csv", "application/pdf"].includes(file2.mediaType)));
|
|
1887
|
+
}
|
|
1888
|
+
function fields4(value) {
|
|
1889
|
+
let labels = array2(value).map((value2) => {
|
|
1890
|
+
let field = object3(value2);
|
|
1891
|
+
return keys3(field, ["label", "value"]), assert(text3(field.label) && text3(field.value)), field.label;
|
|
1892
|
+
});
|
|
1893
|
+
assert(new Set(labels).size === labels.length);
|
|
1894
|
+
}
|
|
1895
|
+
function block(value) {
|
|
1896
|
+
let entry = object3(value);
|
|
1897
|
+
if (entry.kind === "rich-text") {
|
|
1898
|
+
keys3(entry, ["kind", "markdown"]), assert(text3(entry.markdown));
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
if (entry.kind === "asks") {
|
|
1902
|
+
keys3(entry, ["kind", "problem", "asks"]);
|
|
1903
|
+
let asks = array2(entry.asks);
|
|
1904
|
+
assert(text3(entry.problem) && asks.length > 0 && asks.every(id2) && new Set(asks).size === asks.length);
|
|
1905
|
+
return;
|
|
1906
|
+
}
|
|
1907
|
+
if (assert(["record", "records", "files"].includes(String(entry.kind))), keys3(
|
|
1908
|
+
entry,
|
|
1909
|
+
["kind", "label", "initiallyExpanded", ...entry.kind === "record" ? ["record", "view"] : entry.kind === "records" ? ["records", "view"] : ["files"]],
|
|
1910
|
+
["kind", "label", entry.kind === "record" ? "record" : entry.kind === "records" ? "records" : "files"]
|
|
1911
|
+
), assert(text3(entry.label) && (!("initiallyExpanded" in entry) || typeof entry.initiallyExpanded == "boolean") && (!("view" in entry) || text3(entry.view) && entry.view === entry.view.trim())), entry.kind === "record") {
|
|
1912
|
+
let record3 = object3(entry.record);
|
|
1913
|
+
keys3(record3, ["ref", "title", "fields"]), assert(text3(record3.ref) && record3.ref === record3.ref.trim() && text3(record3.title)), fields4(record3.fields);
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
if (entry.kind === "records") {
|
|
1917
|
+
let records = array2(entry.records), refs = records.map((value2) => {
|
|
1918
|
+
let record3 = object3(value2);
|
|
1919
|
+
return keys3(record3, ["ref", "title", "description", "facts", "view"], ["ref", "title"]), assert(text3(record3.ref) && record3.ref === record3.ref.trim() && text3(record3.title)), "description" in record3 && assert(text3(record3.description)), "facts" in record3 && fields4(record3.facts), "view" in record3 && assert(text3(record3.view) && record3.view === record3.view.trim()), record3.ref;
|
|
1920
|
+
});
|
|
1921
|
+
assert(records.length > 0 && new Set(refs).size === refs.length);
|
|
1922
|
+
return;
|
|
1923
|
+
}
|
|
1924
|
+
let files3 = array2(entry.files);
|
|
1925
|
+
files3.forEach(inboxFile), assert(files3.length > 0 && new Set(files3.map((value2) => object3(value2).id)).size === files3.length);
|
|
1926
|
+
}
|
|
1927
|
+
function response(value) {
|
|
1928
|
+
let answer = object3(value);
|
|
1929
|
+
return assert(Object.keys(answer).every((key) => ["selection", "note"].includes(key))), typeof answer.selection == "string" ? assert(text3(answer.selection) && answer.selection === answer.selection.trim()) : recordReference(answer.selection), Object.hasOwn(answer, "note") && assert(text3(answer.note)), answer;
|
|
1930
|
+
}
|
|
1931
|
+
function parseInboxRequest(value) {
|
|
1932
|
+
try {
|
|
1933
|
+
let envelope = object3(value);
|
|
1934
|
+
assert(Object.keys(envelope).sort().join(",") === "input,operation"), assert(typeof envelope.operation == "string" && Object.hasOwn(operations, envelope.operation));
|
|
1935
|
+
let operation2 = envelope.operation, input = object3(envelope.input), required = operations[operation2];
|
|
1936
|
+
assert(required.every((key) => Object.hasOwn(input, key)) && Object.keys(input).every((key) => required.includes(key) || operation2 === "questions.searchRecords" && key === "selected" || operation2 === "items.list" && key === "beforeNumber"));
|
|
1937
|
+
for (let key of ["itemId", "personId", "fileId"]) key in input && assert(id2(input[key]));
|
|
1938
|
+
return "revision" in input && assert(integer(input.revision)), "beforeNumber" in input && assert(integer(input.beforeNumber)), "questionId" in input && assert(text3(input.questionId) && input.questionId === input.questionId.trim()), "title" in input && assert(text3(input.title)), "lifecycle" in input && assert(input.lifecycle === "open" || input.lifecycle === "closed"), "query" in input && assert(text3(input.query, !0) && input.query.length <= 256), "selected" in input && recordReference(input.selected), "response" in input && response(input.response), assert(new TextEncoder().encode(JSON.stringify(envelope)).byteLength <= INBOX_INPUT_BYTES), { operation: operation2, input };
|
|
1939
|
+
} catch {
|
|
1940
|
+
throw new InboxOperationError(400, "invalid_input");
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
function parseInboxCurrent(value) {
|
|
1944
|
+
let current2 = object3(value), workspace = object3(current2.workspace), viewer = object3(current2.viewer);
|
|
1945
|
+
return assert(id2(workspace.id) && text3(workspace.slug) && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(workspace.slug) && text3(workspace.name) && text3(workspace.locale) && text3(workspace.timezone)), assert(id2(viewer.id) && text3(viewer.name) && text3(viewer.email)), {
|
|
1946
|
+
workspace: { id: workspace.id, slug: workspace.slug, name: workspace.name, locale: workspace.locale, timezone: workspace.timezone },
|
|
1947
|
+
viewer: { id: viewer.id, name: viewer.name, email: viewer.email }
|
|
1948
|
+
};
|
|
1949
|
+
}
|
|
1950
|
+
function parseInboxItem(value) {
|
|
1951
|
+
let item = object3(json2(value));
|
|
1952
|
+
return assert(id2(item.id) && id2(item.workspaceId) && integer(item.number) && integer(item.revision) && integer(item.activityVersion, 0) && ["ask", "digest"].includes(String(item.kind)) && ["open", "closed"].includes(String(item.lifecycle)) && text3(item.title) && text3(item.description, !0) && text3(item.author) && date(item.publishedAt) && optionalDate(item.seenAt) && optionalDate(item.digestReadAt)), item.outcome !== null && assert(text3(object3(item.outcome).outcome)), array2(item.body).forEach(block), array2(item.views).forEach((value2) => {
|
|
1953
|
+
let view = object3(value2);
|
|
1954
|
+
assert(text3(view.id) && text3(view.view) && text3(view.implementation)), json2(view.input);
|
|
1955
|
+
}), array2(item.people).forEach((value2) => {
|
|
1956
|
+
let person = object3(value2);
|
|
1957
|
+
assert(id2(person.id) && text3(person.name));
|
|
1958
|
+
}), array2(item.questions).forEach((value2) => {
|
|
1959
|
+
let question2 = object3(value2);
|
|
1960
|
+
if (assert(text3(question2.id) && id2(question2.to) && text3(question2.prompt) && (question2.instructions === null || text3(question2.instructions, !0)) && typeof question2.available == "boolean"), responseDefinition(question2.response), assert(array2(question2.allowedResponders).every(id2)), question2.acceptedResponse !== null) {
|
|
1961
|
+
let accepted = object3(question2.acceptedResponse);
|
|
1962
|
+
assert(id2(accepted.id) && id2(accepted.userId) && date(accepted.acceptedAt)), response(accepted.response), accepted.label === null ? delete accepted.label : "label" in accepted && assert(text3(accepted.label)), "acceptanceOrder" in accepted && assert(integer(accepted.acceptanceOrder));
|
|
1963
|
+
}
|
|
1964
|
+
if (question2.execution !== null) {
|
|
1965
|
+
let execution = object3(question2.execution);
|
|
1966
|
+
if (assert(id2(execution.id) && ["pending", "running", "completed", "failed"].includes(String(execution.state)) && integer(execution.attempt, 0)), "consequence" in execution) {
|
|
1967
|
+
let consequence = object3(execution.consequence);
|
|
1968
|
+
assert(["pending", "running", "applied", "no-write", "stopped", "partial", "uncertain"].includes(String(consequence.state)) && (consequence.phase === null || ["loading", "invoking", "committing"].includes(String(consequence.phase))) && date(consequence.updatedAt) && typeof consequence.needsReconciliation == "boolean" && (consequence.reason === null || text3(consequence.reason, !0))), array2(consequence.evidence).forEach((value3) => {
|
|
1969
|
+
let receipt = object3(value3);
|
|
1970
|
+
assert(text3(receipt.repository) && text3(receipt.commit) && text3(receipt.diff, !0));
|
|
1971
|
+
});
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
}), array2(item.linkedAsks).forEach((value2) => {
|
|
1975
|
+
let linked = object3(value2);
|
|
1976
|
+
if (assert(id2(linked.id)), linked.state === "unavailable") assert(typeof linked.done == "boolean");
|
|
1977
|
+
else if (assert(["yours", "done", "open", "theirs"].includes(String(linked.state)) && text3(linked.title)), linked.state === "theirs") {
|
|
1978
|
+
let assignee = object3(linked.assignee);
|
|
1979
|
+
assert(id2(assignee.id) && text3(assignee.name));
|
|
1980
|
+
}
|
|
1981
|
+
}), array2(item.activity).forEach((value2) => {
|
|
1982
|
+
let event2 = object3(value2);
|
|
1983
|
+
assert(integer(event2.id) && text3(event2.type) && (event2.actorId === null || id2(event2.actorId)) && (event2.questionId === null || text3(event2.questionId)) && integer(event2.revision) && date(event2.createdAt)), object3(event2.data);
|
|
1984
|
+
}), array2(item.work).forEach((value2) => {
|
|
1985
|
+
let work = object3(value2);
|
|
1986
|
+
assert(id2(work.id) && text3(work.questionId) && text3(work.reason) && optionalDate(work.settledAt));
|
|
1987
|
+
}), item;
|
|
1988
|
+
}
|
|
1989
|
+
function parseInboxAcceptance(value) {
|
|
1990
|
+
let accepted = object3(value);
|
|
1991
|
+
return assert(id2(accepted.responseId) && date(accepted.acceptedAt)), "executionId" in accepted && assert(id2(accepted.executionId)), "acceptanceOrder" in accepted && assert(integer(accepted.acceptanceOrder)), "label" in accepted && assert(text3(accepted.label)), accepted;
|
|
1992
|
+
}
|
|
1993
|
+
function parseInboxResult(operation2, value) {
|
|
1994
|
+
if (operation2 === "current") return parseInboxCurrent(value);
|
|
1995
|
+
if (operation2 === "items.read") return parseInboxItem(value);
|
|
1996
|
+
if (operation2 === "items.list") {
|
|
1997
|
+
let page = object3(value), items = array2(page.items).map(parseInboxItem);
|
|
1998
|
+
return assert(items.length <= 100 && (page.nextBeforeNumber === null || integer(page.nextBeforeNumber))), { items, nextBeforeNumber: page.nextBeforeNumber };
|
|
1999
|
+
}
|
|
2000
|
+
if (operation2 === "items.see") {
|
|
2001
|
+
assert(date(value));
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
if (operation2 === "items.markDigestRead") {
|
|
2005
|
+
let read2 = object3(value);
|
|
2006
|
+
return assert(integer(read2.activityId) && date(read2.readAt)), read2;
|
|
2007
|
+
}
|
|
2008
|
+
if (operation2 === "items.rename" || operation2 === "items.setLifecycle") {
|
|
2009
|
+
let update = object3(value), item = parseInboxItem(update.item);
|
|
2010
|
+
return assert((update.activityId === null || integer(update.activityId)) && optionalDate(update.changedAt)), { ...update, item };
|
|
2011
|
+
}
|
|
2012
|
+
if (operation2 === "items.listRecipientCandidates") {
|
|
2013
|
+
let candidates = array2(value);
|
|
2014
|
+
return candidates.forEach((value2) => {
|
|
2015
|
+
let person = object3(value2);
|
|
2016
|
+
assert(id2(person.id) && text3(person.name) && text3(person.email));
|
|
2017
|
+
}), assert(new Set(candidates.map((value2) => object3(value2).id)).size === candidates.length), candidates;
|
|
2018
|
+
}
|
|
2019
|
+
if (operation2 === "items.addRecipient") {
|
|
2020
|
+
let addition = object3(value), item = parseInboxItem(addition.item);
|
|
2021
|
+
return assert(id2(addition.addedPersonId) && item.people.some((person) => person.id === addition.addedPersonId)), { ...addition, item };
|
|
2022
|
+
}
|
|
2023
|
+
if (operation2 === "questions.answer") return parseInboxAcceptance(value);
|
|
2024
|
+
if (operation2 === "questions.searchRecords") {
|
|
2025
|
+
let result2 = object3(value);
|
|
2026
|
+
assert(text3(result2.recordType) && integer(result2.eligibleCount, 0) && integer(result2.matchCount, 0) && Number(result2.matchCount) <= Number(result2.eligibleCount));
|
|
2027
|
+
let labeled = (value2) => {
|
|
2028
|
+
let record3 = object3(value2);
|
|
2029
|
+
recordReference({ repository: record3.repository, ref: record3.ref }), assert(text3(record3.label)), "reason" in record3 && assert(text3(record3.reason));
|
|
2030
|
+
};
|
|
2031
|
+
return array2(result2.matches).forEach(labeled), array2(result2.suggestions).forEach(labeled), "selected" in result2 && labeled(result2.selected), result2;
|
|
2032
|
+
}
|
|
2033
|
+
throw new Error("File content is not a JSON result");
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
async function limitedBody(request, limit, timeoutMs) {
|
|
2037
|
+
if (!request.body) return new Uint8Array();
|
|
2038
|
+
let reader = request.body.getReader(), expired = !1, timer = timeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
2039
|
+
expired = !0, reader.cancel().catch(() => {
|
|
2040
|
+
});
|
|
2041
|
+
}, timeoutMs), chunks = [], length = 0;
|
|
2042
|
+
try {
|
|
2043
|
+
for (; ; ) {
|
|
2044
|
+
let { done, value } = await reader.read();
|
|
2045
|
+
if (done) break;
|
|
2046
|
+
if (length += value.byteLength, length > limit) {
|
|
2047
|
+
await reader.cancel();
|
|
2048
|
+
return;
|
|
2049
|
+
}
|
|
2050
|
+
chunks.push(value);
|
|
2051
|
+
}
|
|
2052
|
+
if (expired) return;
|
|
2053
|
+
let contents = new Uint8Array(length), offset = 0;
|
|
2054
|
+
for (let chunk of chunks)
|
|
2055
|
+
contents.set(chunk, offset), offset += chunk.byteLength;
|
|
2056
|
+
return contents;
|
|
2057
|
+
} finally {
|
|
2058
|
+
timer !== void 0 && clearTimeout(timer);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
var unavailable2 = () => new InboxOperationError(503, "unavailable"), stale = () => new InboxOperationError(401, "authority_unavailable");
|
|
2063
|
+
async function send2(operation2, input) {
|
|
2064
|
+
let envelope = parseInboxRequest({ operation: operation2, input }), context2;
|
|
2065
|
+
try {
|
|
2066
|
+
context2 = await resolveAppContext();
|
|
2067
|
+
} catch {
|
|
2068
|
+
throw stale();
|
|
2069
|
+
}
|
|
2070
|
+
if (context2.kind === "local" || context2.endpoint !== `https://${context2.workspace}.oddington.ai` || ["auth", "www", "api", "os"].includes(context2.workspace)) throw stale();
|
|
2071
|
+
let check = () => {
|
|
2072
|
+
if (!context2.isCurrent() || !Number.isFinite(context2.expiresAt) || context2.expiresAt <= Date.now()) throw stale();
|
|
2073
|
+
};
|
|
2074
|
+
check();
|
|
2075
|
+
try {
|
|
2076
|
+
let response2 = await fetch(`${context2.endpoint}/api/inbox`, {
|
|
2077
|
+
method: "POST",
|
|
2078
|
+
headers: { authorization: `Bearer ${context2.accessToken}`, "content-type": "application/json" },
|
|
2079
|
+
body: JSON.stringify(envelope),
|
|
2080
|
+
redirect: "error",
|
|
2081
|
+
cache: "no-store",
|
|
2082
|
+
signal: AbortSignal.timeout(3e4)
|
|
2083
|
+
});
|
|
2084
|
+
try {
|
|
2085
|
+
check();
|
|
2086
|
+
} catch (error) {
|
|
2087
|
+
throw response2.body?.cancel().catch(() => {
|
|
2088
|
+
}), error;
|
|
2089
|
+
}
|
|
2090
|
+
if (!response2.ok)
|
|
2091
|
+
throw response2.body?.cancel().catch(() => {
|
|
2092
|
+
}), new InboxOperationError(
|
|
2093
|
+
[400, 401, 403, 409].includes(response2.status) ? response2.status : 503,
|
|
2094
|
+
response2.status === 400 ? "invalid_input" : response2.status === 401 ? "authority_unavailable" : response2.status === 403 ? "access_denied" : response2.status === 409 ? "conflict" : "unavailable"
|
|
2095
|
+
);
|
|
2096
|
+
if (response2.status !== 200)
|
|
2097
|
+
throw response2.body?.cancel().catch(() => {
|
|
2098
|
+
}), unavailable2();
|
|
2099
|
+
if (operation2 === "files.read") {
|
|
2100
|
+
if (!response2.body) throw unavailable2();
|
|
2101
|
+
let source = response2.body, reader, size = 0, cancel = async (reason) => {
|
|
2102
|
+
try {
|
|
2103
|
+
await (reader ? reader.cancel(reason) : source.cancel(reason));
|
|
2104
|
+
} finally {
|
|
2105
|
+
reader?.releaseLock();
|
|
2106
|
+
}
|
|
2107
|
+
}, body2 = new ReadableStream({
|
|
2108
|
+
async pull(controller) {
|
|
2109
|
+
try {
|
|
2110
|
+
check(), reader ??= source.getReader();
|
|
2111
|
+
let next = await reader.read();
|
|
2112
|
+
if (check(), next.done) {
|
|
2113
|
+
reader.releaseLock(), controller.close();
|
|
2114
|
+
return;
|
|
2115
|
+
}
|
|
2116
|
+
if (size += next.value.byteLength, size > 25 * 1024 * 1024) throw unavailable2();
|
|
2117
|
+
controller.enqueue(next.value);
|
|
2118
|
+
} catch (error) {
|
|
2119
|
+
controller.error(error), await cancel(error).catch(() => {
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2122
|
+
},
|
|
2123
|
+
cancel
|
|
2124
|
+
}, { highWaterMark: 0 });
|
|
2125
|
+
return new Response(body2, { status: response2.status, headers: response2.headers });
|
|
2126
|
+
}
|
|
2127
|
+
let bytes = await limitedBody(response2, INBOX_RESULT_BYTES);
|
|
2128
|
+
if (check(), !bytes) throw unavailable2();
|
|
2129
|
+
let value = JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes)), parsed = parseInboxResult(operation2, value);
|
|
2130
|
+
if (check(), operation2 === "current" && parsed.workspace.slug !== context2.workspace) throw unavailable2();
|
|
2131
|
+
if ("itemId" in envelope.input) {
|
|
2132
|
+
let item = operation2 === "items.read" ? parsed : operation2 === "items.rename" || operation2 === "items.setLifecycle" || operation2 === "items.addRecipient" ? parsed.item : void 0;
|
|
2133
|
+
if (item && (item.id !== envelope.input.itemId || "revision" in envelope.input && item.revision !== envelope.input.revision) || operation2 === "items.addRecipient" && parsed.addedPersonId !== envelope.input.personId || operation2 === "questions.answer" && typeof envelope.input.response.selection == "object" && !parsed.label?.trim()) throw unavailable2();
|
|
2134
|
+
}
|
|
2135
|
+
return parsed;
|
|
2136
|
+
} catch (error) {
|
|
2137
|
+
throw check(), error instanceof InboxOperationError ? error : unavailable2();
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
var inbox = {
|
|
2141
|
+
current: async () => await send2("current", {}),
|
|
2142
|
+
items: {
|
|
2143
|
+
async list() {
|
|
2144
|
+
let items = [], beforeNumber, initial;
|
|
2145
|
+
try {
|
|
2146
|
+
initial = await resolveAppContext();
|
|
2147
|
+
} catch {
|
|
2148
|
+
throw stale();
|
|
2149
|
+
}
|
|
2150
|
+
let check = () => {
|
|
2151
|
+
if (!initial.isCurrent() || initial.expiresAt <= Date.now()) throw stale();
|
|
2152
|
+
};
|
|
2153
|
+
do {
|
|
2154
|
+
check();
|
|
2155
|
+
let page = await send2("items.list", beforeNumber === void 0 ? {} : { beforeNumber });
|
|
2156
|
+
if (check(), beforeNumber !== void 0 && (page.items.some((item) => item.number >= beforeNumber) || page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber)) throw unavailable2();
|
|
2157
|
+
if (items.push(...page.items), page.nextBeforeNumber === null) return items;
|
|
2158
|
+
beforeNumber = page.nextBeforeNumber;
|
|
2159
|
+
} while (!0);
|
|
2160
|
+
},
|
|
2161
|
+
read: async (itemId) => await send2("items.read", { itemId }),
|
|
2162
|
+
see: async (itemId) => {
|
|
2163
|
+
await send2("items.see", { itemId });
|
|
2164
|
+
},
|
|
2165
|
+
markDigestRead: async (itemId) => await send2("items.markDigestRead", { itemId }),
|
|
2166
|
+
rename: async (input) => await send2("items.rename", input),
|
|
2167
|
+
setLifecycle: async (input) => await send2("items.setLifecycle", input),
|
|
2168
|
+
listRecipientCandidates: async (itemId) => await send2("items.listRecipientCandidates", { itemId }),
|
|
2169
|
+
addRecipient: async (input) => await send2("items.addRecipient", input)
|
|
2170
|
+
},
|
|
2171
|
+
questions: {
|
|
2172
|
+
answer: async (input) => await send2("questions.answer", input),
|
|
2173
|
+
searchRecords: async (input) => await send2("questions.searchRecords", input)
|
|
2174
|
+
},
|
|
2175
|
+
files: { read: async (input) => await send2("files.read", input) }
|
|
2176
|
+
};
|
|
2177
|
+
|
|
1773
2178
|
var sources = /* @__PURE__ */ new WeakMap();
|
|
1774
2179
|
function registerBrowserAuth(handle2, source) {
|
|
1775
2180
|
sources.set(handle2, source);
|
|
@@ -1782,14 +2187,14 @@ var sessionKey = "_os.app.session", responseChecks = /* @__PURE__ */ new WeakMap
|
|
|
1782
2187
|
}, AppContextDenied = class extends Error {
|
|
1783
2188
|
}, AppRenewalUnavailable = class extends Error {
|
|
1784
2189
|
};
|
|
1785
|
-
async function appResponse(
|
|
1786
|
-
if (signal.aborted || !
|
|
1787
|
-
let reader =
|
|
2190
|
+
async function appResponse(response2, maximum, signal) {
|
|
2191
|
+
if (signal.aborted || !response2.body || response2.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() !== "application/json") throw new Error();
|
|
2192
|
+
let reader = response2.body.getReader(), abort = () => {
|
|
1788
2193
|
reader.cancel().catch(() => {
|
|
1789
2194
|
});
|
|
1790
2195
|
};
|
|
1791
2196
|
signal.addEventListener("abort", abort, { once: !0 });
|
|
1792
|
-
let bytes = 0,
|
|
2197
|
+
let bytes = 0, text4 = "", decoder = new TextDecoder("utf-8", { fatal: !0 });
|
|
1793
2198
|
try {
|
|
1794
2199
|
for (; ; ) {
|
|
1795
2200
|
let chunk;
|
|
@@ -1800,13 +2205,13 @@ async function appResponse(response, maximum, signal) {
|
|
|
1800
2205
|
}
|
|
1801
2206
|
if (signal.aborted) throw new Error();
|
|
1802
2207
|
if (chunk.done) {
|
|
1803
|
-
let value = JSON.parse(
|
|
1804
|
-
if (await responseChecks.get(
|
|
2208
|
+
let value = JSON.parse(text4 + decoder.decode());
|
|
2209
|
+
if (await responseChecks.get(response2)?.(value), signal.aborted) throw new Error();
|
|
1805
2210
|
return value;
|
|
1806
2211
|
}
|
|
1807
2212
|
if (bytes += chunk.value.byteLength, bytes > maximum)
|
|
1808
2213
|
throw abort(), new Error();
|
|
1809
|
-
|
|
2214
|
+
text4 += decoder.decode(chunk.value, { stream: !0 });
|
|
1810
2215
|
}
|
|
1811
2216
|
} finally {
|
|
1812
2217
|
signal.removeEventListener("abort", abort), reader.releaseLock();
|
|
@@ -1844,7 +2249,7 @@ function appContext(origin, active2) {
|
|
|
1844
2249
|
}, sameSession = (value) => !binding || value.appId === binding.appId && value.memberId === binding.memberId && value.workspace === binding.workspace && value.sessionId === binding.sessionId, bounded = (value) => validBinding(value) && value.expiresAt > Date.now() && value.expiresAt <= Date.now() + 6e5 && sameSession(value);
|
|
1845
2250
|
async function proof(candidate, signal = controller.signal) {
|
|
1846
2251
|
if (!alive() || !/^[A-Za-z0-9_-]{43}$/.test(candidate)) throw new Error();
|
|
1847
|
-
let url = `${origin}/_os/app/context`,
|
|
2252
|
+
let url = `${origin}/_os/app/context`, response2 = await fetch(url, {
|
|
1848
2253
|
credentials: "omit",
|
|
1849
2254
|
redirect: "error",
|
|
1850
2255
|
cache: "no-store",
|
|
@@ -1852,10 +2257,10 @@ function appContext(origin, active2) {
|
|
|
1852
2257
|
headers: { authorization: `Bearer ${candidate}` },
|
|
1853
2258
|
signal
|
|
1854
2259
|
});
|
|
1855
|
-
if (
|
|
1856
|
-
if (
|
|
1857
|
-
if (!
|
|
1858
|
-
let value = await appResponse(
|
|
2260
|
+
if (response2.redirected || response2.url && response2.url !== url) throw new Error();
|
|
2261
|
+
if (response2.status === 401 || response2.status === 403) throw new AppContextDenied();
|
|
2262
|
+
if (!response2.ok) throw new Error();
|
|
2263
|
+
let value = await appResponse(response2, 4096, signal);
|
|
1859
2264
|
if (!alive() || !bounded(value)) throw new Error();
|
|
1860
2265
|
return value;
|
|
1861
2266
|
}
|
|
@@ -1906,9 +2311,9 @@ function appContext(origin, active2) {
|
|
|
1906
2311
|
let timeout = setTimeout(abort, Math.min(2e4, deadline - Date.now())), previous = credential;
|
|
1907
2312
|
try {
|
|
1908
2313
|
if (await synchronize(), credential !== previous) return;
|
|
1909
|
-
let url = `${origin}/_os/app/renew`,
|
|
2314
|
+
let url = `${origin}/_os/app/renew`, response2;
|
|
1910
2315
|
try {
|
|
1911
|
-
|
|
2316
|
+
response2 = await fetch(url, {
|
|
1912
2317
|
method: "POST",
|
|
1913
2318
|
credentials: "omit",
|
|
1914
2319
|
redirect: "error",
|
|
@@ -1920,11 +2325,11 @@ function appContext(origin, active2) {
|
|
|
1920
2325
|
} catch {
|
|
1921
2326
|
throw new AppRenewalUnavailable();
|
|
1922
2327
|
}
|
|
1923
|
-
if (
|
|
1924
|
-
let value = await appResponse(
|
|
1925
|
-
if (
|
|
2328
|
+
if (response2.redirected || response2.url && response2.url !== url) throw new Error();
|
|
2329
|
+
let value = await appResponse(response2, 4096, requestController.signal);
|
|
2330
|
+
if (response2.status === 503 && value && typeof value == "object" && !Array.isArray(value) && Object.keys(value).join(",") === "error" && "error" in value && value.error === "renewal_unavailable")
|
|
1926
2331
|
throw new AppRenewalUnavailable();
|
|
1927
|
-
if (
|
|
2332
|
+
if (response2.status === 403 && value && typeof value == "object" && !Array.isArray(value) && Object.keys(value).join(",") === "error" && "error" in value && value.error === "renewal_conflict") {
|
|
1928
2333
|
for (; alive() && stored() === previous && !requestController.signal.aborted; )
|
|
1929
2334
|
await new Promise((resolve2, reject) => {
|
|
1930
2335
|
let abortWait = () => {
|
|
@@ -1938,7 +2343,7 @@ function appContext(origin, active2) {
|
|
|
1938
2343
|
await synchronize();
|
|
1939
2344
|
return;
|
|
1940
2345
|
}
|
|
1941
|
-
if (!
|
|
2346
|
+
if (!response2.ok) throw new Error();
|
|
1942
2347
|
if (!alive() || Date.now() >= deadline || !value || typeof value != "object" || Array.isArray(value) || Object.keys(value).sort().join(",") !== "context,credential") throw new Error();
|
|
1943
2348
|
let result2 = value;
|
|
1944
2349
|
if (!bounded(result2.context) || typeof result2.credential != "string" || !/^[A-Za-z0-9_-]{43}$/.test(result2.credential) || result2.credential === previous) throw new Error();
|
|
@@ -1994,7 +2399,7 @@ function appContext(origin, active2) {
|
|
|
1994
2399
|
async function requestData(operation2, input) {
|
|
1995
2400
|
try {
|
|
1996
2401
|
if (operation2 !== "data/query" || !current2()) throw new Error();
|
|
1997
|
-
let url = `${origin}/_os/app/data`, admitted = credential,
|
|
2402
|
+
let url = `${origin}/_os/app/data`, admitted = credential, response2 = await fetch(url, {
|
|
1998
2403
|
method: "POST",
|
|
1999
2404
|
credentials: "omit",
|
|
2000
2405
|
redirect: "error",
|
|
@@ -2005,13 +2410,13 @@ function appContext(origin, active2) {
|
|
|
2005
2410
|
body: JSON.stringify(input)
|
|
2006
2411
|
});
|
|
2007
2412
|
for (await synchronize(); alive() && stored() !== credential; ) await synchronize();
|
|
2008
|
-
if (!current2() ||
|
|
2009
|
-
if (
|
|
2413
|
+
if (!current2() || response2.redirected || response2.url && response2.url !== url) throw new Error();
|
|
2414
|
+
if (response2.status === 401 || response2.status === 403)
|
|
2010
2415
|
throw admitted === credential && invalidate(), new DataOperationError("access_denied");
|
|
2011
|
-
let result2 = await appResponse(
|
|
2416
|
+
let result2 = await appResponse(response2, Number.MAX_SAFE_INTEGER, controller.signal);
|
|
2012
2417
|
for (await synchronize(); alive() && stored() !== credential; ) await synchronize();
|
|
2013
2418
|
if (!current2()) throw new Error();
|
|
2014
|
-
if (!
|
|
2419
|
+
if (!response2.ok) throw dataTransportError(response2.status, result2);
|
|
2015
2420
|
return result2;
|
|
2016
2421
|
} catch (error) {
|
|
2017
2422
|
throw error instanceof DataOperationError ? error : !current2() || controller.signal.aborted ? new DataOperationError("context_unavailable") : new DataOperationError("unavailable", !0);
|
|
@@ -2020,7 +2425,7 @@ function appContext(origin, active2) {
|
|
|
2020
2425
|
async function requestRoutine(key, suffix, init2 = {}) {
|
|
2021
2426
|
if (!current2())
|
|
2022
2427
|
throw invalidate(), new Error("Local app context unavailable.");
|
|
2023
|
-
let url = `${origin}/_os/app/routines/${encodeURIComponent(key)}/${suffix}`, admitted = credential,
|
|
2428
|
+
let url = `${origin}/_os/app/routines/${encodeURIComponent(key)}/${suffix}`, admitted = credential, response2 = await fetch(url, {
|
|
2024
2429
|
...init2,
|
|
2025
2430
|
credentials: "omit",
|
|
2026
2431
|
redirect: "error",
|
|
@@ -2030,12 +2435,12 @@ function appContext(origin, active2) {
|
|
|
2030
2435
|
headers: { ...init2.body === void 0 ? {} : { "content-type": "application/json" }, authorization: `Bearer ${credential}` }
|
|
2031
2436
|
});
|
|
2032
2437
|
for (await synchronize(); alive() && stored() !== credential; ) await synchronize();
|
|
2033
|
-
if (!current2() ||
|
|
2438
|
+
if (!current2() || response2.redirected || response2.url && response2.url !== url)
|
|
2034
2439
|
throw invalidate(), new Error("Local app context unavailable.");
|
|
2035
|
-
return (
|
|
2440
|
+
return (response2.status === 401 || response2.status === 403) && admitted === credential && invalidate(), responseChecks.set(response2, async (value) => {
|
|
2036
2441
|
for (await synchronize(); alive() && stored() !== credential; ) await synchronize();
|
|
2037
2442
|
admitted === credential && value && typeof value == "object" && "error" in value && value.error === "authority_unavailable" && invalidate();
|
|
2038
|
-
}),
|
|
2443
|
+
}), response2;
|
|
2039
2444
|
}
|
|
2040
2445
|
function context2() {
|
|
2041
2446
|
let issued = credential;
|
|
@@ -2144,9 +2549,9 @@ function authorizationConfiguration(value) {
|
|
|
2144
2549
|
if (!setup || typeof setup.clientId != "string" || !/^[A-Za-z0-9_-]{1,128}$/.test(setup.clientId) || setup.redirectUri !== CLI_CALLBACK || !Array.isArray(setup.scopes) || setup.scopes.length !== 1 || setup.scopes[0] !== "email") throw new Error("Unavailable");
|
|
2145
2550
|
return { clientId: setup.clientId, redirectUri: CLI_CALLBACK, scopes: ["email"] };
|
|
2146
2551
|
}
|
|
2147
|
-
function authorizationDetails(value,
|
|
2552
|
+
function authorizationDetails(value, id3, setup, userId, account) {
|
|
2148
2553
|
let details = value;
|
|
2149
|
-
return !details || details.authorization_id !==
|
|
2554
|
+
return !details || details.authorization_id !== id3 || details.redirect_uri !== setup.redirectUri || details.client?.id !== setup.clientId || typeof details.client.name != "string" || !details.client.name.trim() || details.client.name.length > 128 || /[\x00-\x1f\x7f]/.test(details.client.name) || details.user?.id !== userId || details.user.email !== account.email || typeof details.scope != "string" || details.scope.trim() !== "email" ? Object.freeze({ status: "invalid" }) : Object.freeze({
|
|
2150
2555
|
status: "consent",
|
|
2151
2556
|
clientName: details.client.name.trim(),
|
|
2152
2557
|
account,
|
|
@@ -2196,7 +2601,8 @@ function createBrowserAuth(runtime) {
|
|
|
2196
2601
|
}
|
|
2197
2602
|
function accept(c, event2, session) {
|
|
2198
2603
|
if (!c.active || event2 === "INITIAL_SESSION" && c.state.status !== "initializing" || event2 === "TOKEN_REFRESHED" && !c.session && c.state.status !== "initializing") return;
|
|
2199
|
-
|
|
2604
|
+
let replaced = c.session?.user?.id !== session?.user?.id || event2 === "SIGNED_OUT" || !!(event2 === "SIGNED_IN" && c.session && session?.access_token !== c.session.access_token);
|
|
2605
|
+
replaced && c.revision++, c.timer && clearTimeout(c.timer);
|
|
2200
2606
|
let pending = c.state.pending;
|
|
2201
2607
|
if (!session) {
|
|
2202
2608
|
c.session = null, publish(c, { status: c.state.status === "expired" ? "expired" : "signed_out", ...pending ? { pending } : {} }), notify(c, "SIGNED_OUT");
|
|
@@ -2207,8 +2613,8 @@ function createBrowserAuth(runtime) {
|
|
|
2207
2613
|
return;
|
|
2208
2614
|
}
|
|
2209
2615
|
c.session = session;
|
|
2210
|
-
let email = typeof session.user.email == "string" ? session.user.email.trim() : "", metadata = session.user.user_metadata,
|
|
2211
|
-
publish(c, { status: "signed_in", account
|
|
2616
|
+
let email = typeof session.user.email == "string" ? session.user.email.trim() : "", metadata = session.user.user_metadata, name = ["name", "full_name", "first_name"].map((key) => metadata?.[key]).find((value) => typeof value == "string" && value.trim())?.trim() || email, account = !replaced && c.state.account?.email === email && c.state.account.displayName === name ? c.state.account : Object.freeze({ email, displayName: name });
|
|
2617
|
+
publish(c, { status: "signed_in", account, ...pending ? { pending } : {} }), notify(c, event2);
|
|
2212
2618
|
let checkExpiry = () => {
|
|
2213
2619
|
if (!c.active || !c.session) return;
|
|
2214
2620
|
let remaining = c.session.expires_at * 1e3 - Date.now();
|
|
@@ -2234,9 +2640,9 @@ function createBrowserAuth(runtime) {
|
|
|
2234
2640
|
let revision = c.revision;
|
|
2235
2641
|
try {
|
|
2236
2642
|
if (!allowedOrigin(origin)) throw runtime.failure("unavailable");
|
|
2237
|
-
let
|
|
2238
|
-
if (!
|
|
2239
|
-
let configuration = validateConfiguration(await
|
|
2643
|
+
let response2 = await fetch(`${origin}/api/auth`, { method: "GET", credentials: "same-origin", redirect: "error", cache: "no-store" });
|
|
2644
|
+
if (!response2.ok) throw runtime.failure("unavailable");
|
|
2645
|
+
let configuration = validateConfiguration(await response2.json());
|
|
2240
2646
|
if (configuration.authorization && origin !== "https://auth.oddington.ai" && origin !== "http://127.0.0.1:5176") throw runtime.failure("unavailable");
|
|
2241
2647
|
if (c.authorization = configuration.authorization, !c.active || globalThis.location?.origin !== origin) return;
|
|
2242
2648
|
if (c.provider = await runtime.provider(configuration, {
|
|
@@ -2297,10 +2703,10 @@ function createBrowserAuth(runtime) {
|
|
|
2297
2703
|
coordinator.action === marker && (coordinator.action = void 0, coordinator.active && (publish(coordinator, { ...coordinator.state, pending: void 0 }), kind === "sign_out" && coordinator.session && notify(coordinator, "TOKEN_REFRESHED"))), ownedAction === marker && (ownedAction = void 0);
|
|
2298
2704
|
}
|
|
2299
2705
|
}
|
|
2300
|
-
async function authorize(kind,
|
|
2706
|
+
async function authorize(kind, id3) {
|
|
2301
2707
|
if (!active2) return Object.freeze({ status: "disposed" });
|
|
2302
|
-
if (
|
|
2303
|
-
if (typeof
|
|
2708
|
+
if (id3 !== authorizationId && (authorizationId = id3, authorizationGeneration++, inspected = void 0), !id3) return Object.freeze({ status: "missing" });
|
|
2709
|
+
if (typeof id3 != "string" || !/^[A-Za-z0-9_-]{1,128}$/.test(id3)) return Object.freeze({ status: "invalid" });
|
|
2304
2710
|
let generation = authorizationGeneration;
|
|
2305
2711
|
if (await coordinator.ready, !active2) return Object.freeze({ status: "disposed" });
|
|
2306
2712
|
if (generation !== authorizationGeneration) return Object.freeze({ status: "stale" });
|
|
@@ -2309,37 +2715,37 @@ function createBrowserAuth(runtime) {
|
|
|
2309
2715
|
if (!coordinator.session || coordinator.state.pending === "sign_out") return Object.freeze({ status: coordinator.state.status === "expired" ? "expired" : coordinator.state.status === "unavailable" ? "unavailable" : "signed_out" });
|
|
2310
2716
|
if (!coordinator.authorization || !coordinator.provider) return Object.freeze({ status: "unavailable" });
|
|
2311
2717
|
if (coordinator.action) return Object.freeze({ status: "busy" });
|
|
2312
|
-
if (kind !== "get" && (!inspected || inspected.id !==
|
|
2718
|
+
if (kind !== "get" && (!inspected || inspected.id !== id3 || inspected.revision !== revision)) return Object.freeze({ status: "stale" });
|
|
2313
2719
|
if (kind !== "get" && inspected?.result.status !== "consent") return inspected.result;
|
|
2314
2720
|
let marker = {};
|
|
2315
2721
|
coordinator.action = marker, ownedAction = marker;
|
|
2316
|
-
let requestCurrent = () => active2 && generation === authorizationGeneration && current2(coordinator, origin, revision) && coordinator.action === marker && !!coordinator.session && coordinator.state.pending !== "sign_out",
|
|
2722
|
+
let requestCurrent = () => active2 && generation === authorizationGeneration && current2(coordinator, origin, revision) && coordinator.action === marker && !!coordinator.session && coordinator.state.pending !== "sign_out", stale2 = () => Object.freeze({ status: active2 ? "stale" : "disposed" });
|
|
2317
2723
|
try {
|
|
2318
|
-
let provider2 = coordinator.provider,
|
|
2319
|
-
if (!requestCurrent()) return
|
|
2320
|
-
if (
|
|
2724
|
+
let provider2 = coordinator.provider, response2 = await provider2.authorization.get(id3, requestCurrent);
|
|
2725
|
+
if (!requestCurrent()) return stale2();
|
|
2726
|
+
if (response2.error) {
|
|
2321
2727
|
inspected = void 0;
|
|
2322
|
-
let failure = authorizationFailure(
|
|
2728
|
+
let failure = authorizationFailure(response2.error);
|
|
2323
2729
|
return failure.status === "signed_out" && expire(coordinator), failure;
|
|
2324
2730
|
}
|
|
2325
|
-
let account = coordinator.state.account, result2 =
|
|
2326
|
-
if (inspected = { id:
|
|
2327
|
-
if (!requestCurrent()) return
|
|
2328
|
-
let decision = await provider2.authorization[kind](
|
|
2329
|
-
if (!requestCurrent()) return
|
|
2731
|
+
let account = coordinator.state.account, result2 = response2.data && typeof response2.data == "object" && "redirect_url" in response2.data ? authorizationReturn(response2.data) : authorizationDetails(response2.data, id3, coordinator.authorization, coordinator.session.user.id, account);
|
|
2732
|
+
if (inspected = { id: id3, revision, result: result2 }, kind === "get" || result2.status !== "consent") return result2;
|
|
2733
|
+
if (!requestCurrent()) return stale2();
|
|
2734
|
+
let decision = await provider2.authorization[kind](id3, requestCurrent);
|
|
2735
|
+
if (!requestCurrent()) return stale2();
|
|
2330
2736
|
let returned = decision.error ? authorizationFailure(decision.error) : authorizationReturn(decision.data, kind);
|
|
2331
|
-
return returned.status === "signed_out" && expire(coordinator), inspected = { id:
|
|
2737
|
+
return returned.status === "signed_out" && expire(coordinator), inspected = { id: id3, revision, result: returned }, returned;
|
|
2332
2738
|
} catch (error) {
|
|
2333
|
-
return !requestCurrent() || (inspected = void 0, safeReason(error) === "stale") ?
|
|
2739
|
+
return !requestCurrent() || (inspected = void 0, safeReason(error) === "stale") ? stale2() : Object.freeze({ status: "unavailable" });
|
|
2334
2740
|
} finally {
|
|
2335
2741
|
coordinator.action === marker && (coordinator.action = void 0), ownedAction === marker && (ownedAction = void 0);
|
|
2336
2742
|
}
|
|
2337
2743
|
}
|
|
2338
2744
|
let handle2 = Object.freeze({
|
|
2339
2745
|
authorization: Object.freeze({
|
|
2340
|
-
get: (
|
|
2341
|
-
approve: (
|
|
2342
|
-
deny: (
|
|
2746
|
+
get: (id3) => authorize("get", id3),
|
|
2747
|
+
approve: (id3) => authorize("approve", id3),
|
|
2748
|
+
deny: (id3) => authorize("deny", id3)
|
|
2343
2749
|
}),
|
|
2344
2750
|
getState() {
|
|
2345
2751
|
return active2 && coordinator.session && !validSession(coordinator.session) && expire(coordinator), lastState;
|
|
@@ -2477,19 +2883,19 @@ async function provider(configuration, guard) {
|
|
|
2477
2883
|
throw request && (request.rejected = !0), new BrowserAuthError("stale");
|
|
2478
2884
|
};
|
|
2479
2885
|
request && (!request.current() || !guard.canAuthorize(new Headers(init2?.headers).get("authorization")?.replace(/^Bearer /, "") ?? "")) && rejectStale();
|
|
2480
|
-
let
|
|
2886
|
+
let response2 = await fetch(input, { ...init2, redirect: "error" }), body2 = await response2.arrayBuffer();
|
|
2481
2887
|
(!guard.current(revision) || request && !request.current()) && rejectStale();
|
|
2482
2888
|
let result2 = new Response(
|
|
2483
|
-
[204, 205, 304].includes(
|
|
2484
|
-
{ status:
|
|
2485
|
-
),
|
|
2889
|
+
[204, 205, 304].includes(response2.status) ? null : body2,
|
|
2890
|
+
{ status: response2.status, statusText: response2.statusText, headers: response2.headers }
|
|
2891
|
+
), json3 = result2.json.bind(result2);
|
|
2486
2892
|
return result2.json = async () => {
|
|
2487
|
-
let value = await
|
|
2893
|
+
let value = await json3();
|
|
2488
2894
|
return (!guard.current(revision) || request && !request.current()) && rejectStale(), value && typeof value.access_token == "string" && provenance.set(value.access_token, revision), value;
|
|
2489
2895
|
}, result2;
|
|
2490
2896
|
}, { preconnect: fetch.preconnect })
|
|
2491
2897
|
});
|
|
2492
|
-
async function authorization(kind,
|
|
2898
|
+
async function authorization(kind, id3, current2) {
|
|
2493
2899
|
let previous = authorizationQueue, release;
|
|
2494
2900
|
authorizationQueue = new Promise((resolve) => {
|
|
2495
2901
|
release = resolve;
|
|
@@ -2498,7 +2904,7 @@ async function provider(configuration, guard) {
|
|
|
2498
2904
|
authorizationRequest = request;
|
|
2499
2905
|
try {
|
|
2500
2906
|
if (!current2()) throw new BrowserAuthError("stale");
|
|
2501
|
-
let result2 = await (kind === "get" ? client.oauth.getAuthorizationDetails(
|
|
2907
|
+
let result2 = await (kind === "get" ? client.oauth.getAuthorizationDetails(id3) : kind === "approve" ? client.oauth.approveAuthorization(id3, { skipBrowserRedirect: !0 }) : client.oauth.denyAuthorization(id3, { skipBrowserRedirect: !0 }));
|
|
2502
2908
|
if (request.rejected || !current2()) throw new BrowserAuthError("stale");
|
|
2503
2909
|
return result2;
|
|
2504
2910
|
} catch (error) {
|
|
@@ -2509,9 +2915,9 @@ async function provider(configuration, guard) {
|
|
|
2509
2915
|
}
|
|
2510
2916
|
return {
|
|
2511
2917
|
authorization: {
|
|
2512
|
-
get: (
|
|
2513
|
-
approve: (
|
|
2514
|
-
deny: (
|
|
2918
|
+
get: (id3, current2) => authorization("get", id3, current2),
|
|
2919
|
+
approve: (id3, current2) => authorization("approve", id3, current2),
|
|
2920
|
+
deny: (id3, current2) => authorization("deny", id3, current2)
|
|
2515
2921
|
},
|
|
2516
2922
|
getSession: () => client.getSession(),
|
|
2517
2923
|
onAuthStateChange: (callback) => client.onAuthStateChange((event2, session) => {
|
|
@@ -2546,50 +2952,50 @@ var identifier = /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/, uuid = /^[0-9a-f]{8}-[0-
|
|
|
2546
2952
|
function fail3(reason) {
|
|
2547
2953
|
throw new AppRoutineError(reason);
|
|
2548
2954
|
}
|
|
2549
|
-
function
|
|
2955
|
+
function object4(value) {
|
|
2550
2956
|
return !!value && typeof value == "object" && !Array.isArray(value);
|
|
2551
2957
|
}
|
|
2552
|
-
function
|
|
2958
|
+
function keys4(value, expected) {
|
|
2553
2959
|
return Object.keys(value).sort().join(",") === expected;
|
|
2554
2960
|
}
|
|
2555
2961
|
function current(context2) {
|
|
2556
2962
|
(!context2.isCurrent() || context2.signal.aborted) && fail3("authority_unavailable");
|
|
2557
2963
|
}
|
|
2558
|
-
async function body(context2,
|
|
2964
|
+
async function body(context2, response2, maximum) {
|
|
2559
2965
|
try {
|
|
2560
|
-
let value = await appResponse(
|
|
2561
|
-
return current(context2),
|
|
2966
|
+
let value = await appResponse(response2, maximum, context2.signal);
|
|
2967
|
+
return current(context2), response2.ok || (object4(value) && keys4(value, "error") && isReason(value.error) && (value.error === "authority_unavailable" && context2.invalidate(), fail3(value.error)), fail3("authority_unavailable")), value;
|
|
2562
2968
|
} catch (error) {
|
|
2563
2969
|
if (current(context2), error instanceof AppResponseReadError || error instanceof AppRoutineError) throw error;
|
|
2564
2970
|
return fail3("execution_unavailable");
|
|
2565
2971
|
}
|
|
2566
2972
|
}
|
|
2567
2973
|
function descriptor(value, key) {
|
|
2568
|
-
return (!
|
|
2974
|
+
return (!object4(value) || !keys4(value, "after,key,routine,runId") || value.key !== key || typeof value.runId != "string" || !uuid.test(value.runId) || value.after !== 0 || typeof value.routine != "string" || !identifier.test(value.routine)) && fail3("execution_unavailable"), value;
|
|
2569
2975
|
}
|
|
2570
2976
|
function safeValue(value, depth = 0) {
|
|
2571
|
-
return depth > 32 ? !1 : value === null || typeof value == "string" || typeof value == "boolean" ? !0 : typeof value == "number" ? Number.isFinite(value) : Array.isArray(value) ? value.every((item) => safeValue(item, depth + 1)) :
|
|
2977
|
+
return depth > 32 ? !1 : value === null || typeof value == "string" || typeof value == "boolean" ? !0 : typeof value == "number" ? Number.isFinite(value) : Array.isArray(value) ? value.every((item) => safeValue(item, depth + 1)) : object4(value) && Object.entries(value).every(([key, item]) => !["__proto__", "constructor", "prototype"].includes(key) && safeValue(item, depth + 1));
|
|
2572
2978
|
}
|
|
2573
2979
|
function event(value, run, steps) {
|
|
2574
|
-
(!
|
|
2980
|
+
(!object4(value) || value.runId !== run.runId || value.key !== run.key || value.routine !== run.routine || !Number.isSafeInteger(value.sequence) || value.sequence < 1 || new TextEncoder().encode(JSON.stringify(value)).byteLength > 16 * 1024) && fail3("execution_unavailable");
|
|
2575
2981
|
let common = "key,routine,runId,sequence,";
|
|
2576
|
-
if (value.type === "started" &&
|
|
2577
|
-
if (value.type === "step" && typeof value.id == "string" && identifier.test(value.id) && (!steps || steps.includes(value.id)) &&
|
|
2982
|
+
if (value.type === "started" && keys4(value, common + "type") && value.sequence === 1) return { type: "started" };
|
|
2983
|
+
if (value.type === "step" && typeof value.id == "string" && identifier.test(value.id) && (!steps || steps.includes(value.id)) && keys4(value, "id," + common + (Object.hasOwn(value, "summary") ? "summary,type" : "type")) && (!Object.hasOwn(value, "summary") || safeValue(value.summary)))
|
|
2578
2984
|
return {
|
|
2579
2985
|
type: "step",
|
|
2580
2986
|
id: value.id,
|
|
2581
2987
|
...Object.hasOwn(value, "summary") ? { summary: value.summary } : {}
|
|
2582
2988
|
};
|
|
2583
2989
|
if (value.type === "finished") {
|
|
2584
|
-
if (value.state === "succeeded" &&
|
|
2990
|
+
if (value.state === "succeeded" && keys4(value, "key," + (Object.hasOwn(value, "result") ? "result," : "") + "routine,runId,sequence,state,type") && (!Object.hasOwn(value, "result") || safeValue(value.result)))
|
|
2585
2991
|
return {
|
|
2586
2992
|
type: "finished",
|
|
2587
2993
|
state: "succeeded",
|
|
2588
2994
|
...Object.hasOwn(value, "result") ? { result: value.result } : {}
|
|
2589
2995
|
};
|
|
2590
|
-
if (value.state === "failed" && value.error === "execution_failed" &&
|
|
2996
|
+
if (value.state === "failed" && value.error === "execution_failed" && keys4(value, "error," + common + "state,type"))
|
|
2591
2997
|
return { type: "finished", state: "failed", error: "execution_failed" };
|
|
2592
|
-
if (value.state === "cancelled" &&
|
|
2998
|
+
if (value.state === "cancelled" && keys4(value, common + "state,type")) return { type: "finished", state: "cancelled" };
|
|
2593
2999
|
}
|
|
2594
3000
|
return fail3("execution_unavailable");
|
|
2595
3001
|
}
|
|
@@ -2610,26 +3016,26 @@ function handle(context2, run, steps) {
|
|
|
2610
3016
|
let cursor = 0, terminal = !1, delay = 100, retainedBytes = 0, seen = [];
|
|
2611
3017
|
for (; !terminal; ) {
|
|
2612
3018
|
current(context2);
|
|
2613
|
-
let
|
|
3019
|
+
let response2;
|
|
2614
3020
|
try {
|
|
2615
|
-
|
|
3021
|
+
response2 = await context2.requestRoutine(run.key, `runs/${run.runId}/events?after=${cursor}`);
|
|
2616
3022
|
} catch {
|
|
2617
3023
|
current(context2), await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
2618
3024
|
continue;
|
|
2619
3025
|
}
|
|
2620
|
-
if (
|
|
2621
|
-
await
|
|
3026
|
+
if (response2.status >= 500) {
|
|
3027
|
+
await response2.body?.cancel(), await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
2622
3028
|
continue;
|
|
2623
3029
|
}
|
|
2624
3030
|
let value;
|
|
2625
3031
|
try {
|
|
2626
|
-
value = await body(context2,
|
|
3032
|
+
value = await body(context2, response2, 80 * 1024);
|
|
2627
3033
|
} catch (error) {
|
|
2628
3034
|
if (!(error instanceof AppResponseReadError)) throw error;
|
|
2629
3035
|
await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
2630
3036
|
continue;
|
|
2631
3037
|
}
|
|
2632
|
-
(!
|
|
3038
|
+
(!object4(value) || !keys4(value, "after,events,terminal") || !Array.isArray(value.events) || value.events.length > 256 || typeof value.terminal != "boolean" || !Number.isSafeInteger(value.after)) && fail3("execution_unavailable");
|
|
2633
3039
|
let delivery = [];
|
|
2634
3040
|
for (let raw of value.events) {
|
|
2635
3041
|
let publicEvent = event(raw, run, steps), encoded = JSON.stringify(raw), sequence = raw.sequence;
|
|
@@ -2649,7 +3055,7 @@ function handle(context2, run, steps) {
|
|
|
2649
3055
|
args.length && fail3("invalid_input");
|
|
2650
3056
|
try {
|
|
2651
3057
|
let value = await body(context2, await context2.requestRoutine(run.key, `runs/${run.runId}/cancel`, { method: "POST" }), 1024);
|
|
2652
|
-
(!
|
|
3058
|
+
(!object4(value) || !keys4(value, "cancelled") || value.cancelled !== !0) && fail3("execution_unavailable");
|
|
2653
3059
|
} catch (error) {
|
|
2654
3060
|
if (current(context2), error instanceof AppRoutineError) throw error;
|
|
2655
3061
|
fail3("execution_unavailable");
|
|
@@ -2664,12 +3070,12 @@ async function appRoutineOperation(key, input, recover) {
|
|
|
2664
3070
|
let resolved = await resolveAppContext();
|
|
2665
3071
|
if (resolved.kind !== "local" && fail3("execution_unavailable"), context2 = resolved, recover) {
|
|
2666
3072
|
let value2 = await body(context2, await context2.requestRoutine(key, "runs"), 16384);
|
|
2667
|
-
(!
|
|
3073
|
+
(!object4(value2) || !keys4(value2, "runs") || !Array.isArray(value2.runs) || value2.runs.length > 20) && fail3("execution_unavailable");
|
|
2668
3074
|
let runs = value2.runs.map((run) => descriptor(run, key));
|
|
2669
3075
|
return (new Set(runs.map((run) => run.runId)).size !== runs.length || new Set(runs.map((run) => run.routine)).size > 1) && fail3("execution_unavailable"), runs.map((run) => handle(resolved, run));
|
|
2670
3076
|
}
|
|
2671
3077
|
let available = await body(context2, await context2.requestAvailability(key), 16 * 1024);
|
|
2672
|
-
|
|
3078
|
+
object4(available) && keys4(available, "available,reason") && available.available === !1 && isReason(available.reason) && fail3(available.reason), (!object4(available) || !keys4(available, "available,steps") || available.available !== !0 || !Array.isArray(available.steps) || available.steps.length < 1 || available.steps.length > 64 || !available.steps.every((step) => typeof step == "string" && identifier.test(step)) || new Set(available.steps).size !== available.steps.length) && fail3("execution_unavailable");
|
|
2673
3079
|
let steps = [...available.steps], encoded;
|
|
2674
3080
|
try {
|
|
2675
3081
|
encoded = JSON.stringify(input), (encoded === void 0 || new TextEncoder().encode(encoded).byteLength > 16 * 1024) && fail3("invalid_input");
|
|
@@ -2693,10 +3099,10 @@ async function availability(key) {
|
|
|
2693
3099
|
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/.test(key)) return authorityUnavailable();
|
|
2694
3100
|
let context2 = await resolveAppContext();
|
|
2695
3101
|
if (context2.kind !== "local") return { available: !1, reason: "execution_unavailable" };
|
|
2696
|
-
let
|
|
2697
|
-
if (!
|
|
3102
|
+
let response2 = await context2.requestAvailability(key);
|
|
3103
|
+
if (!response2.ok || response2.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() !== "application/json")
|
|
2698
3104
|
return authorityUnavailable();
|
|
2699
|
-
let value = await appResponse(
|
|
3105
|
+
let value = await appResponse(response2, MAX_RESPONSE_BYTES, context2.signal);
|
|
2700
3106
|
if (!context2.isCurrent() || !value || typeof value != "object" || Array.isArray(value)) return authorityUnavailable();
|
|
2701
3107
|
let result2 = value;
|
|
2702
3108
|
return result2.available === !1 && Object.keys(result2).sort().join(",") === "available,reason" && (result2.reason === "authority_unavailable" || result2.reason === "execution_unavailable") ? { available: !1, reason: result2.reason } : result2.available !== !0 || Object.keys(result2).sort().join(",") !== "available,steps" || !Array.isArray(result2.steps) || result2.steps.length < 1 || result2.steps.length > 64 || !result2.steps.every((step) => typeof step == "string" && /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/.test(step)) || new Set(result2.steps).size !== result2.steps.length ? authorityUnavailable() : { available: !0, steps: [...result2.steps] };
|
|
@@ -2751,28 +3157,28 @@ function routinePublicationClient2(options = {}) {
|
|
|
2751
3157
|
} : async () => {
|
|
2752
3158
|
throw new Error("Member publication requires a host-supplied request");
|
|
2753
3159
|
});
|
|
2754
|
-
async function
|
|
3160
|
+
async function send3(operation2, body2) {
|
|
2755
3161
|
if (local) return await local(operation2, body2);
|
|
2756
|
-
let
|
|
3162
|
+
let response2 = await request(`/api/cli/workspaces/${workspace}/inbox/${operation2}`, {
|
|
2757
3163
|
method: "POST",
|
|
2758
3164
|
headers: { "content-type": "application/json", ...headers },
|
|
2759
3165
|
body: JSON.stringify(body2)
|
|
2760
|
-
}), result2 = await
|
|
2761
|
-
if (!
|
|
3166
|
+
}), result2 = await response2.json();
|
|
3167
|
+
if (!response2.ok && operation2 === "records/update")
|
|
2762
3168
|
throw new RoutineRecordWriteError(result2.error ?? "Could not confirm routine preparation", result2.effect ?? "uncertain");
|
|
2763
|
-
if (!
|
|
3169
|
+
if (!response2.ok) throw new Error(result2.error ?? "Could not confirm routine publication");
|
|
2764
3170
|
return result2;
|
|
2765
3171
|
}
|
|
2766
3172
|
let transport = {
|
|
2767
3173
|
async publish(body2) {
|
|
2768
|
-
return await
|
|
3174
|
+
return await send3("publish", body2);
|
|
2769
3175
|
},
|
|
2770
3176
|
async resolve(body2) {
|
|
2771
|
-
await
|
|
3177
|
+
await send3("resolve", body2);
|
|
2772
3178
|
}
|
|
2773
3179
|
};
|
|
2774
3180
|
async function readRecords(input) {
|
|
2775
|
-
return await
|
|
3181
|
+
return await send3("records/read", validateRecordRead(input));
|
|
2776
3182
|
}
|
|
2777
3183
|
return {
|
|
2778
3184
|
...createInboxPublisher(transport),
|
|
@@ -2781,15 +3187,15 @@ function routinePublicationClient2(options = {}) {
|
|
|
2781
3187
|
readRecords,
|
|
2782
3188
|
async writeRecords(input, options2) {
|
|
2783
3189
|
if (!capability) throw new Error("A trusted routine launch is required");
|
|
2784
|
-
return await
|
|
3190
|
+
return await send3("records/update", validateRoutineRecordWrite({ input, requestKey: options2?.requestKey }));
|
|
2785
3191
|
},
|
|
2786
3192
|
async updateRecords(input, options2) {
|
|
2787
3193
|
if (!capability) throw new Error("A trusted routine launch is required");
|
|
2788
|
-
return await
|
|
3194
|
+
return await send3("records/update", validateRoutineRecordWrite({ input: validateRecordUpdate(input), requestKey: options2?.requestKey }));
|
|
2789
3195
|
},
|
|
2790
3196
|
async deleteRecords(input, options2) {
|
|
2791
3197
|
if (!capability) throw new Error("A trusted routine launch is required");
|
|
2792
|
-
return await
|
|
3198
|
+
return await send3("records/update", validateRoutineRecordWrite({ input: validateRecordDelete(input), requestKey: options2?.requestKey }));
|
|
2793
3199
|
}
|
|
2794
3200
|
},
|
|
2795
3201
|
files: {
|
|
@@ -2800,7 +3206,7 @@ function routinePublicationClient2(options = {}) {
|
|
|
2800
3206
|
}
|
|
2801
3207
|
},
|
|
2802
3208
|
async check(body2) {
|
|
2803
|
-
await
|
|
3209
|
+
await send3("check", { requestKey: body2.requestKey, item: validatePublication(body2.item) });
|
|
2804
3210
|
}
|
|
2805
3211
|
};
|
|
2806
3212
|
}
|
|
@@ -2811,6 +3217,7 @@ export {
|
|
|
2811
3217
|
DataOperationError,
|
|
2812
3218
|
FileOperationError,
|
|
2813
3219
|
InboxContractError,
|
|
3220
|
+
InboxOperationError,
|
|
2814
3221
|
RoutineRecordWriteError,
|
|
2815
3222
|
app,
|
|
2816
3223
|
appRun,
|
|
@@ -2824,6 +3231,7 @@ export {
|
|
|
2824
3231
|
file,
|
|
2825
3232
|
fileBlock,
|
|
2826
3233
|
files,
|
|
3234
|
+
inbox,
|
|
2827
3235
|
os,
|
|
2828
3236
|
question,
|
|
2829
3237
|
recordBlock,
|