@oddington/sdk 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/browser.js +630 -207
- package/dist/index.js +16 -16
- package/dist/types/packages/sdk/src/public.d.ts +5 -1
- package/dist/types/packages/sdk/src/routine-definition-types.d.ts +17 -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,17 @@ 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
|
-
|
|
672
|
+
async artifact(input2) {
|
|
673
|
+
if (!active2) throw new Error("Run authority ended");
|
|
674
|
+
if (!runtime.artifact) throw new Error("Run artifact transport unavailable");
|
|
675
|
+
return runtime.artifact(input2);
|
|
676
|
+
},
|
|
677
|
+
step(id3, ...summary) {
|
|
673
678
|
if (!active2 || broken || summary.length > 1)
|
|
674
679
|
return broken = !0, Promise.reject(new AppRoutineContractError("invalid_value"));
|
|
675
680
|
let value;
|
|
676
681
|
try {
|
|
677
|
-
let step = contract.steps.find((step2) => step2.id ===
|
|
682
|
+
let step = contract.steps.find((step2) => step2.id === id3);
|
|
678
683
|
if (!step) return invalid();
|
|
679
684
|
if (step.summary === void 0) {
|
|
680
685
|
if (summary.length) return invalid();
|
|
@@ -682,7 +687,7 @@ async function executeRoutineDefinition(definition, input, runtime) {
|
|
|
682
687
|
} catch (error) {
|
|
683
688
|
return broken = !0, Promise.reject(error);
|
|
684
689
|
}
|
|
685
|
-
let report = reports.then(() => broken ? invalid() : runtime.step(
|
|
690
|
+
let report = reports.then(() => broken ? invalid() : runtime.step(id3, value));
|
|
686
691
|
return reports = report.catch(() => {
|
|
687
692
|
broken = !0;
|
|
688
693
|
}), report;
|
|
@@ -821,8 +826,8 @@ function captureDataDelete(record3) {
|
|
|
821
826
|
return !validRecordRef(identity.$ref) || typeof identity.$version != "string" || !identity.$version.length || identity.$version.length > 512 ? invalidChange() : { ref: identity.$ref, expectedVersion: identity.$version };
|
|
822
827
|
}
|
|
823
828
|
function captureDataUpdate(record3, set) {
|
|
824
|
-
let identity = captureDataDelete(record3),
|
|
825
|
-
return !Object.keys(
|
|
829
|
+
let identity = captureDataDelete(record3), fields5 = mapping(set);
|
|
830
|
+
return !Object.keys(fields5).length || Object.keys(fields5).some((key) => key.startsWith("$") || ["id", "type"].includes(key)) ? invalidChange() : { ...identity, set: captureValue(fields5) };
|
|
826
831
|
}
|
|
827
832
|
function captureIdentities(value, update, allowEmpty = !0) {
|
|
828
833
|
if (!Array.isArray(value) || !allowEmpty && !value.length || value.length > 1e4) return invalidChange();
|
|
@@ -841,14 +846,14 @@ function captureDataCreate(value) {
|
|
|
841
846
|
let row = mapping(value);
|
|
842
847
|
if (!validRecordRef(row.$ref) || Object.keys(row).some((key) => key.startsWith("$") && !["$ref", "$filing"].includes(key)))
|
|
843
848
|
return invalidChange();
|
|
844
|
-
let { $ref: ref, $filing, ...
|
|
849
|
+
let { $ref: ref, $filing, ...fields5 } = row, filing;
|
|
845
850
|
if ($filing !== void 0) {
|
|
846
851
|
let components = mapping($filing);
|
|
847
852
|
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
853
|
return invalidChange();
|
|
849
854
|
filing = { ...components };
|
|
850
855
|
}
|
|
851
|
-
return { ref, fields: captureValue(
|
|
856
|
+
return { ref, fields: captureValue(fields5), ...filing ? { filing } : {} };
|
|
852
857
|
}
|
|
853
858
|
function captureDataChanges(updatesValue, createsValue = [], deletesValue = []) {
|
|
854
859
|
let updates = captureDataUpdates(updatesValue, !0);
|
|
@@ -856,8 +861,8 @@ function captureDataChanges(updatesValue, createsValue = [], deletesValue = [])
|
|
|
856
861
|
let creates = createsValue.map((item) => {
|
|
857
862
|
let row = mapping(item);
|
|
858
863
|
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(
|
|
864
|
+
let fields5 = mapping(row.fields);
|
|
865
|
+
return Object.keys(fields5).some((key) => key.startsWith("$")) ? invalidChange() : captureDataCreate({ ...fields5, $ref: row.ref, ...Object.hasOwn(row, "filing") ? { $filing: row.filing } : {} });
|
|
861
866
|
}), deletes = captureIdentities(deletesValue, !1), refs = [...updates, ...creates, ...deletes].map((item) => item.ref);
|
|
862
867
|
return !refs.length || refs.length > 1e4 || new Set(refs).size !== refs.length ? invalidChange() : { updates, creates, deletes };
|
|
863
868
|
}
|
|
@@ -883,12 +888,10 @@ function dataTransportError(status, value) {
|
|
|
883
888
|
);
|
|
884
889
|
}
|
|
885
890
|
|
|
886
|
-
var
|
|
887
|
-
function
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
throw new Error("ODDINGTON_OS_ORIGIN must use HTTPS");
|
|
891
|
-
return url.origin;
|
|
891
|
+
var installed, ended = !1;
|
|
892
|
+
function routineTransport() {
|
|
893
|
+
if (ended || installed && !installed.isCurrent()) throw new Error("Routine authority ended");
|
|
894
|
+
return installed;
|
|
892
895
|
}
|
|
893
896
|
|
|
894
897
|
var memberContext;
|
|
@@ -953,20 +956,19 @@ function checked(workspace, endpoint, headers) {
|
|
|
953
956
|
|
|
954
957
|
var data = {
|
|
955
958
|
repository(repository) {
|
|
956
|
-
async function
|
|
957
|
-
let context2 = await resolveDataContext();
|
|
959
|
+
async function send3(input) {
|
|
960
|
+
let context2 = await resolveDataContext(), envelope = { repository, ...input };
|
|
961
|
+
if (checkDataRequestSize(envelope), "local" in context2) return await context2.local("data/query", envelope);
|
|
958
962
|
try {
|
|
959
|
-
let
|
|
960
|
-
if (checkDataRequestSize(envelope), "local" in context2) return await context2.local("data/query", envelope);
|
|
961
|
-
let response = await fetch(context2.url, {
|
|
963
|
+
let response2 = await fetch(context2.url, {
|
|
962
964
|
method: "POST",
|
|
963
965
|
redirect: "error",
|
|
964
966
|
cache: "no-store",
|
|
965
967
|
headers: { "content-type": "application/json", ...context2.headers },
|
|
966
968
|
body: JSON.stringify(envelope)
|
|
967
|
-
}), result2 = await
|
|
968
|
-
if (!
|
|
969
|
-
throw dataTransportError(
|
|
969
|
+
}), result2 = await response2.json();
|
|
970
|
+
if (!response2.ok)
|
|
971
|
+
throw dataTransportError(response2.status, result2);
|
|
970
972
|
return result2;
|
|
971
973
|
} catch (error) {
|
|
972
974
|
throw error instanceof DataOperationError ? error : new DataOperationError("unavailable", !0);
|
|
@@ -974,17 +976,17 @@ var data = {
|
|
|
974
976
|
}
|
|
975
977
|
return {
|
|
976
978
|
collections: {
|
|
977
|
-
list: () =>
|
|
978
|
-
schema: (name) =>
|
|
979
|
+
list: () => send3({ operation: "collections.list" }),
|
|
980
|
+
schema: (name) => send3({ operation: "collections.schema", name })
|
|
979
981
|
},
|
|
980
982
|
records: {
|
|
981
|
-
select: (query) =>
|
|
982
|
-
search: async (query, options) =>
|
|
983
|
+
select: (query) => send3({ operation: "records.select", query }),
|
|
984
|
+
search: async (query, options) => send3({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
|
|
983
985
|
},
|
|
984
986
|
history: {
|
|
985
|
-
list: async (options) =>
|
|
986
|
-
at: async (instant) =>
|
|
987
|
-
changes: async (options) =>
|
|
987
|
+
list: async (options) => send3({ operation: "history.list", options: captureHistoryListOptions(options) }),
|
|
988
|
+
at: async (instant) => send3({ operation: "history.at", instant: captureHistoryInstant(instant) }),
|
|
989
|
+
changes: async (options) => send3({ operation: "history.changes", options: captureHistoryChangesOptions(options) })
|
|
988
990
|
},
|
|
989
991
|
changes() {
|
|
990
992
|
let updates = [], creates = [], deletes = [], publicationId, pending, confirmed, assertMutable = () => {
|
|
@@ -1015,7 +1017,7 @@ var data = {
|
|
|
1015
1017
|
snapshot(updates, creates, next), deletes = next;
|
|
1016
1018
|
},
|
|
1017
1019
|
async validate() {
|
|
1018
|
-
await
|
|
1020
|
+
await send3({ operation: "changes.validate", ...snapshot() });
|
|
1019
1021
|
},
|
|
1020
1022
|
publish() {
|
|
1021
1023
|
if (confirmed) return Promise.resolve(structuredClone(confirmed));
|
|
@@ -1026,7 +1028,7 @@ var data = {
|
|
|
1026
1028
|
} catch (error) {
|
|
1027
1029
|
return Promise.reject(error);
|
|
1028
1030
|
}
|
|
1029
|
-
publicationId ??= crypto.randomUUID(), pending =
|
|
1031
|
+
publicationId ??= routineTransport()?.key("data") ?? crypto.randomUUID(), pending = send3({ operation: "changes.publish", ...captured, publicationId }).then((result2) => (confirmed = structuredClone(result2), result2)).catch((error) => {
|
|
1030
1032
|
throw error instanceof DataOperationError ? new DataOperationError(
|
|
1031
1033
|
error.code,
|
|
1032
1034
|
error.retryable,
|
|
@@ -1083,9 +1085,9 @@ async function timed(work, parent, timeout = TIMEOUT_MS) {
|
|
|
1083
1085
|
clearTimeout(timer), parent?.removeEventListener("abort", abort);
|
|
1084
1086
|
}
|
|
1085
1087
|
}
|
|
1086
|
-
async function result(
|
|
1088
|
+
async function result(response2, maximum = RESULT_BYTES) {
|
|
1087
1089
|
try {
|
|
1088
|
-
let bytes = await boundedBytes(
|
|
1090
|
+
let bytes = await boundedBytes(response2.body, maximum);
|
|
1089
1091
|
return JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes));
|
|
1090
1092
|
} catch {
|
|
1091
1093
|
throw unavailable();
|
|
@@ -1096,13 +1098,13 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1096
1098
|
parent.addEventListener("abort", abort, { once: !0 }), parent.aborted && abort();
|
|
1097
1099
|
let detach = () => parent.removeEventListener("abort", abort);
|
|
1098
1100
|
try {
|
|
1099
|
-
let
|
|
1101
|
+
let response2 = await upstream(url, { ...init2, signal: delivery.signal });
|
|
1100
1102
|
if (delivery.signal.aborted)
|
|
1101
|
-
throw
|
|
1103
|
+
throw response2.body?.cancel().catch(() => {
|
|
1102
1104
|
}), unavailable();
|
|
1103
|
-
if (!
|
|
1104
|
-
return detach(),
|
|
1105
|
-
let source =
|
|
1105
|
+
if (!response2.body)
|
|
1106
|
+
return detach(), response2;
|
|
1107
|
+
let source = response2.body, reader, settled = !1, cancel = async (reason) => {
|
|
1106
1108
|
if (!settled) {
|
|
1107
1109
|
settled = !0, detach(), delivery.abort(reason);
|
|
1108
1110
|
try {
|
|
@@ -1127,9 +1129,9 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1127
1129
|
}
|
|
1128
1130
|
},
|
|
1129
1131
|
cancel
|
|
1130
|
-
}, { highWaterMark: 0 }), wrapped = new Response(body2, { status:
|
|
1132
|
+
}, { highWaterMark: 0 }), wrapped = new Response(body2, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
|
|
1131
1133
|
for (let key of ["url", "redirected", "type"])
|
|
1132
|
-
Object.defineProperty(wrapped, key, { value:
|
|
1134
|
+
Object.defineProperty(wrapped, key, { value: response2[key] });
|
|
1133
1135
|
return wrapped;
|
|
1134
1136
|
} catch (error) {
|
|
1135
1137
|
throw detach(), delivery.abort(error), error;
|
|
@@ -1145,7 +1147,7 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1145
1147
|
let context2 = await resolveFilesContext();
|
|
1146
1148
|
checkCurrent(context2);
|
|
1147
1149
|
try {
|
|
1148
|
-
let
|
|
1150
|
+
let response2 = await (async () => {
|
|
1149
1151
|
let url = `${context2.url}${suffix}`, request = {
|
|
1150
1152
|
...init2,
|
|
1151
1153
|
signal: parent,
|
|
@@ -1155,22 +1157,22 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1155
1157
|
};
|
|
1156
1158
|
return descriptor2 ? fetch(url, request) : hostedContent(url, request, parent);
|
|
1157
1159
|
})();
|
|
1158
|
-
if (!
|
|
1159
|
-
let value2 = await result(
|
|
1160
|
-
throw code ? new FileOperationError(code,
|
|
1160
|
+
if (!response2.ok) {
|
|
1161
|
+
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);
|
|
1162
|
+
throw code ? new FileOperationError(code, response2.status, code === "capacity" || code === "unavailable") : unavailable();
|
|
1161
1163
|
}
|
|
1162
|
-
if (
|
|
1163
|
-
throw
|
|
1164
|
+
if (response2.status !== (descriptor2 === 204 ? 204 : 200) || descriptor2 === 204 && response2.body !== null)
|
|
1165
|
+
throw response2.body?.cancel().catch(() => {
|
|
1164
1166
|
}), unavailable();
|
|
1165
1167
|
try {
|
|
1166
1168
|
checkCurrent();
|
|
1167
1169
|
} catch (error) {
|
|
1168
|
-
throw
|
|
1170
|
+
throw response2.body?.cancel().catch(() => {
|
|
1169
1171
|
}), error;
|
|
1170
1172
|
}
|
|
1171
1173
|
if (descriptor2 === 204) return;
|
|
1172
|
-
if (!descriptor2) return
|
|
1173
|
-
let value = await result(
|
|
1174
|
+
if (!descriptor2) return response2;
|
|
1175
|
+
let value = await result(response2, descriptor2 === "control" ? CONTROL_RESULT_BYTES : RESULT_BYTES);
|
|
1174
1176
|
if (descriptor2 === "control")
|
|
1175
1177
|
return checkCurrent(), value;
|
|
1176
1178
|
let parsed;
|
|
@@ -1188,9 +1190,9 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1188
1190
|
}
|
|
1189
1191
|
throw unavailable();
|
|
1190
1192
|
}
|
|
1191
|
-
function idPath(
|
|
1192
|
-
if (typeof
|
|
1193
|
-
return `/${
|
|
1193
|
+
function idPath(id3) {
|
|
1194
|
+
if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw invalid4();
|
|
1195
|
+
return `/${id3}`;
|
|
1194
1196
|
}
|
|
1195
1197
|
async function multipartCreate(input, metadata, exchange, release = () => {
|
|
1196
1198
|
active--;
|
|
@@ -1292,16 +1294,16 @@ async function operation(work, initial, parent) {
|
|
|
1292
1294
|
throw error instanceof FileOperationError ? error : unavailable();
|
|
1293
1295
|
});
|
|
1294
1296
|
}
|
|
1295
|
-
function contentPath(
|
|
1296
|
-
let path = idPath(
|
|
1297
|
+
function contentPath(id3, name) {
|
|
1298
|
+
let path = idPath(id3);
|
|
1297
1299
|
if (name === void 0) return `${path}/content`;
|
|
1298
1300
|
if (!safeEnrichmentName(name)) throw invalid4();
|
|
1299
1301
|
return `${path}/enrichments/${encodeURIComponent(name)}/content`;
|
|
1300
1302
|
}
|
|
1301
|
-
async function read(
|
|
1303
|
+
async function read(id3, names) {
|
|
1302
1304
|
let context2 = await resolveFilesContext();
|
|
1303
|
-
if (idPath(
|
|
1304
|
-
let path = contentPath(
|
|
1305
|
+
if (idPath(id3), names === void 0 || typeof names == "string") {
|
|
1306
|
+
let path = contentPath(id3, names);
|
|
1305
1307
|
return operation((context3, signal) => send(path, { method: "GET" }, !1, context3, signal), context2);
|
|
1306
1308
|
}
|
|
1307
1309
|
if (!Array.isArray(names)) throw invalid4();
|
|
@@ -1313,31 +1315,31 @@ async function read(id2, names) {
|
|
|
1313
1315
|
seen.add(name), distinct.push(name);
|
|
1314
1316
|
}
|
|
1315
1317
|
}
|
|
1316
|
-
let paths = distinct.map((name) => contentPath(
|
|
1318
|
+
let paths = distinct.map((name) => contentPath(id3, name));
|
|
1317
1319
|
return timed(async (parent) => {
|
|
1318
1320
|
let responses = {};
|
|
1319
1321
|
try {
|
|
1320
1322
|
for (let i = 0; i < paths.length; i++) {
|
|
1321
|
-
let
|
|
1322
|
-
Object.defineProperty(responses, distinct[i], { value:
|
|
1323
|
+
let response2 = await operation((context3, signal) => send(paths[i], { method: "GET" }, !1, context3, signal), context2, parent);
|
|
1324
|
+
Object.defineProperty(responses, distinct[i], { value: response2, enumerable: !0 });
|
|
1323
1325
|
}
|
|
1324
1326
|
if (!context2.isCurrent()) throw new FileOperationError("unsupported_context", 400);
|
|
1325
1327
|
return responses;
|
|
1326
1328
|
} catch (error) {
|
|
1327
|
-
for (let
|
|
1329
|
+
for (let response2 of Object.values(responses)) response2.body?.cancel().catch(() => {
|
|
1328
1330
|
});
|
|
1329
1331
|
throw error;
|
|
1330
1332
|
}
|
|
1331
1333
|
});
|
|
1332
1334
|
}
|
|
1333
1335
|
var files = {
|
|
1334
|
-
delete(
|
|
1335
|
-
return operation((context2, signal) => send(idPath(
|
|
1336
|
+
delete(id3) {
|
|
1337
|
+
return operation((context2, signal) => send(idPath(id3), { method: "DELETE" }, 204, context2, signal));
|
|
1336
1338
|
},
|
|
1337
|
-
async upload(
|
|
1339
|
+
async upload(id3) {
|
|
1338
1340
|
return operation(async (context2, signal) => {
|
|
1339
|
-
let file2 = await send(`${idPath(
|
|
1340
|
-
if (file2.id !==
|
|
1341
|
+
let file2 = await send(`${idPath(id3)}/upload`, { method: "POST" }, !0, context2, signal);
|
|
1342
|
+
if (file2.id !== id3) throw unavailable();
|
|
1341
1343
|
return file2;
|
|
1342
1344
|
});
|
|
1343
1345
|
},
|
|
@@ -1345,9 +1347,9 @@ var files = {
|
|
|
1345
1347
|
let context2 = await resolveFilesContext();
|
|
1346
1348
|
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
1349
|
throw invalid4();
|
|
1348
|
-
let blob = input.file instanceof Blob,
|
|
1349
|
-
if (!blob && !
|
|
1350
|
-
let intrinsic = blob ? input.file.size :
|
|
1350
|
+
let blob = input.file instanceof Blob, array3 = input.file instanceof Uint8Array, stream = input.file instanceof ReadableStream;
|
|
1351
|
+
if (!blob && !array3 && !stream) throw invalid4();
|
|
1352
|
+
let intrinsic = blob ? input.file.size : array3 ? input.file.byteLength : void 0;
|
|
1351
1353
|
if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw invalid4();
|
|
1352
1354
|
let name = input.name;
|
|
1353
1355
|
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));
|
|
@@ -1358,7 +1360,7 @@ var files = {
|
|
|
1358
1360
|
storage: input.storage,
|
|
1359
1361
|
csv: input.csv,
|
|
1360
1362
|
...blob && input.file.type === "application/pdf" ? { inputMediaType: "application/pdf" } : {},
|
|
1361
|
-
requestKey: options?.requestKey === void 0 ? crypto.randomUUID() : options.requestKey
|
|
1363
|
+
requestKey: options?.requestKey === void 0 ? routineTransport()?.key("files") ?? crypto.randomUUID() : options.requestKey
|
|
1362
1364
|
}, FILE_ORIGINAL_MAX_BYTES);
|
|
1363
1365
|
if (!context2.local && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
|
|
1364
1366
|
let header = encodeURIComponent(JSON.stringify(metadata));
|
|
@@ -1366,7 +1368,7 @@ var files = {
|
|
|
1366
1368
|
if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
|
|
1367
1369
|
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
1370
|
try {
|
|
1369
|
-
let bytes =
|
|
1371
|
+
let bytes = array3 ? input.file.slice() : await boundedBytes(
|
|
1370
1372
|
blob ? input.file.stream() : input.file,
|
|
1371
1373
|
metadata.size
|
|
1372
1374
|
);
|
|
@@ -1412,8 +1414,8 @@ var files = {
|
|
|
1412
1414
|
return result2;
|
|
1413
1415
|
}, context2);
|
|
1414
1416
|
},
|
|
1415
|
-
async get(
|
|
1416
|
-
return operation((context2, signal) => send(idPath(
|
|
1417
|
+
async get(id3) {
|
|
1418
|
+
return operation((context2, signal) => send(idPath(id3), { method: "GET" }, !0, context2, signal));
|
|
1417
1419
|
},
|
|
1418
1420
|
read
|
|
1419
1421
|
};
|
|
@@ -1515,12 +1517,12 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1515
1517
|
baseId,
|
|
1516
1518
|
table: input.table,
|
|
1517
1519
|
operation: operation2.slice(8),
|
|
1518
|
-
records: ids2.map((
|
|
1520
|
+
records: ids2.map((id3) => ({ id: id3 }))
|
|
1519
1521
|
});
|
|
1520
1522
|
async function request(path2, init2 = {}, write = !1) {
|
|
1521
|
-
let
|
|
1523
|
+
let response2;
|
|
1522
1524
|
try {
|
|
1523
|
-
|
|
1525
|
+
response2 = await (options.fetch ?? fetch)(`https://api.airtable.com/v0/${path2}`, {
|
|
1524
1526
|
...init2,
|
|
1525
1527
|
headers: { authorization: `Bearer ${accessToken}`, "content-type": "application/json" },
|
|
1526
1528
|
redirect: "manual",
|
|
@@ -1529,12 +1531,12 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1529
1531
|
} catch {
|
|
1530
1532
|
throw new AirtableOperationError("Airtable request acknowledgment unavailable", write ? "uncertain" : "unapplied");
|
|
1531
1533
|
}
|
|
1532
|
-
if (!
|
|
1533
|
-
throw await
|
|
1534
|
-
}), new AirtableOperationError("Airtable request rejected", write && (
|
|
1534
|
+
if (!response2.ok)
|
|
1535
|
+
throw await response2.body?.cancel().catch(() => {
|
|
1536
|
+
}), new AirtableOperationError("Airtable request rejected", write && (response2.status >= 500 || response2.status === 408 || response2.status < 400) ? "uncertain" : "unapplied");
|
|
1535
1537
|
try {
|
|
1536
|
-
if (!
|
|
1537
|
-
let value = object2(await
|
|
1538
|
+
if (!response2.headers.get("content-type")?.toLowerCase().includes("application/json")) throw new Error();
|
|
1539
|
+
let value = object2(await response2.json()), safe = serializable(value);
|
|
1538
1540
|
if (Object.hasOwn(value, "error") || JSON.stringify(safe).includes(accessToken)) throw new Error();
|
|
1539
1541
|
return value;
|
|
1540
1542
|
} catch {
|
|
@@ -1601,7 +1603,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1601
1603
|
}
|
|
1602
1604
|
await options.beforeMutation?.();
|
|
1603
1605
|
let query = new URLSearchParams();
|
|
1604
|
-
if (kind === "delete") for (let
|
|
1606
|
+
if (kind === "delete") for (let id3 of ids) query.append("records[]", id3);
|
|
1605
1607
|
let result2 = await request(`${path}${kind === "delete" ? `?${query}` : ""}`, {
|
|
1606
1608
|
method: kind === "create" ? "POST" : kind === "update" ? "PATCH" : "DELETE",
|
|
1607
1609
|
...kind === "delete" ? {} : { body: JSON.stringify({ records: records.map((r) => "id" in r ? { id: r.id, fields: r.set } : r) }) }
|
|
@@ -1640,14 +1642,14 @@ function managedConnections(capability) {
|
|
|
1640
1642
|
safeInput = null;
|
|
1641
1643
|
}
|
|
1642
1644
|
try {
|
|
1643
|
-
let
|
|
1645
|
+
let response2 = await fetch(new URL("airtable", endpoint), {
|
|
1644
1646
|
method: "POST",
|
|
1645
1647
|
redirect: "error",
|
|
1646
1648
|
headers: { authorization: `Bearer ${capability.token}`, "content-type": "application/json" },
|
|
1647
1649
|
body: JSON.stringify({ name, operation: operation2, input: safeInput }),
|
|
1648
1650
|
signal: AbortSignal.timeout(125e3)
|
|
1649
|
-
}), value = await
|
|
1650
|
-
if (!
|
|
1651
|
+
}), value = await response2.json();
|
|
1652
|
+
if (!response2.ok) throw new AirtableOperationError(
|
|
1651
1653
|
"Airtable operation failed; the execution retains its evidence",
|
|
1652
1654
|
value.effect === "partial" || value.effect === "uncertain" ? value.effect : "unapplied",
|
|
1653
1655
|
value.receipts ?? []
|
|
@@ -1669,6 +1671,8 @@ async function reportLocalRoutineEffect(value) {
|
|
|
1669
1671
|
|
|
1670
1672
|
var connections = /* @__PURE__ */ createConnections(async (name, operation2, input) => {
|
|
1671
1673
|
try {
|
|
1674
|
+
let installed2 = routineTransport();
|
|
1675
|
+
if (installed2) return await installed2.request("airtable", { name, operation: operation2, input: serializable(input) });
|
|
1672
1676
|
let managed = process.env[MANAGED_CONNECTION_CAPABILITY_ENV];
|
|
1673
1677
|
if (managed) {
|
|
1674
1678
|
let client = managedConnections(JSON.parse(managed)).airtable(name);
|
|
@@ -1770,6 +1774,411 @@ function validCreatePath(value) {
|
|
|
1770
1774
|
return value === value.trim() && value.endsWith(".md") && !value.startsWith("/") && value.split("/").every((segment) => !!segment && ![".", ".."].includes(segment) && /^[a-zA-Z0-9_.-]+$/.test(segment));
|
|
1771
1775
|
}
|
|
1772
1776
|
|
|
1777
|
+
var InboxOperationError = class extends Error {
|
|
1778
|
+
constructor(status, reason) {
|
|
1779
|
+
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");
|
|
1780
|
+
this.status = status;
|
|
1781
|
+
this.reason = reason;
|
|
1782
|
+
}
|
|
1783
|
+
status;
|
|
1784
|
+
reason;
|
|
1785
|
+
}, 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 = {
|
|
1786
|
+
current: [],
|
|
1787
|
+
"items.list": [],
|
|
1788
|
+
"items.read": ["itemId"],
|
|
1789
|
+
"items.see": ["itemId"],
|
|
1790
|
+
"items.markDigestRead": ["itemId"],
|
|
1791
|
+
"items.rename": ["itemId", "revision", "title"],
|
|
1792
|
+
"items.setLifecycle": ["itemId", "revision", "lifecycle"],
|
|
1793
|
+
"items.listRecipientCandidates": ["itemId"],
|
|
1794
|
+
"items.addRecipient": ["itemId", "personId"],
|
|
1795
|
+
"questions.answer": ["itemId", "revision", "questionId", "response"],
|
|
1796
|
+
"questions.searchRecords": ["itemId", "revision", "questionId", "query"],
|
|
1797
|
+
"files.read": ["itemId", "fileId"]
|
|
1798
|
+
};
|
|
1799
|
+
function assert(value) {
|
|
1800
|
+
if (!value) throw new Error("Invalid Inbox result");
|
|
1801
|
+
}
|
|
1802
|
+
function object3(value) {
|
|
1803
|
+
return assert(value && typeof value == "object" && !Array.isArray(value) && [Object.prototype, null].includes(Object.getPrototypeOf(value)) && Reflect.ownKeys(value).every((key) => {
|
|
1804
|
+
let descriptor2 = typeof key == "string" ? Object.getOwnPropertyDescriptor(value, key) : void 0;
|
|
1805
|
+
return !!descriptor2?.enumerable && "value" in descriptor2;
|
|
1806
|
+
})), value;
|
|
1807
|
+
}
|
|
1808
|
+
function keys3(value, allowed, required = allowed) {
|
|
1809
|
+
assert(Object.keys(value).every((key) => allowed.includes(key)) && required.every((key) => Object.hasOwn(value, key)));
|
|
1810
|
+
}
|
|
1811
|
+
function text3(value, empty2 = !1) {
|
|
1812
|
+
return typeof value == "string" && (empty2 || !!value.trim());
|
|
1813
|
+
}
|
|
1814
|
+
function id2(value) {
|
|
1815
|
+
return typeof value == "string" && INBOX_UUID.test(value);
|
|
1816
|
+
}
|
|
1817
|
+
function integer(value, minimum = 1) {
|
|
1818
|
+
return Number.isSafeInteger(value) && Number(value) >= minimum;
|
|
1819
|
+
}
|
|
1820
|
+
function date(value) {
|
|
1821
|
+
return text3(value) && Number.isFinite(Date.parse(value));
|
|
1822
|
+
}
|
|
1823
|
+
function optionalDate(value) {
|
|
1824
|
+
return value === null || date(value);
|
|
1825
|
+
}
|
|
1826
|
+
function array2(value) {
|
|
1827
|
+
return assert(Array.isArray(value) && Object.getPrototypeOf(value) === Array.prototype && Reflect.ownKeys(value).length === value.length + 1 && value.every((_entry, index) => {
|
|
1828
|
+
let descriptor2 = Object.getOwnPropertyDescriptor(value, String(index));
|
|
1829
|
+
return !!descriptor2?.enumerable && "value" in descriptor2;
|
|
1830
|
+
})), value;
|
|
1831
|
+
}
|
|
1832
|
+
function json2(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
1833
|
+
if (value === null || typeof value == "boolean" || typeof value == "string" || typeof value == "number" && Number.isFinite(value)) return value;
|
|
1834
|
+
assert(value && typeof value == "object" && !ancestors.has(value)), ancestors.add(value);
|
|
1835
|
+
try {
|
|
1836
|
+
return Array.isArray(value) ? array2(value).map((entry) => json2(entry, ancestors)) : Object.fromEntries(Object.entries(object3(value)).map(([key, entry]) => [key, json2(entry, ancestors)]));
|
|
1837
|
+
} finally {
|
|
1838
|
+
ancestors.delete(value);
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
function recordReference(value) {
|
|
1842
|
+
let record3 = object3(value);
|
|
1843
|
+
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;
|
|
1844
|
+
}
|
|
1845
|
+
function responseDefinition(value) {
|
|
1846
|
+
let definition = object3(value);
|
|
1847
|
+
keys3(definition, ["type", "source"]), assert(definition.type === "selection");
|
|
1848
|
+
let source = object3(definition.source);
|
|
1849
|
+
if (source.type === "authored") {
|
|
1850
|
+
keys3(source, ["type", "options", "suggestions", "search"], ["type", "options"]);
|
|
1851
|
+
let options = array2(source.options);
|
|
1852
|
+
assert(options.length > 0);
|
|
1853
|
+
let values = options.map((value2) => {
|
|
1854
|
+
let option = object3(value2);
|
|
1855
|
+
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) {
|
|
1856
|
+
let note = object3(option.note);
|
|
1857
|
+
keys3(note, ["placeholder"]), assert(text3(note.placeholder));
|
|
1858
|
+
}
|
|
1859
|
+
return option.value;
|
|
1860
|
+
});
|
|
1861
|
+
if (assert(new Set(values).size === values.length), "search" in source || "suggestions" in source) {
|
|
1862
|
+
let search = object3(source.search);
|
|
1863
|
+
keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text3(search.triggerLabel) && text3(search.placeholder) && text3(search.emptyLabel));
|
|
1864
|
+
let suggestions2 = array2(source.suggestions);
|
|
1865
|
+
assert(suggestions2.length <= 8 && suggestions2.every((value2) => text3(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
|
|
1866
|
+
} else assert(options.length <= 9);
|
|
1867
|
+
return;
|
|
1868
|
+
}
|
|
1869
|
+
assert(source.type === "records"), keys3(source, ["type", "collection", "refPrefix", "where", "display", "suggestions"], ["type", "collection", "display"]);
|
|
1870
|
+
let collection = object3(source.collection);
|
|
1871
|
+
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));
|
|
1872
|
+
let where = object3(source.where ?? {});
|
|
1873
|
+
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))));
|
|
1874
|
+
let display = object3(source.display);
|
|
1875
|
+
keys3(display, ["labelFields"]);
|
|
1876
|
+
let labels = array2(display.labelFields);
|
|
1877
|
+
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)));
|
|
1878
|
+
let suggestions = array2(source.suggestions ?? []), refs = suggestions.map((value2) => {
|
|
1879
|
+
let suggestion = object3(value2);
|
|
1880
|
+
keys3(suggestion, ["record", "reason"], ["record"]);
|
|
1881
|
+
let record3 = recordReference(suggestion.record);
|
|
1882
|
+
return assert(record3.repository === collection.repository), "reason" in suggestion && assert(text3(suggestion.reason)), record3.ref;
|
|
1883
|
+
});
|
|
1884
|
+
assert(suggestions.length <= 8 && new Set(refs).size === refs.length);
|
|
1885
|
+
}
|
|
1886
|
+
function inboxFile(value) {
|
|
1887
|
+
let file2 = object3(value);
|
|
1888
|
+
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));
|
|
1889
|
+
let details = object3(file2.details);
|
|
1890
|
+
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)));
|
|
1891
|
+
}
|
|
1892
|
+
function fields4(value) {
|
|
1893
|
+
let labels = array2(value).map((value2) => {
|
|
1894
|
+
let field = object3(value2);
|
|
1895
|
+
return keys3(field, ["label", "value"]), assert(text3(field.label) && text3(field.value)), field.label;
|
|
1896
|
+
});
|
|
1897
|
+
assert(new Set(labels).size === labels.length);
|
|
1898
|
+
}
|
|
1899
|
+
function block(value) {
|
|
1900
|
+
let entry = object3(value);
|
|
1901
|
+
if (entry.kind === "rich-text") {
|
|
1902
|
+
keys3(entry, ["kind", "markdown"]), assert(text3(entry.markdown));
|
|
1903
|
+
return;
|
|
1904
|
+
}
|
|
1905
|
+
if (entry.kind === "asks") {
|
|
1906
|
+
keys3(entry, ["kind", "problem", "asks"]);
|
|
1907
|
+
let asks = array2(entry.asks);
|
|
1908
|
+
assert(text3(entry.problem) && asks.length > 0 && asks.every(id2) && new Set(asks).size === asks.length);
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
if (assert(["record", "records", "files"].includes(String(entry.kind))), keys3(
|
|
1912
|
+
entry,
|
|
1913
|
+
["kind", "label", "initiallyExpanded", ...entry.kind === "record" ? ["record", "view"] : entry.kind === "records" ? ["records", "view"] : ["files"]],
|
|
1914
|
+
["kind", "label", entry.kind === "record" ? "record" : entry.kind === "records" ? "records" : "files"]
|
|
1915
|
+
), 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") {
|
|
1916
|
+
let record3 = object3(entry.record);
|
|
1917
|
+
keys3(record3, ["ref", "title", "fields"]), assert(text3(record3.ref) && record3.ref === record3.ref.trim() && text3(record3.title)), fields4(record3.fields);
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
if (entry.kind === "records") {
|
|
1921
|
+
let records = array2(entry.records), refs = records.map((value2) => {
|
|
1922
|
+
let record3 = object3(value2);
|
|
1923
|
+
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;
|
|
1924
|
+
});
|
|
1925
|
+
assert(records.length > 0 && new Set(refs).size === refs.length);
|
|
1926
|
+
return;
|
|
1927
|
+
}
|
|
1928
|
+
let files3 = array2(entry.files);
|
|
1929
|
+
files3.forEach(inboxFile), assert(files3.length > 0 && new Set(files3.map((value2) => object3(value2).id)).size === files3.length);
|
|
1930
|
+
}
|
|
1931
|
+
function response(value) {
|
|
1932
|
+
let answer = object3(value);
|
|
1933
|
+
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;
|
|
1934
|
+
}
|
|
1935
|
+
function parseInboxRequest(value) {
|
|
1936
|
+
try {
|
|
1937
|
+
let envelope = object3(value);
|
|
1938
|
+
assert(Object.keys(envelope).sort().join(",") === "input,operation"), assert(typeof envelope.operation == "string" && Object.hasOwn(operations, envelope.operation));
|
|
1939
|
+
let operation2 = envelope.operation, input = object3(envelope.input), required = operations[operation2];
|
|
1940
|
+
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"));
|
|
1941
|
+
for (let key of ["itemId", "personId", "fileId"]) key in input && assert(id2(input[key]));
|
|
1942
|
+
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 };
|
|
1943
|
+
} catch {
|
|
1944
|
+
throw new InboxOperationError(400, "invalid_input");
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
function parseInboxCurrent(value) {
|
|
1948
|
+
let current2 = object3(value), workspace = object3(current2.workspace), viewer = object3(current2.viewer);
|
|
1949
|
+
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)), {
|
|
1950
|
+
workspace: { id: workspace.id, slug: workspace.slug, name: workspace.name, locale: workspace.locale, timezone: workspace.timezone },
|
|
1951
|
+
viewer: { id: viewer.id, name: viewer.name, email: viewer.email }
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
function parseInboxItem(value) {
|
|
1955
|
+
let item = object3(json2(value));
|
|
1956
|
+
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) => {
|
|
1957
|
+
let view = object3(value2);
|
|
1958
|
+
assert(text3(view.id) && text3(view.view) && text3(view.implementation)), json2(view.input);
|
|
1959
|
+
}), array2(item.people).forEach((value2) => {
|
|
1960
|
+
let person = object3(value2);
|
|
1961
|
+
assert(id2(person.id) && text3(person.name));
|
|
1962
|
+
}), array2(item.questions).forEach((value2) => {
|
|
1963
|
+
let question2 = object3(value2);
|
|
1964
|
+
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) {
|
|
1965
|
+
let accepted = object3(question2.acceptedResponse);
|
|
1966
|
+
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));
|
|
1967
|
+
}
|
|
1968
|
+
if (question2.execution !== null) {
|
|
1969
|
+
let execution = object3(question2.execution);
|
|
1970
|
+
if (assert(id2(execution.id) && ["pending", "running", "completed", "failed"].includes(String(execution.state)) && integer(execution.attempt, 0)), "consequence" in execution) {
|
|
1971
|
+
let consequence = object3(execution.consequence);
|
|
1972
|
+
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) => {
|
|
1973
|
+
let receipt = object3(value3);
|
|
1974
|
+
assert(text3(receipt.repository) && text3(receipt.commit) && text3(receipt.diff, !0));
|
|
1975
|
+
});
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
}), array2(item.linkedAsks).forEach((value2) => {
|
|
1979
|
+
let linked = object3(value2);
|
|
1980
|
+
if (assert(id2(linked.id)), linked.state === "unavailable") assert(typeof linked.done == "boolean");
|
|
1981
|
+
else if (assert(["yours", "done", "open", "theirs"].includes(String(linked.state)) && text3(linked.title)), linked.state === "theirs") {
|
|
1982
|
+
let assignee = object3(linked.assignee);
|
|
1983
|
+
assert(id2(assignee.id) && text3(assignee.name));
|
|
1984
|
+
}
|
|
1985
|
+
}), array2(item.activity).forEach((value2) => {
|
|
1986
|
+
let event2 = object3(value2);
|
|
1987
|
+
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);
|
|
1988
|
+
}), array2(item.work).forEach((value2) => {
|
|
1989
|
+
let work = object3(value2);
|
|
1990
|
+
assert(id2(work.id) && text3(work.questionId) && text3(work.reason) && optionalDate(work.settledAt));
|
|
1991
|
+
}), item;
|
|
1992
|
+
}
|
|
1993
|
+
function parseInboxAcceptance(value) {
|
|
1994
|
+
let accepted = object3(value);
|
|
1995
|
+
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;
|
|
1996
|
+
}
|
|
1997
|
+
function parseInboxResult(operation2, value) {
|
|
1998
|
+
if (operation2 === "current") return parseInboxCurrent(value);
|
|
1999
|
+
if (operation2 === "items.read") return parseInboxItem(value);
|
|
2000
|
+
if (operation2 === "items.list") {
|
|
2001
|
+
let page = object3(value), items = array2(page.items).map(parseInboxItem);
|
|
2002
|
+
return assert(items.length <= 100 && (page.nextBeforeNumber === null || integer(page.nextBeforeNumber))), { items, nextBeforeNumber: page.nextBeforeNumber };
|
|
2003
|
+
}
|
|
2004
|
+
if (operation2 === "items.see") {
|
|
2005
|
+
assert(date(value));
|
|
2006
|
+
return;
|
|
2007
|
+
}
|
|
2008
|
+
if (operation2 === "items.markDigestRead") {
|
|
2009
|
+
let read2 = object3(value);
|
|
2010
|
+
return assert(integer(read2.activityId) && date(read2.readAt)), read2;
|
|
2011
|
+
}
|
|
2012
|
+
if (operation2 === "items.rename" || operation2 === "items.setLifecycle") {
|
|
2013
|
+
let update = object3(value), item = parseInboxItem(update.item);
|
|
2014
|
+
return assert((update.activityId === null || integer(update.activityId)) && optionalDate(update.changedAt)), { ...update, item };
|
|
2015
|
+
}
|
|
2016
|
+
if (operation2 === "items.listRecipientCandidates") {
|
|
2017
|
+
let candidates = array2(value);
|
|
2018
|
+
return candidates.forEach((value2) => {
|
|
2019
|
+
let person = object3(value2);
|
|
2020
|
+
assert(id2(person.id) && text3(person.name) && text3(person.email));
|
|
2021
|
+
}), assert(new Set(candidates.map((value2) => object3(value2).id)).size === candidates.length), candidates;
|
|
2022
|
+
}
|
|
2023
|
+
if (operation2 === "items.addRecipient") {
|
|
2024
|
+
let addition = object3(value), item = parseInboxItem(addition.item);
|
|
2025
|
+
return assert(id2(addition.addedPersonId) && item.people.some((person) => person.id === addition.addedPersonId)), { ...addition, item };
|
|
2026
|
+
}
|
|
2027
|
+
if (operation2 === "questions.answer") return parseInboxAcceptance(value);
|
|
2028
|
+
if (operation2 === "questions.searchRecords") {
|
|
2029
|
+
let result2 = object3(value);
|
|
2030
|
+
assert(text3(result2.recordType) && integer(result2.eligibleCount, 0) && integer(result2.matchCount, 0) && Number(result2.matchCount) <= Number(result2.eligibleCount));
|
|
2031
|
+
let labeled = (value2) => {
|
|
2032
|
+
let record3 = object3(value2);
|
|
2033
|
+
recordReference({ repository: record3.repository, ref: record3.ref }), assert(text3(record3.label)), "reason" in record3 && assert(text3(record3.reason));
|
|
2034
|
+
};
|
|
2035
|
+
return array2(result2.matches).forEach(labeled), array2(result2.suggestions).forEach(labeled), "selected" in result2 && labeled(result2.selected), result2;
|
|
2036
|
+
}
|
|
2037
|
+
throw new Error("File content is not a JSON result");
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
async function limitedBody(request, limit, timeoutMs) {
|
|
2041
|
+
if (!request.body) return new Uint8Array();
|
|
2042
|
+
let reader = request.body.getReader(), expired = !1, timer = timeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
2043
|
+
expired = !0, reader.cancel().catch(() => {
|
|
2044
|
+
});
|
|
2045
|
+
}, timeoutMs), chunks = [], length = 0;
|
|
2046
|
+
try {
|
|
2047
|
+
for (; ; ) {
|
|
2048
|
+
let { done, value } = await reader.read();
|
|
2049
|
+
if (done) break;
|
|
2050
|
+
if (length += value.byteLength, length > limit) {
|
|
2051
|
+
await reader.cancel();
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
chunks.push(value);
|
|
2055
|
+
}
|
|
2056
|
+
if (expired) return;
|
|
2057
|
+
let contents = new Uint8Array(length), offset = 0;
|
|
2058
|
+
for (let chunk of chunks)
|
|
2059
|
+
contents.set(chunk, offset), offset += chunk.byteLength;
|
|
2060
|
+
return contents;
|
|
2061
|
+
} finally {
|
|
2062
|
+
timer !== void 0 && clearTimeout(timer);
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
var unavailable2 = () => new InboxOperationError(503, "unavailable"), stale = () => new InboxOperationError(401, "authority_unavailable");
|
|
2067
|
+
async function send2(operation2, input) {
|
|
2068
|
+
let envelope = parseInboxRequest({ operation: operation2, input }), context2;
|
|
2069
|
+
try {
|
|
2070
|
+
context2 = await resolveAppContext();
|
|
2071
|
+
} catch {
|
|
2072
|
+
throw stale();
|
|
2073
|
+
}
|
|
2074
|
+
if (context2.kind === "local" || context2.endpoint !== `https://${context2.workspace}.oddington.ai` || ["auth", "www", "api", "os"].includes(context2.workspace)) throw stale();
|
|
2075
|
+
let check = () => {
|
|
2076
|
+
if (!context2.isCurrent() || !Number.isFinite(context2.expiresAt) || context2.expiresAt <= Date.now()) throw stale();
|
|
2077
|
+
};
|
|
2078
|
+
check();
|
|
2079
|
+
try {
|
|
2080
|
+
let response2 = await fetch(`${context2.endpoint}/api/inbox`, {
|
|
2081
|
+
method: "POST",
|
|
2082
|
+
headers: { authorization: `Bearer ${context2.accessToken}`, "content-type": "application/json" },
|
|
2083
|
+
body: JSON.stringify(envelope),
|
|
2084
|
+
redirect: "error",
|
|
2085
|
+
cache: "no-store",
|
|
2086
|
+
signal: AbortSignal.timeout(3e4)
|
|
2087
|
+
});
|
|
2088
|
+
try {
|
|
2089
|
+
check();
|
|
2090
|
+
} catch (error) {
|
|
2091
|
+
throw response2.body?.cancel().catch(() => {
|
|
2092
|
+
}), error;
|
|
2093
|
+
}
|
|
2094
|
+
if (!response2.ok)
|
|
2095
|
+
throw response2.body?.cancel().catch(() => {
|
|
2096
|
+
}), new InboxOperationError(
|
|
2097
|
+
[400, 401, 403, 409].includes(response2.status) ? response2.status : 503,
|
|
2098
|
+
response2.status === 400 ? "invalid_input" : response2.status === 401 ? "authority_unavailable" : response2.status === 403 ? "access_denied" : response2.status === 409 ? "conflict" : "unavailable"
|
|
2099
|
+
);
|
|
2100
|
+
if (response2.status !== 200)
|
|
2101
|
+
throw response2.body?.cancel().catch(() => {
|
|
2102
|
+
}), unavailable2();
|
|
2103
|
+
if (operation2 === "files.read") {
|
|
2104
|
+
if (!response2.body) throw unavailable2();
|
|
2105
|
+
let source = response2.body, reader, size = 0, cancel = async (reason) => {
|
|
2106
|
+
try {
|
|
2107
|
+
await (reader ? reader.cancel(reason) : source.cancel(reason));
|
|
2108
|
+
} finally {
|
|
2109
|
+
reader?.releaseLock();
|
|
2110
|
+
}
|
|
2111
|
+
}, body2 = new ReadableStream({
|
|
2112
|
+
async pull(controller) {
|
|
2113
|
+
try {
|
|
2114
|
+
check(), reader ??= source.getReader();
|
|
2115
|
+
let next = await reader.read();
|
|
2116
|
+
if (check(), next.done) {
|
|
2117
|
+
reader.releaseLock(), controller.close();
|
|
2118
|
+
return;
|
|
2119
|
+
}
|
|
2120
|
+
if (size += next.value.byteLength, size > 25 * 1024 * 1024) throw unavailable2();
|
|
2121
|
+
controller.enqueue(next.value);
|
|
2122
|
+
} catch (error) {
|
|
2123
|
+
controller.error(error), await cancel(error).catch(() => {
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
},
|
|
2127
|
+
cancel
|
|
2128
|
+
}, { highWaterMark: 0 });
|
|
2129
|
+
return new Response(body2, { status: response2.status, headers: response2.headers });
|
|
2130
|
+
}
|
|
2131
|
+
let bytes = await limitedBody(response2, INBOX_RESULT_BYTES);
|
|
2132
|
+
if (check(), !bytes) throw unavailable2();
|
|
2133
|
+
let value = JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes)), parsed = parseInboxResult(operation2, value);
|
|
2134
|
+
if (check(), operation2 === "current" && parsed.workspace.slug !== context2.workspace) throw unavailable2();
|
|
2135
|
+
if ("itemId" in envelope.input) {
|
|
2136
|
+
let item = operation2 === "items.read" ? parsed : operation2 === "items.rename" || operation2 === "items.setLifecycle" || operation2 === "items.addRecipient" ? parsed.item : void 0;
|
|
2137
|
+
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();
|
|
2138
|
+
}
|
|
2139
|
+
return parsed;
|
|
2140
|
+
} catch (error) {
|
|
2141
|
+
throw check(), error instanceof InboxOperationError ? error : unavailable2();
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
var inbox = {
|
|
2145
|
+
current: async () => await send2("current", {}),
|
|
2146
|
+
items: {
|
|
2147
|
+
async list() {
|
|
2148
|
+
let items = [], beforeNumber, initial;
|
|
2149
|
+
try {
|
|
2150
|
+
initial = await resolveAppContext();
|
|
2151
|
+
} catch {
|
|
2152
|
+
throw stale();
|
|
2153
|
+
}
|
|
2154
|
+
let check = () => {
|
|
2155
|
+
if (!initial.isCurrent() || initial.expiresAt <= Date.now()) throw stale();
|
|
2156
|
+
};
|
|
2157
|
+
do {
|
|
2158
|
+
check();
|
|
2159
|
+
let page = await send2("items.list", beforeNumber === void 0 ? {} : { beforeNumber });
|
|
2160
|
+
if (check(), beforeNumber !== void 0 && (page.items.some((item) => item.number >= beforeNumber) || page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber)) throw unavailable2();
|
|
2161
|
+
if (items.push(...page.items), page.nextBeforeNumber === null) return items;
|
|
2162
|
+
beforeNumber = page.nextBeforeNumber;
|
|
2163
|
+
} while (!0);
|
|
2164
|
+
},
|
|
2165
|
+
read: async (itemId) => await send2("items.read", { itemId }),
|
|
2166
|
+
see: async (itemId) => {
|
|
2167
|
+
await send2("items.see", { itemId });
|
|
2168
|
+
},
|
|
2169
|
+
markDigestRead: async (itemId) => await send2("items.markDigestRead", { itemId }),
|
|
2170
|
+
rename: async (input) => await send2("items.rename", input),
|
|
2171
|
+
setLifecycle: async (input) => await send2("items.setLifecycle", input),
|
|
2172
|
+
listRecipientCandidates: async (itemId) => await send2("items.listRecipientCandidates", { itemId }),
|
|
2173
|
+
addRecipient: async (input) => await send2("items.addRecipient", input)
|
|
2174
|
+
},
|
|
2175
|
+
questions: {
|
|
2176
|
+
answer: async (input) => await send2("questions.answer", input),
|
|
2177
|
+
searchRecords: async (input) => await send2("questions.searchRecords", input)
|
|
2178
|
+
},
|
|
2179
|
+
files: { read: async (input) => await send2("files.read", input) }
|
|
2180
|
+
};
|
|
2181
|
+
|
|
1773
2182
|
var sources = /* @__PURE__ */ new WeakMap();
|
|
1774
2183
|
function registerBrowserAuth(handle2, source) {
|
|
1775
2184
|
sources.set(handle2, source);
|
|
@@ -1782,14 +2191,14 @@ var sessionKey = "_os.app.session", responseChecks = /* @__PURE__ */ new WeakMap
|
|
|
1782
2191
|
}, AppContextDenied = class extends Error {
|
|
1783
2192
|
}, AppRenewalUnavailable = class extends Error {
|
|
1784
2193
|
};
|
|
1785
|
-
async function appResponse(
|
|
1786
|
-
if (signal.aborted || !
|
|
1787
|
-
let reader =
|
|
2194
|
+
async function appResponse(response2, maximum, signal) {
|
|
2195
|
+
if (signal.aborted || !response2.body || response2.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() !== "application/json") throw new Error();
|
|
2196
|
+
let reader = response2.body.getReader(), abort = () => {
|
|
1788
2197
|
reader.cancel().catch(() => {
|
|
1789
2198
|
});
|
|
1790
2199
|
};
|
|
1791
2200
|
signal.addEventListener("abort", abort, { once: !0 });
|
|
1792
|
-
let bytes = 0,
|
|
2201
|
+
let bytes = 0, text4 = "", decoder = new TextDecoder("utf-8", { fatal: !0 });
|
|
1793
2202
|
try {
|
|
1794
2203
|
for (; ; ) {
|
|
1795
2204
|
let chunk;
|
|
@@ -1800,13 +2209,13 @@ async function appResponse(response, maximum, signal) {
|
|
|
1800
2209
|
}
|
|
1801
2210
|
if (signal.aborted) throw new Error();
|
|
1802
2211
|
if (chunk.done) {
|
|
1803
|
-
let value = JSON.parse(
|
|
1804
|
-
if (await responseChecks.get(
|
|
2212
|
+
let value = JSON.parse(text4 + decoder.decode());
|
|
2213
|
+
if (await responseChecks.get(response2)?.(value), signal.aborted) throw new Error();
|
|
1805
2214
|
return value;
|
|
1806
2215
|
}
|
|
1807
2216
|
if (bytes += chunk.value.byteLength, bytes > maximum)
|
|
1808
2217
|
throw abort(), new Error();
|
|
1809
|
-
|
|
2218
|
+
text4 += decoder.decode(chunk.value, { stream: !0 });
|
|
1810
2219
|
}
|
|
1811
2220
|
} finally {
|
|
1812
2221
|
signal.removeEventListener("abort", abort), reader.releaseLock();
|
|
@@ -1844,7 +2253,7 @@ function appContext(origin, active2) {
|
|
|
1844
2253
|
}, 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
2254
|
async function proof(candidate, signal = controller.signal) {
|
|
1846
2255
|
if (!alive() || !/^[A-Za-z0-9_-]{43}$/.test(candidate)) throw new Error();
|
|
1847
|
-
let url = `${origin}/_os/app/context`,
|
|
2256
|
+
let url = `${origin}/_os/app/context`, response2 = await fetch(url, {
|
|
1848
2257
|
credentials: "omit",
|
|
1849
2258
|
redirect: "error",
|
|
1850
2259
|
cache: "no-store",
|
|
@@ -1852,10 +2261,10 @@ function appContext(origin, active2) {
|
|
|
1852
2261
|
headers: { authorization: `Bearer ${candidate}` },
|
|
1853
2262
|
signal
|
|
1854
2263
|
});
|
|
1855
|
-
if (
|
|
1856
|
-
if (
|
|
1857
|
-
if (!
|
|
1858
|
-
let value = await appResponse(
|
|
2264
|
+
if (response2.redirected || response2.url && response2.url !== url) throw new Error();
|
|
2265
|
+
if (response2.status === 401 || response2.status === 403) throw new AppContextDenied();
|
|
2266
|
+
if (!response2.ok) throw new Error();
|
|
2267
|
+
let value = await appResponse(response2, 4096, signal);
|
|
1859
2268
|
if (!alive() || !bounded(value)) throw new Error();
|
|
1860
2269
|
return value;
|
|
1861
2270
|
}
|
|
@@ -1906,9 +2315,9 @@ function appContext(origin, active2) {
|
|
|
1906
2315
|
let timeout = setTimeout(abort, Math.min(2e4, deadline - Date.now())), previous = credential;
|
|
1907
2316
|
try {
|
|
1908
2317
|
if (await synchronize(), credential !== previous) return;
|
|
1909
|
-
let url = `${origin}/_os/app/renew`,
|
|
2318
|
+
let url = `${origin}/_os/app/renew`, response2;
|
|
1910
2319
|
try {
|
|
1911
|
-
|
|
2320
|
+
response2 = await fetch(url, {
|
|
1912
2321
|
method: "POST",
|
|
1913
2322
|
credentials: "omit",
|
|
1914
2323
|
redirect: "error",
|
|
@@ -1920,11 +2329,11 @@ function appContext(origin, active2) {
|
|
|
1920
2329
|
} catch {
|
|
1921
2330
|
throw new AppRenewalUnavailable();
|
|
1922
2331
|
}
|
|
1923
|
-
if (
|
|
1924
|
-
let value = await appResponse(
|
|
1925
|
-
if (
|
|
2332
|
+
if (response2.redirected || response2.url && response2.url !== url) throw new Error();
|
|
2333
|
+
let value = await appResponse(response2, 4096, requestController.signal);
|
|
2334
|
+
if (response2.status === 503 && value && typeof value == "object" && !Array.isArray(value) && Object.keys(value).join(",") === "error" && "error" in value && value.error === "renewal_unavailable")
|
|
1926
2335
|
throw new AppRenewalUnavailable();
|
|
1927
|
-
if (
|
|
2336
|
+
if (response2.status === 403 && value && typeof value == "object" && !Array.isArray(value) && Object.keys(value).join(",") === "error" && "error" in value && value.error === "renewal_conflict") {
|
|
1928
2337
|
for (; alive() && stored() === previous && !requestController.signal.aborted; )
|
|
1929
2338
|
await new Promise((resolve2, reject) => {
|
|
1930
2339
|
let abortWait = () => {
|
|
@@ -1938,7 +2347,7 @@ function appContext(origin, active2) {
|
|
|
1938
2347
|
await synchronize();
|
|
1939
2348
|
return;
|
|
1940
2349
|
}
|
|
1941
|
-
if (!
|
|
2350
|
+
if (!response2.ok) throw new Error();
|
|
1942
2351
|
if (!alive() || Date.now() >= deadline || !value || typeof value != "object" || Array.isArray(value) || Object.keys(value).sort().join(",") !== "context,credential") throw new Error();
|
|
1943
2352
|
let result2 = value;
|
|
1944
2353
|
if (!bounded(result2.context) || typeof result2.credential != "string" || !/^[A-Za-z0-9_-]{43}$/.test(result2.credential) || result2.credential === previous) throw new Error();
|
|
@@ -1994,7 +2403,7 @@ function appContext(origin, active2) {
|
|
|
1994
2403
|
async function requestData(operation2, input) {
|
|
1995
2404
|
try {
|
|
1996
2405
|
if (operation2 !== "data/query" || !current2()) throw new Error();
|
|
1997
|
-
let url = `${origin}/_os/app/data`, admitted = credential,
|
|
2406
|
+
let url = `${origin}/_os/app/data`, admitted = credential, response2 = await fetch(url, {
|
|
1998
2407
|
method: "POST",
|
|
1999
2408
|
credentials: "omit",
|
|
2000
2409
|
redirect: "error",
|
|
@@ -2005,13 +2414,13 @@ function appContext(origin, active2) {
|
|
|
2005
2414
|
body: JSON.stringify(input)
|
|
2006
2415
|
});
|
|
2007
2416
|
for (await synchronize(); alive() && stored() !== credential; ) await synchronize();
|
|
2008
|
-
if (!current2() ||
|
|
2009
|
-
if (
|
|
2417
|
+
if (!current2() || response2.redirected || response2.url && response2.url !== url) throw new Error();
|
|
2418
|
+
if (response2.status === 401 || response2.status === 403)
|
|
2010
2419
|
throw admitted === credential && invalidate(), new DataOperationError("access_denied");
|
|
2011
|
-
let result2 = await appResponse(
|
|
2420
|
+
let result2 = await appResponse(response2, Number.MAX_SAFE_INTEGER, controller.signal);
|
|
2012
2421
|
for (await synchronize(); alive() && stored() !== credential; ) await synchronize();
|
|
2013
2422
|
if (!current2()) throw new Error();
|
|
2014
|
-
if (!
|
|
2423
|
+
if (!response2.ok) throw dataTransportError(response2.status, result2);
|
|
2015
2424
|
return result2;
|
|
2016
2425
|
} catch (error) {
|
|
2017
2426
|
throw error instanceof DataOperationError ? error : !current2() || controller.signal.aborted ? new DataOperationError("context_unavailable") : new DataOperationError("unavailable", !0);
|
|
@@ -2020,7 +2429,7 @@ function appContext(origin, active2) {
|
|
|
2020
2429
|
async function requestRoutine(key, suffix, init2 = {}) {
|
|
2021
2430
|
if (!current2())
|
|
2022
2431
|
throw invalidate(), new Error("Local app context unavailable.");
|
|
2023
|
-
let url = `${origin}/_os/app/routines/${encodeURIComponent(key)}/${suffix}`, admitted = credential,
|
|
2432
|
+
let url = `${origin}/_os/app/routines/${encodeURIComponent(key)}/${suffix}`, admitted = credential, response2 = await fetch(url, {
|
|
2024
2433
|
...init2,
|
|
2025
2434
|
credentials: "omit",
|
|
2026
2435
|
redirect: "error",
|
|
@@ -2030,12 +2439,12 @@ function appContext(origin, active2) {
|
|
|
2030
2439
|
headers: { ...init2.body === void 0 ? {} : { "content-type": "application/json" }, authorization: `Bearer ${credential}` }
|
|
2031
2440
|
});
|
|
2032
2441
|
for (await synchronize(); alive() && stored() !== credential; ) await synchronize();
|
|
2033
|
-
if (!current2() ||
|
|
2442
|
+
if (!current2() || response2.redirected || response2.url && response2.url !== url)
|
|
2034
2443
|
throw invalidate(), new Error("Local app context unavailable.");
|
|
2035
|
-
return (
|
|
2444
|
+
return (response2.status === 401 || response2.status === 403) && admitted === credential && invalidate(), responseChecks.set(response2, async (value) => {
|
|
2036
2445
|
for (await synchronize(); alive() && stored() !== credential; ) await synchronize();
|
|
2037
2446
|
admitted === credential && value && typeof value == "object" && "error" in value && value.error === "authority_unavailable" && invalidate();
|
|
2038
|
-
}),
|
|
2447
|
+
}), response2;
|
|
2039
2448
|
}
|
|
2040
2449
|
function context2() {
|
|
2041
2450
|
let issued = credential;
|
|
@@ -2144,9 +2553,9 @@ function authorizationConfiguration(value) {
|
|
|
2144
2553
|
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
2554
|
return { clientId: setup.clientId, redirectUri: CLI_CALLBACK, scopes: ["email"] };
|
|
2146
2555
|
}
|
|
2147
|
-
function authorizationDetails(value,
|
|
2556
|
+
function authorizationDetails(value, id3, setup, userId, account) {
|
|
2148
2557
|
let details = value;
|
|
2149
|
-
return !details || details.authorization_id !==
|
|
2558
|
+
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
2559
|
status: "consent",
|
|
2151
2560
|
clientName: details.client.name.trim(),
|
|
2152
2561
|
account,
|
|
@@ -2196,7 +2605,8 @@ function createBrowserAuth(runtime) {
|
|
|
2196
2605
|
}
|
|
2197
2606
|
function accept(c, event2, session) {
|
|
2198
2607
|
if (!c.active || event2 === "INITIAL_SESSION" && c.state.status !== "initializing" || event2 === "TOKEN_REFRESHED" && !c.session && c.state.status !== "initializing") return;
|
|
2199
|
-
|
|
2608
|
+
let replaced = c.session?.user?.id !== session?.user?.id || event2 === "SIGNED_OUT" || !!(event2 === "SIGNED_IN" && c.session && session?.access_token !== c.session.access_token);
|
|
2609
|
+
replaced && c.revision++, c.timer && clearTimeout(c.timer);
|
|
2200
2610
|
let pending = c.state.pending;
|
|
2201
2611
|
if (!session) {
|
|
2202
2612
|
c.session = null, publish(c, { status: c.state.status === "expired" ? "expired" : "signed_out", ...pending ? { pending } : {} }), notify(c, "SIGNED_OUT");
|
|
@@ -2207,8 +2617,8 @@ function createBrowserAuth(runtime) {
|
|
|
2207
2617
|
return;
|
|
2208
2618
|
}
|
|
2209
2619
|
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
|
|
2620
|
+
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 });
|
|
2621
|
+
publish(c, { status: "signed_in", account, ...pending ? { pending } : {} }), notify(c, event2);
|
|
2212
2622
|
let checkExpiry = () => {
|
|
2213
2623
|
if (!c.active || !c.session) return;
|
|
2214
2624
|
let remaining = c.session.expires_at * 1e3 - Date.now();
|
|
@@ -2234,9 +2644,9 @@ function createBrowserAuth(runtime) {
|
|
|
2234
2644
|
let revision = c.revision;
|
|
2235
2645
|
try {
|
|
2236
2646
|
if (!allowedOrigin(origin)) throw runtime.failure("unavailable");
|
|
2237
|
-
let
|
|
2238
|
-
if (!
|
|
2239
|
-
let configuration = validateConfiguration(await
|
|
2647
|
+
let response2 = await fetch(`${origin}/api/auth`, { method: "GET", credentials: "same-origin", redirect: "error", cache: "no-store" });
|
|
2648
|
+
if (!response2.ok) throw runtime.failure("unavailable");
|
|
2649
|
+
let configuration = validateConfiguration(await response2.json());
|
|
2240
2650
|
if (configuration.authorization && origin !== "https://auth.oddington.ai" && origin !== "http://127.0.0.1:5176") throw runtime.failure("unavailable");
|
|
2241
2651
|
if (c.authorization = configuration.authorization, !c.active || globalThis.location?.origin !== origin) return;
|
|
2242
2652
|
if (c.provider = await runtime.provider(configuration, {
|
|
@@ -2297,10 +2707,10 @@ function createBrowserAuth(runtime) {
|
|
|
2297
2707
|
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
2708
|
}
|
|
2299
2709
|
}
|
|
2300
|
-
async function authorize(kind,
|
|
2710
|
+
async function authorize(kind, id3) {
|
|
2301
2711
|
if (!active2) return Object.freeze({ status: "disposed" });
|
|
2302
|
-
if (
|
|
2303
|
-
if (typeof
|
|
2712
|
+
if (id3 !== authorizationId && (authorizationId = id3, authorizationGeneration++, inspected = void 0), !id3) return Object.freeze({ status: "missing" });
|
|
2713
|
+
if (typeof id3 != "string" || !/^[A-Za-z0-9_-]{1,128}$/.test(id3)) return Object.freeze({ status: "invalid" });
|
|
2304
2714
|
let generation = authorizationGeneration;
|
|
2305
2715
|
if (await coordinator.ready, !active2) return Object.freeze({ status: "disposed" });
|
|
2306
2716
|
if (generation !== authorizationGeneration) return Object.freeze({ status: "stale" });
|
|
@@ -2309,37 +2719,37 @@ function createBrowserAuth(runtime) {
|
|
|
2309
2719
|
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
2720
|
if (!coordinator.authorization || !coordinator.provider) return Object.freeze({ status: "unavailable" });
|
|
2311
2721
|
if (coordinator.action) return Object.freeze({ status: "busy" });
|
|
2312
|
-
if (kind !== "get" && (!inspected || inspected.id !==
|
|
2722
|
+
if (kind !== "get" && (!inspected || inspected.id !== id3 || inspected.revision !== revision)) return Object.freeze({ status: "stale" });
|
|
2313
2723
|
if (kind !== "get" && inspected?.result.status !== "consent") return inspected.result;
|
|
2314
2724
|
let marker = {};
|
|
2315
2725
|
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",
|
|
2726
|
+
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
2727
|
try {
|
|
2318
|
-
let provider2 = coordinator.provider,
|
|
2319
|
-
if (!requestCurrent()) return
|
|
2320
|
-
if (
|
|
2728
|
+
let provider2 = coordinator.provider, response2 = await provider2.authorization.get(id3, requestCurrent);
|
|
2729
|
+
if (!requestCurrent()) return stale2();
|
|
2730
|
+
if (response2.error) {
|
|
2321
2731
|
inspected = void 0;
|
|
2322
|
-
let failure = authorizationFailure(
|
|
2732
|
+
let failure = authorizationFailure(response2.error);
|
|
2323
2733
|
return failure.status === "signed_out" && expire(coordinator), failure;
|
|
2324
2734
|
}
|
|
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
|
|
2735
|
+
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);
|
|
2736
|
+
if (inspected = { id: id3, revision, result: result2 }, kind === "get" || result2.status !== "consent") return result2;
|
|
2737
|
+
if (!requestCurrent()) return stale2();
|
|
2738
|
+
let decision = await provider2.authorization[kind](id3, requestCurrent);
|
|
2739
|
+
if (!requestCurrent()) return stale2();
|
|
2330
2740
|
let returned = decision.error ? authorizationFailure(decision.error) : authorizationReturn(decision.data, kind);
|
|
2331
|
-
return returned.status === "signed_out" && expire(coordinator), inspected = { id:
|
|
2741
|
+
return returned.status === "signed_out" && expire(coordinator), inspected = { id: id3, revision, result: returned }, returned;
|
|
2332
2742
|
} catch (error) {
|
|
2333
|
-
return !requestCurrent() || (inspected = void 0, safeReason(error) === "stale") ?
|
|
2743
|
+
return !requestCurrent() || (inspected = void 0, safeReason(error) === "stale") ? stale2() : Object.freeze({ status: "unavailable" });
|
|
2334
2744
|
} finally {
|
|
2335
2745
|
coordinator.action === marker && (coordinator.action = void 0), ownedAction === marker && (ownedAction = void 0);
|
|
2336
2746
|
}
|
|
2337
2747
|
}
|
|
2338
2748
|
let handle2 = Object.freeze({
|
|
2339
2749
|
authorization: Object.freeze({
|
|
2340
|
-
get: (
|
|
2341
|
-
approve: (
|
|
2342
|
-
deny: (
|
|
2750
|
+
get: (id3) => authorize("get", id3),
|
|
2751
|
+
approve: (id3) => authorize("approve", id3),
|
|
2752
|
+
deny: (id3) => authorize("deny", id3)
|
|
2343
2753
|
}),
|
|
2344
2754
|
getState() {
|
|
2345
2755
|
return active2 && coordinator.session && !validSession(coordinator.session) && expire(coordinator), lastState;
|
|
@@ -2477,19 +2887,19 @@ async function provider(configuration, guard) {
|
|
|
2477
2887
|
throw request && (request.rejected = !0), new BrowserAuthError("stale");
|
|
2478
2888
|
};
|
|
2479
2889
|
request && (!request.current() || !guard.canAuthorize(new Headers(init2?.headers).get("authorization")?.replace(/^Bearer /, "") ?? "")) && rejectStale();
|
|
2480
|
-
let
|
|
2890
|
+
let response2 = await fetch(input, { ...init2, redirect: "error" }), body2 = await response2.arrayBuffer();
|
|
2481
2891
|
(!guard.current(revision) || request && !request.current()) && rejectStale();
|
|
2482
2892
|
let result2 = new Response(
|
|
2483
|
-
[204, 205, 304].includes(
|
|
2484
|
-
{ status:
|
|
2485
|
-
),
|
|
2893
|
+
[204, 205, 304].includes(response2.status) ? null : body2,
|
|
2894
|
+
{ status: response2.status, statusText: response2.statusText, headers: response2.headers }
|
|
2895
|
+
), json3 = result2.json.bind(result2);
|
|
2486
2896
|
return result2.json = async () => {
|
|
2487
|
-
let value = await
|
|
2897
|
+
let value = await json3();
|
|
2488
2898
|
return (!guard.current(revision) || request && !request.current()) && rejectStale(), value && typeof value.access_token == "string" && provenance.set(value.access_token, revision), value;
|
|
2489
2899
|
}, result2;
|
|
2490
2900
|
}, { preconnect: fetch.preconnect })
|
|
2491
2901
|
});
|
|
2492
|
-
async function authorization(kind,
|
|
2902
|
+
async function authorization(kind, id3, current2) {
|
|
2493
2903
|
let previous = authorizationQueue, release;
|
|
2494
2904
|
authorizationQueue = new Promise((resolve) => {
|
|
2495
2905
|
release = resolve;
|
|
@@ -2498,7 +2908,7 @@ async function provider(configuration, guard) {
|
|
|
2498
2908
|
authorizationRequest = request;
|
|
2499
2909
|
try {
|
|
2500
2910
|
if (!current2()) throw new BrowserAuthError("stale");
|
|
2501
|
-
let result2 = await (kind === "get" ? client.oauth.getAuthorizationDetails(
|
|
2911
|
+
let result2 = await (kind === "get" ? client.oauth.getAuthorizationDetails(id3) : kind === "approve" ? client.oauth.approveAuthorization(id3, { skipBrowserRedirect: !0 }) : client.oauth.denyAuthorization(id3, { skipBrowserRedirect: !0 }));
|
|
2502
2912
|
if (request.rejected || !current2()) throw new BrowserAuthError("stale");
|
|
2503
2913
|
return result2;
|
|
2504
2914
|
} catch (error) {
|
|
@@ -2509,9 +2919,9 @@ async function provider(configuration, guard) {
|
|
|
2509
2919
|
}
|
|
2510
2920
|
return {
|
|
2511
2921
|
authorization: {
|
|
2512
|
-
get: (
|
|
2513
|
-
approve: (
|
|
2514
|
-
deny: (
|
|
2922
|
+
get: (id3, current2) => authorization("get", id3, current2),
|
|
2923
|
+
approve: (id3, current2) => authorization("approve", id3, current2),
|
|
2924
|
+
deny: (id3, current2) => authorization("deny", id3, current2)
|
|
2515
2925
|
},
|
|
2516
2926
|
getSession: () => client.getSession(),
|
|
2517
2927
|
onAuthStateChange: (callback) => client.onAuthStateChange((event2, session) => {
|
|
@@ -2546,50 +2956,50 @@ var identifier = /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/, uuid = /^[0-9a-f]{8}-[0-
|
|
|
2546
2956
|
function fail3(reason) {
|
|
2547
2957
|
throw new AppRoutineError(reason);
|
|
2548
2958
|
}
|
|
2549
|
-
function
|
|
2959
|
+
function object4(value) {
|
|
2550
2960
|
return !!value && typeof value == "object" && !Array.isArray(value);
|
|
2551
2961
|
}
|
|
2552
|
-
function
|
|
2962
|
+
function keys4(value, expected) {
|
|
2553
2963
|
return Object.keys(value).sort().join(",") === expected;
|
|
2554
2964
|
}
|
|
2555
2965
|
function current(context2) {
|
|
2556
2966
|
(!context2.isCurrent() || context2.signal.aborted) && fail3("authority_unavailable");
|
|
2557
2967
|
}
|
|
2558
|
-
async function body(context2,
|
|
2968
|
+
async function body(context2, response2, maximum) {
|
|
2559
2969
|
try {
|
|
2560
|
-
let value = await appResponse(
|
|
2561
|
-
return current(context2),
|
|
2970
|
+
let value = await appResponse(response2, maximum, context2.signal);
|
|
2971
|
+
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
2972
|
} catch (error) {
|
|
2563
2973
|
if (current(context2), error instanceof AppResponseReadError || error instanceof AppRoutineError) throw error;
|
|
2564
2974
|
return fail3("execution_unavailable");
|
|
2565
2975
|
}
|
|
2566
2976
|
}
|
|
2567
2977
|
function descriptor(value, key) {
|
|
2568
|
-
return (!
|
|
2978
|
+
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
2979
|
}
|
|
2570
2980
|
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)) :
|
|
2981
|
+
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
2982
|
}
|
|
2573
2983
|
function event(value, run, steps) {
|
|
2574
|
-
(!
|
|
2984
|
+
(!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
2985
|
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)) &&
|
|
2986
|
+
if (value.type === "started" && keys4(value, common + "type") && value.sequence === 1) return { type: "started" };
|
|
2987
|
+
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
2988
|
return {
|
|
2579
2989
|
type: "step",
|
|
2580
2990
|
id: value.id,
|
|
2581
2991
|
...Object.hasOwn(value, "summary") ? { summary: value.summary } : {}
|
|
2582
2992
|
};
|
|
2583
2993
|
if (value.type === "finished") {
|
|
2584
|
-
if (value.state === "succeeded" &&
|
|
2994
|
+
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
2995
|
return {
|
|
2586
2996
|
type: "finished",
|
|
2587
2997
|
state: "succeeded",
|
|
2588
2998
|
...Object.hasOwn(value, "result") ? { result: value.result } : {}
|
|
2589
2999
|
};
|
|
2590
|
-
if (value.state === "failed" && value.error === "execution_failed" &&
|
|
3000
|
+
if (value.state === "failed" && value.error === "execution_failed" && keys4(value, "error," + common + "state,type"))
|
|
2591
3001
|
return { type: "finished", state: "failed", error: "execution_failed" };
|
|
2592
|
-
if (value.state === "cancelled" &&
|
|
3002
|
+
if (value.state === "cancelled" && keys4(value, common + "state,type")) return { type: "finished", state: "cancelled" };
|
|
2593
3003
|
}
|
|
2594
3004
|
return fail3("execution_unavailable");
|
|
2595
3005
|
}
|
|
@@ -2610,26 +3020,26 @@ function handle(context2, run, steps) {
|
|
|
2610
3020
|
let cursor = 0, terminal = !1, delay = 100, retainedBytes = 0, seen = [];
|
|
2611
3021
|
for (; !terminal; ) {
|
|
2612
3022
|
current(context2);
|
|
2613
|
-
let
|
|
3023
|
+
let response2;
|
|
2614
3024
|
try {
|
|
2615
|
-
|
|
3025
|
+
response2 = await context2.requestRoutine(run.key, `runs/${run.runId}/events?after=${cursor}`);
|
|
2616
3026
|
} catch {
|
|
2617
3027
|
current(context2), await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
2618
3028
|
continue;
|
|
2619
3029
|
}
|
|
2620
|
-
if (
|
|
2621
|
-
await
|
|
3030
|
+
if (response2.status >= 500) {
|
|
3031
|
+
await response2.body?.cancel(), await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
2622
3032
|
continue;
|
|
2623
3033
|
}
|
|
2624
3034
|
let value;
|
|
2625
3035
|
try {
|
|
2626
|
-
value = await body(context2,
|
|
3036
|
+
value = await body(context2, response2, 80 * 1024);
|
|
2627
3037
|
} catch (error) {
|
|
2628
3038
|
if (!(error instanceof AppResponseReadError)) throw error;
|
|
2629
3039
|
await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
2630
3040
|
continue;
|
|
2631
3041
|
}
|
|
2632
|
-
(!
|
|
3042
|
+
(!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
3043
|
let delivery = [];
|
|
2634
3044
|
for (let raw of value.events) {
|
|
2635
3045
|
let publicEvent = event(raw, run, steps), encoded = JSON.stringify(raw), sequence = raw.sequence;
|
|
@@ -2649,7 +3059,7 @@ function handle(context2, run, steps) {
|
|
|
2649
3059
|
args.length && fail3("invalid_input");
|
|
2650
3060
|
try {
|
|
2651
3061
|
let value = await body(context2, await context2.requestRoutine(run.key, `runs/${run.runId}/cancel`, { method: "POST" }), 1024);
|
|
2652
|
-
(!
|
|
3062
|
+
(!object4(value) || !keys4(value, "cancelled") || value.cancelled !== !0) && fail3("execution_unavailable");
|
|
2653
3063
|
} catch (error) {
|
|
2654
3064
|
if (current(context2), error instanceof AppRoutineError) throw error;
|
|
2655
3065
|
fail3("execution_unavailable");
|
|
@@ -2664,12 +3074,12 @@ async function appRoutineOperation(key, input, recover) {
|
|
|
2664
3074
|
let resolved = await resolveAppContext();
|
|
2665
3075
|
if (resolved.kind !== "local" && fail3("execution_unavailable"), context2 = resolved, recover) {
|
|
2666
3076
|
let value2 = await body(context2, await context2.requestRoutine(key, "runs"), 16384);
|
|
2667
|
-
(!
|
|
3077
|
+
(!object4(value2) || !keys4(value2, "runs") || !Array.isArray(value2.runs) || value2.runs.length > 20) && fail3("execution_unavailable");
|
|
2668
3078
|
let runs = value2.runs.map((run) => descriptor(run, key));
|
|
2669
3079
|
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
3080
|
}
|
|
2671
3081
|
let available = await body(context2, await context2.requestAvailability(key), 16 * 1024);
|
|
2672
|
-
|
|
3082
|
+
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
3083
|
let steps = [...available.steps], encoded;
|
|
2674
3084
|
try {
|
|
2675
3085
|
encoded = JSON.stringify(input), (encoded === void 0 || new TextEncoder().encode(encoded).byteLength > 16 * 1024) && fail3("invalid_input");
|
|
@@ -2693,10 +3103,10 @@ async function availability(key) {
|
|
|
2693
3103
|
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/.test(key)) return authorityUnavailable();
|
|
2694
3104
|
let context2 = await resolveAppContext();
|
|
2695
3105
|
if (context2.kind !== "local") return { available: !1, reason: "execution_unavailable" };
|
|
2696
|
-
let
|
|
2697
|
-
if (!
|
|
3106
|
+
let response2 = await context2.requestAvailability(key);
|
|
3107
|
+
if (!response2.ok || response2.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() !== "application/json")
|
|
2698
3108
|
return authorityUnavailable();
|
|
2699
|
-
let value = await appResponse(
|
|
3109
|
+
let value = await appResponse(response2, MAX_RESPONSE_BYTES, context2.signal);
|
|
2700
3110
|
if (!context2.isCurrent() || !value || typeof value != "object" || Array.isArray(value)) return authorityUnavailable();
|
|
2701
3111
|
let result2 = value;
|
|
2702
3112
|
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] };
|
|
@@ -2739,40 +3149,51 @@ function validateCsvHints(value) {
|
|
|
2739
3149
|
return v;
|
|
2740
3150
|
}
|
|
2741
3151
|
|
|
3152
|
+
var PREPARED_RECORD_INPUT_LIMIT = 64 * 1024 * 1024;
|
|
3153
|
+
|
|
3154
|
+
function routineDataEnvelope(command) {
|
|
3155
|
+
return "preflight" in command ? { operation: "changes.validate", captured: command.preflight } : "apply" in command ? { operation: "changes.publish", captured: command.apply } : { operation: "changes.publish", request: command };
|
|
3156
|
+
}
|
|
3157
|
+
|
|
2742
3158
|
function routinePublicationClient2(options = {}) {
|
|
2743
|
-
let environment = {}, local = void 0, workspace = options.workspace ?? environment.ODDINGTON_ROUTINE_WORKSPACE, capability = options.capability ?? environment.ODDINGTON_ROUTINE_RUN;
|
|
3159
|
+
let environment = {}, installed2 = routineTransport(), local = installed2?.request ?? void 0, workspace = installed2 ? "installed" : options.workspace ?? environment.ODDINGTON_ROUTINE_WORKSPACE, capability = options.capability ?? environment.ODDINGTON_ROUTINE_RUN;
|
|
2744
3160
|
if (!workspace || !/^[a-z0-9][a-z0-9-]*$/.test(workspace) || capability !== void 0 && !/^[0-9a-f]{64}$/.test(capability))
|
|
2745
3161
|
throw new Error("A workspace and valid optional routine capability are required");
|
|
2746
3162
|
let workingRoot = options.workingRoot ?? environment.ODDINGTON_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-oddington-run": capability } : {}, request = options.request ?? (capability ? async (path, init2) => {
|
|
2747
|
-
|
|
2748
|
-
|
|
3163
|
+
if (path === "/api/data") return fetch(`https://${workspace}.oddington.ai/api/data`, { ...init2, redirect: "error" });
|
|
3164
|
+
let origin = `https://${workspace}.oddington.ai`, target = new URL(path, `${origin}/`);
|
|
3165
|
+
if (workspace.length > 63 || ["auth", "www", "api", "os"].includes(workspace) || target.origin !== origin || target.search || target.hash || target.username || target.password || !/^\/api\/inbox\/(check|publish|resolve|files)$/.test(path) || init2?.method !== "POST")
|
|
2749
3166
|
throw new Error("Invalid routine endpoint");
|
|
2750
3167
|
return fetch(target, { ...init2, redirect: "error" });
|
|
2751
3168
|
} : async () => {
|
|
2752
3169
|
throw new Error("Member publication requires a host-supplied request");
|
|
2753
3170
|
});
|
|
2754
|
-
async function
|
|
3171
|
+
async function send3(operation2, body2) {
|
|
2755
3172
|
if (local) return await local(operation2, body2);
|
|
2756
|
-
let
|
|
3173
|
+
let writing = operation2 === "records/update", reading = operation2 === "records/read", response2 = await request(writing || reading ? "/api/data" : `/api/inbox/${operation2}`, {
|
|
2757
3174
|
method: "POST",
|
|
2758
|
-
headers: {
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
3175
|
+
headers: {
|
|
3176
|
+
"content-type": "application/json",
|
|
3177
|
+
...headers,
|
|
3178
|
+
...writing || reading ? { "x-oddington-workspace": workspace, "x-oddington-captured-records": "1" } : {}
|
|
3179
|
+
},
|
|
3180
|
+
body: JSON.stringify(writing ? routineDataEnvelope(validateRoutineRecordWrite(body2)) : reading ? { operation: "records.select", request: validateRecordRead(body2) } : body2)
|
|
3181
|
+
}), result2 = await response2.json();
|
|
3182
|
+
if (!response2.ok && operation2 === "records/update")
|
|
2762
3183
|
throw new RoutineRecordWriteError(result2.error ?? "Could not confirm routine preparation", result2.effect ?? "uncertain");
|
|
2763
|
-
if (!
|
|
3184
|
+
if (!response2.ok) throw new Error(result2.error ?? "Could not confirm routine publication");
|
|
2764
3185
|
return result2;
|
|
2765
3186
|
}
|
|
2766
3187
|
let transport = {
|
|
2767
3188
|
async publish(body2) {
|
|
2768
|
-
return await
|
|
3189
|
+
return await send3("publish", body2);
|
|
2769
3190
|
},
|
|
2770
3191
|
async resolve(body2) {
|
|
2771
|
-
await
|
|
3192
|
+
await send3("resolve", body2);
|
|
2772
3193
|
}
|
|
2773
3194
|
};
|
|
2774
3195
|
async function readRecords(input) {
|
|
2775
|
-
return await
|
|
3196
|
+
return await send3("records/read", validateRecordRead(input));
|
|
2776
3197
|
}
|
|
2777
3198
|
return {
|
|
2778
3199
|
...createInboxPublisher(transport),
|
|
@@ -2780,16 +3201,16 @@ function routinePublicationClient2(options = {}) {
|
|
|
2780
3201
|
repository: {
|
|
2781
3202
|
readRecords,
|
|
2782
3203
|
async writeRecords(input, options2) {
|
|
2783
|
-
if (!capability) throw new Error("A trusted routine launch is required");
|
|
2784
|
-
return await
|
|
3204
|
+
if (!capability && !installed2) throw new Error("A trusted routine launch is required");
|
|
3205
|
+
return await send3("records/update", validateRoutineRecordWrite({ input, requestKey: options2?.requestKey }));
|
|
2785
3206
|
},
|
|
2786
3207
|
async updateRecords(input, options2) {
|
|
2787
|
-
if (!capability) throw new Error("A trusted routine launch is required");
|
|
2788
|
-
return await
|
|
3208
|
+
if (!capability && !installed2) throw new Error("A trusted routine launch is required");
|
|
3209
|
+
return await send3("records/update", validateRoutineRecordWrite({ input: validateRecordUpdate(input), requestKey: options2?.requestKey }));
|
|
2789
3210
|
},
|
|
2790
3211
|
async deleteRecords(input, options2) {
|
|
2791
|
-
if (!capability) throw new Error("A trusted routine launch is required");
|
|
2792
|
-
return await
|
|
3212
|
+
if (!capability && !installed2) throw new Error("A trusted routine launch is required");
|
|
3213
|
+
return await send3("records/update", validateRoutineRecordWrite({ input: validateRecordDelete(input), requestKey: options2?.requestKey }));
|
|
2793
3214
|
}
|
|
2794
3215
|
},
|
|
2795
3216
|
files: {
|
|
@@ -2800,7 +3221,7 @@ function routinePublicationClient2(options = {}) {
|
|
|
2800
3221
|
}
|
|
2801
3222
|
},
|
|
2802
3223
|
async check(body2) {
|
|
2803
|
-
await
|
|
3224
|
+
await send3("check", { requestKey: body2.requestKey, item: validatePublication(body2.item) });
|
|
2804
3225
|
}
|
|
2805
3226
|
};
|
|
2806
3227
|
}
|
|
@@ -2811,6 +3232,7 @@ export {
|
|
|
2811
3232
|
DataOperationError,
|
|
2812
3233
|
FileOperationError,
|
|
2813
3234
|
InboxContractError,
|
|
3235
|
+
InboxOperationError,
|
|
2814
3236
|
RoutineRecordWriteError,
|
|
2815
3237
|
app,
|
|
2816
3238
|
appRun,
|
|
@@ -2824,6 +3246,7 @@ export {
|
|
|
2824
3246
|
file,
|
|
2825
3247
|
fileBlock,
|
|
2826
3248
|
files,
|
|
3249
|
+
inbox,
|
|
2827
3250
|
os,
|
|
2828
3251
|
question,
|
|
2829
3252
|
recordBlock,
|