@oddington/sdk 0.1.22 → 0.1.23
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/dist/browser.js +259 -150
- package/dist/index.js +4 -4
- package/dist/types/packages/sdk/src/public.d.ts +3 -1
- package/dist/types/packages/sdk/src/routine-definition-types.d.ts +12 -2
- package/dist/types/shared/airtable-contract.d.ts +1 -0
- package/dist/types/shared/app-descriptor.d.ts +3 -0
- package/dist/types/shared/app-routine-contract.d.ts +1 -0
- package/dist/types/shared/connection-runtime.d.ts +20 -0
- package/dist/types/shared/inbox-contract.d.ts +9 -1
- package/dist/types/shared/inbox-member-types.d.ts +15 -2
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -285,7 +285,7 @@ function validatePublication(value) {
|
|
|
285
285
|
"views",
|
|
286
286
|
"body",
|
|
287
287
|
"notifyImmediately",
|
|
288
|
-
...source.kind === "ask" ? ["questions"] : []
|
|
288
|
+
...source.kind === "ask" ? ["questions", "tags", "recordRefs"] : []
|
|
289
289
|
], "publication"), source.notifyImmediately !== void 0 && typeof source.notifyImmediately != "boolean" && fail("notifyImmediately must be a boolean");
|
|
290
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 {
|
|
@@ -297,10 +297,24 @@ function validatePublication(value) {
|
|
|
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);
|
|
300
|
-
|
|
300
|
+
!questions.length && !extra.length && fail("Ask requires at least one recipient");
|
|
301
|
+
let tags = array(source.tags === void 0 ? [] : source.tags, "Ask tags").map((value2) => {
|
|
302
|
+
let tag = text(value2, "Ask tag");
|
|
303
|
+
return new TextEncoder().encode(tag).byteLength > 64 && fail("Ask tag exceeds 64 UTF-8 bytes"), tag;
|
|
304
|
+
});
|
|
305
|
+
(tags.length > 32 || new Set(tags).size !== tags.length) && fail("Ask tags exceed bounds or contain duplicates");
|
|
306
|
+
let recordRefs = array(source.recordRefs === void 0 ? [] : source.recordRefs, "Ask Record references").map((value2) => {
|
|
307
|
+
let row = object(value2, "Ask Record reference");
|
|
308
|
+
keys(row, ["repository", "id"], "Ask Record reference");
|
|
309
|
+
let { repository, ref } = validateRecordReference({ repository: row.repository, ref: row.id });
|
|
310
|
+
return { repository, id: ref };
|
|
311
|
+
});
|
|
312
|
+
return new Set(recordRefs.map((ref) => JSON.stringify([ref.repository, ref.id]))).size !== recordRefs.length && fail("Ask Record references contain duplicates"), {
|
|
301
313
|
kind: "ask",
|
|
302
314
|
...itemPresentation,
|
|
303
315
|
questions,
|
|
316
|
+
tags,
|
|
317
|
+
recordRefs,
|
|
304
318
|
recipients: [.../* @__PURE__ */ new Set([...extra, ...questions.flatMap((entry) => [entry.to, ...entry.allowedResponders])])]
|
|
305
319
|
};
|
|
306
320
|
}
|
|
@@ -335,7 +349,7 @@ function createInboxPublisher(transport) {
|
|
|
335
349
|
return {
|
|
336
350
|
async publishAsk(value, options) {
|
|
337
351
|
let source = object(value, "ask");
|
|
338
|
-
keys(source, ["title", "description", "recipients", "views", "body", "questions", "notifyImmediately"], "ask");
|
|
352
|
+
keys(source, ["title", "description", "recipients", "views", "body", "questions", "notifyImmediately", "tags", "recordRefs"], "ask");
|
|
339
353
|
let result2 = await transport.publish({
|
|
340
354
|
requestKey: publicationRequestKey(options),
|
|
341
355
|
item: validatePublication({ ...source, kind: "ask" })
|
|
@@ -517,8 +531,9 @@ function parseAppRoutineContract(value) {
|
|
|
517
531
|
case "array":
|
|
518
532
|
return !fields2(value2, ["type", "items", "maxItems"]) || !Number.isSafeInteger(value2.maxItems) || value2.maxItems < 1 || value2.maxItems > 64 ? invalidContract() : { type: "array", items: schema2(value2.items, depth + 1), maxItems: value2.maxItems };
|
|
519
533
|
case "boolean":
|
|
520
|
-
case "file":
|
|
521
534
|
return fields2(value2, ["type"]) ? { type: value2.type } : invalidContract();
|
|
535
|
+
case "file":
|
|
536
|
+
return !fields2(value2, ["type"], ["storage"]) || owns(value2, "storage") && value2.storage !== "local" && value2.storage !== "remote" ? invalidContract() : { type: "file", ...owns(value2, "storage") ? { storage: value2.storage } : {} };
|
|
522
537
|
case "string":
|
|
523
538
|
return !fields2(value2, ["type"], ["maxLength"]) || owns(value2, "maxLength") && (!Number.isSafeInteger(value2.maxLength) || value2.maxLength < 0 || value2.maxLength > 4096) ? invalidContract() : { type: "string", ...owns(value2, "maxLength") ? { maxLength: value2.maxLength } : {} };
|
|
524
539
|
case "integer":
|
|
@@ -716,7 +731,7 @@ var schema = {
|
|
|
716
731
|
boolean() {
|
|
717
732
|
return declaration({ type: "boolean" });
|
|
718
733
|
}
|
|
719
|
-
}, file = () => declaration({ type: "file" }), definitions = /* @__PURE__ */ new WeakMap(), defineRoutine = (definition) => {
|
|
734
|
+
}, file = (options = {}) => (assertRoutineFields(options, ["storage"]), declaration({ type: "file", ...options })), definitions = /* @__PURE__ */ new WeakMap(), defineRoutine = (definition) => {
|
|
720
735
|
if (assertRoutineFields(definition, ["id", "title", "input", "steps", "result", "access", "responses", "run"]), !isAppRoutineName(definition.id) || definition.title !== void 0 && !routineTitle(definition.title) || typeof definition.run != "function") return invalidContract3();
|
|
721
736
|
let input = definition.input === void 0 ? { schema: empty, default: {} } : schemaMetadata(definition.input), result2 = definition.result === void 0 ? void 0 : schemaMetadata(definition.result).schema, access = parseRoutineAccess(definition.access);
|
|
722
737
|
assertRoutineFields(definition.steps ?? {});
|
|
@@ -795,6 +810,12 @@ async function executeRoutineDefinition(definition, input, runtime) {
|
|
|
795
810
|
...guarded({
|
|
796
811
|
...runtime,
|
|
797
812
|
run: freezeRoutineMetadata({ ...runtime.run }),
|
|
813
|
+
connections: { ...runtime.connections, get: async (identity) => {
|
|
814
|
+
if (!active2 || broken || !contract.access.connections?.includes(identity)) throw new Error("Connection unavailable");
|
|
815
|
+
let value = await runtime.connections.get(identity);
|
|
816
|
+
if (!active2 || broken) throw new Error("Run authority ended");
|
|
817
|
+
return value;
|
|
818
|
+
} },
|
|
798
819
|
inbox: { ...runtime.inbox, publishAsk: (value, options) => runtime.inbox.publishAsk(qualify(value), options) }
|
|
799
820
|
}),
|
|
800
821
|
step(id3, ...input2) {
|
|
@@ -1029,16 +1050,16 @@ function routineTransport() {
|
|
|
1029
1050
|
return installed;
|
|
1030
1051
|
}
|
|
1031
1052
|
|
|
1032
|
-
var memberContext;
|
|
1033
|
-
function installMemberContext(resolve) {
|
|
1034
|
-
return memberContext = resolve, () => {
|
|
1035
|
-
memberContext === resolve && (memberContext = void 0);
|
|
1053
|
+
var memberContext, retainedContext;
|
|
1054
|
+
function installMemberContext(resolve, retained = resolve) {
|
|
1055
|
+
return memberContext = resolve, retainedContext = retained, () => {
|
|
1056
|
+
memberContext === resolve && (memberContext = void 0, retainedContext = void 0);
|
|
1036
1057
|
};
|
|
1037
1058
|
}
|
|
1038
|
-
async function resolveAppContext() {
|
|
1059
|
+
async function resolveAppContext(retained = !1) {
|
|
1039
1060
|
let host = memberContext;
|
|
1040
1061
|
if (!host) throw new Error("App context unavailable.");
|
|
1041
|
-
let context2 = await host();
|
|
1062
|
+
let context2 = await (retained ? retainedContext : host)();
|
|
1042
1063
|
if (host !== memberContext || !context2.isCurrent() || context2.expiresAt <= Date.now() || context2.kind !== "local" && (typeof context2.accessToken != "string" || !/^[^\s]{1,8192}$/.test(context2.accessToken)))
|
|
1043
1064
|
throw new Error("App context unavailable.");
|
|
1044
1065
|
return context2;
|
|
@@ -1063,13 +1084,22 @@ async function resolveFilesContext() {
|
|
|
1063
1084
|
let environment = {}, host = memberContext;
|
|
1064
1085
|
if (host) {
|
|
1065
1086
|
let context2 = await host();
|
|
1066
|
-
if (context2.
|
|
1087
|
+
if (host !== memberContext || !context2.isCurrent() || context2.expiresAt <= Date.now()) throw new Error();
|
|
1088
|
+
if (context2.kind === "local") return {
|
|
1089
|
+
url: `private:app:${context2.workspace}/${context2.memberId}`,
|
|
1090
|
+
headers: {},
|
|
1091
|
+
isCurrent: context2.isCurrent,
|
|
1092
|
+
signal: context2.signal,
|
|
1093
|
+
local: void 0,
|
|
1094
|
+
localFiles: context2.requestFiles
|
|
1095
|
+
};
|
|
1067
1096
|
if (!Number.isFinite(context2.expiresAt) || context2.expiresAt <= Date.now() || typeof context2.accessToken != "string" || !/^[^\s]{1,8192}$/.test(context2.accessToken)) throw new Error();
|
|
1068
1097
|
return {
|
|
1069
1098
|
...filesContext(context2.workspace, context2.endpoint, { authorization: `Bearer ${context2.accessToken}` }),
|
|
1070
1099
|
isCurrent: context2.isCurrent,
|
|
1071
1100
|
local: void 0,
|
|
1072
|
-
localFiles: void 0
|
|
1101
|
+
localFiles: void 0,
|
|
1102
|
+
signal: void 0
|
|
1073
1103
|
};
|
|
1074
1104
|
}
|
|
1075
1105
|
throw new Error();
|
|
@@ -1182,6 +1212,64 @@ var data = {
|
|
|
1182
1212
|
}
|
|
1183
1213
|
};
|
|
1184
1214
|
|
|
1215
|
+
async function hostedContent(url, init2, parent, upstream = fetch, check = async () => {
|
|
1216
|
+
}, failure) {
|
|
1217
|
+
let delivery = new AbortController(), abort = () => delivery.abort(parent.reason);
|
|
1218
|
+
parent.addEventListener("abort", abort, { once: !0 }), parent.aborted && abort();
|
|
1219
|
+
let detach = () => parent.removeEventListener("abort", abort);
|
|
1220
|
+
try {
|
|
1221
|
+
let response2 = await upstream(url, { ...init2, signal: delivery.signal });
|
|
1222
|
+
try {
|
|
1223
|
+
if (await check(), delivery.signal.aborted) throw failure?.() ?? new FileOperationError("unavailable", 503, !0);
|
|
1224
|
+
} catch (error) {
|
|
1225
|
+
throw response2.body?.cancel().catch(() => {
|
|
1226
|
+
}), error;
|
|
1227
|
+
}
|
|
1228
|
+
if (!response2.body)
|
|
1229
|
+
return detach(), response2;
|
|
1230
|
+
let source = response2.body, reader, settled = !1, output, cancel = async (reason) => {
|
|
1231
|
+
if (!settled) {
|
|
1232
|
+
settled = !0, detach(), delivery.signal.removeEventListener("abort", stop), delivery.abort(reason);
|
|
1233
|
+
try {
|
|
1234
|
+
await (reader ? reader.cancel(reason) : source.cancel(reason));
|
|
1235
|
+
} catch (error) {
|
|
1236
|
+
if (error !== delivery.signal.reason && !(error instanceof Error && error.name === "AbortError")) throw error;
|
|
1237
|
+
} finally {
|
|
1238
|
+
reader?.releaseLock();
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
}, stop = () => {
|
|
1242
|
+
if (settled) return;
|
|
1243
|
+
let error = failure?.() ?? delivery.signal.reason;
|
|
1244
|
+
cancel(error).catch(() => {
|
|
1245
|
+
}), output.error(error);
|
|
1246
|
+
}, body = new ReadableStream({
|
|
1247
|
+
start(controller) {
|
|
1248
|
+
output = controller, delivery.signal.addEventListener("abort", stop, { once: !0 }), delivery.signal.aborted && stop();
|
|
1249
|
+
},
|
|
1250
|
+
async pull(controller) {
|
|
1251
|
+
try {
|
|
1252
|
+
if (await check(), settled) return;
|
|
1253
|
+
reader ??= source.getReader();
|
|
1254
|
+
let { done, value } = await reader.read();
|
|
1255
|
+
if (await check(), settled) return;
|
|
1256
|
+
done ? (settled = !0, detach(), delivery.signal.removeEventListener("abort", stop), reader.releaseLock(), controller.close()) : controller.enqueue(value);
|
|
1257
|
+
} catch (error) {
|
|
1258
|
+
if (settled) return;
|
|
1259
|
+
controller.error(failure?.() ?? error), await cancel(error).catch(() => {
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
},
|
|
1263
|
+
cancel
|
|
1264
|
+
}, { highWaterMark: 0 }), wrapped = new Response(body, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
|
|
1265
|
+
for (let key of ["url", "redirected", "type"])
|
|
1266
|
+
Object.defineProperty(wrapped, key, { value: response2[key] });
|
|
1267
|
+
return wrapped;
|
|
1268
|
+
} catch (error) {
|
|
1269
|
+
throw detach(), delivery.abort(error), error;
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1185
1273
|
var MAX_BYTES = 16 * 1024 * 1024, PART_BYTES = 8 * 1024 * 1024, METADATA_BYTES = 4096, RESULT_BYTES = 16 * 1024, CONTROL_RESULT_BYTES = 128 * 1024, TIMEOUT_MS = 3e4, MAX_ACTIVE = 4, ATTEMPTS = 2, active = 0, invalid6 = () => new FileOperationError("invalid_input", 400), unavailable = () => new FileOperationError("unavailable", 503, !0), failures = {
|
|
1186
1274
|
400: ["invalid_input", "unsupported_context"],
|
|
1187
1275
|
401: ["unauthenticated"],
|
|
@@ -1192,19 +1280,26 @@ var MAX_BYTES = 16 * 1024 * 1024, PART_BYTES = 8 * 1024 * 1024, METADATA_BYTES =
|
|
|
1192
1280
|
429: ["capacity"],
|
|
1193
1281
|
503: ["integrity", "unavailable"]
|
|
1194
1282
|
};
|
|
1195
|
-
async function boundedBytes(stream, limit) {
|
|
1283
|
+
async function boundedBytes(stream, limit, signal) {
|
|
1196
1284
|
if (!stream) return new Uint8Array();
|
|
1197
|
-
let reader = stream.getReader(), bytes = new Uint8Array(limit), size = 0
|
|
1285
|
+
let reader = stream.getReader(), bytes = new Uint8Array(limit), size = 0, cancel = () => {
|
|
1286
|
+
reader.cancel().catch(() => {
|
|
1287
|
+
});
|
|
1288
|
+
};
|
|
1289
|
+
signal?.addEventListener("abort", cancel, { once: !0 }), signal?.aborted && cancel();
|
|
1198
1290
|
try {
|
|
1199
1291
|
for (; ; ) {
|
|
1200
1292
|
let { done, value } = await reader.read();
|
|
1293
|
+
if (signal?.aborted) throw unavailable();
|
|
1201
1294
|
if (done) break;
|
|
1202
1295
|
if (!(value instanceof Uint8Array)) throw invalid6();
|
|
1203
1296
|
if (size += value.byteLength, size > limit) throw new FileOperationError("request_too_large", 413);
|
|
1204
1297
|
bytes.set(value, size - value.byteLength);
|
|
1205
1298
|
}
|
|
1299
|
+
} catch (error) {
|
|
1300
|
+
throw cancel(), error;
|
|
1206
1301
|
} finally {
|
|
1207
|
-
reader.releaseLock();
|
|
1302
|
+
signal?.removeEventListener("abort", cancel), reader.releaseLock();
|
|
1208
1303
|
}
|
|
1209
1304
|
return bytes.slice(0, size);
|
|
1210
1305
|
}
|
|
@@ -1228,50 +1323,6 @@ async function result(response2, maximum = RESULT_BYTES) {
|
|
|
1228
1323
|
throw unavailable();
|
|
1229
1324
|
}
|
|
1230
1325
|
}
|
|
1231
|
-
async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
1232
|
-
let delivery = new AbortController(), abort = () => delivery.abort(parent.reason);
|
|
1233
|
-
parent.addEventListener("abort", abort, { once: !0 }), parent.aborted && abort();
|
|
1234
|
-
let detach = () => parent.removeEventListener("abort", abort);
|
|
1235
|
-
try {
|
|
1236
|
-
let response2 = await upstream(url, { ...init2, signal: delivery.signal });
|
|
1237
|
-
if (delivery.signal.aborted)
|
|
1238
|
-
throw response2.body?.cancel().catch(() => {
|
|
1239
|
-
}), unavailable();
|
|
1240
|
-
if (!response2.body)
|
|
1241
|
-
return detach(), response2;
|
|
1242
|
-
let source = response2.body, reader, settled = !1, cancel = async (reason) => {
|
|
1243
|
-
if (!settled) {
|
|
1244
|
-
settled = !0, detach(), delivery.abort(reason);
|
|
1245
|
-
try {
|
|
1246
|
-
await (reader ? reader.cancel(reason) : source.cancel(reason));
|
|
1247
|
-
} catch (error) {
|
|
1248
|
-
if (error !== delivery.signal.reason && !(error instanceof Error && error.name === "AbortError")) throw error;
|
|
1249
|
-
} finally {
|
|
1250
|
-
reader?.releaseLock();
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
}, body = new ReadableStream({
|
|
1254
|
-
async pull(controller) {
|
|
1255
|
-
try {
|
|
1256
|
-
reader ??= source.getReader();
|
|
1257
|
-
let { done, value } = await reader.read();
|
|
1258
|
-
if (settled) return;
|
|
1259
|
-
done ? (settled = !0, detach(), reader.releaseLock(), controller.close()) : controller.enqueue(value);
|
|
1260
|
-
} catch (error) {
|
|
1261
|
-
if (settled) return;
|
|
1262
|
-
controller.error(error), await cancel(error).catch(() => {
|
|
1263
|
-
});
|
|
1264
|
-
}
|
|
1265
|
-
},
|
|
1266
|
-
cancel
|
|
1267
|
-
}, { highWaterMark: 0 }), wrapped = new Response(body, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
|
|
1268
|
-
for (let key of ["url", "redirected", "type"])
|
|
1269
|
-
Object.defineProperty(wrapped, key, { value: response2[key] });
|
|
1270
|
-
return wrapped;
|
|
1271
|
-
} catch (error) {
|
|
1272
|
-
throw detach(), delivery.abort(error), error;
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
1326
|
async function send(suffix, init2, descriptor, initial, parent) {
|
|
1276
1327
|
let original = initial, checkCurrent = (context2 = original) => {
|
|
1277
1328
|
if (parent?.aborted) throw unavailable();
|
|
@@ -1282,7 +1333,7 @@ async function send(suffix, init2, descriptor, initial, parent) {
|
|
|
1282
1333
|
let context2 = await resolveFilesContext();
|
|
1283
1334
|
checkCurrent(context2);
|
|
1284
1335
|
try {
|
|
1285
|
-
let response2 = await (async () => {
|
|
1336
|
+
let response2 = context2.localFiles ? await context2.localFiles(suffix, init2, parent) : await (async () => {
|
|
1286
1337
|
let url = `${context2.url}${suffix}`, request2 = {
|
|
1287
1338
|
...init2,
|
|
1288
1339
|
signal: parent,
|
|
@@ -1419,13 +1470,15 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1419
1470
|
async function operation(work, initial, parent) {
|
|
1420
1471
|
let context2 = initial ?? await resolveFilesContext();
|
|
1421
1472
|
if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
|
|
1422
|
-
|
|
1473
|
+
active++;
|
|
1474
|
+
let execute = async (signal2) => {
|
|
1423
1475
|
try {
|
|
1424
|
-
return await work(context2,
|
|
1476
|
+
return await work(context2, signal2);
|
|
1425
1477
|
} finally {
|
|
1426
1478
|
active--;
|
|
1427
1479
|
}
|
|
1428
|
-
}, parent
|
|
1480
|
+
}, signal = context2.signal && parent ? AbortSignal.any([context2.signal, parent]) : context2.signal ?? parent;
|
|
1481
|
+
return context2.localFiles ? execute(signal ?? new AbortController().signal) : timed(execute, signal).catch((error) => {
|
|
1429
1482
|
throw error instanceof FileOperationError ? error : unavailable();
|
|
1430
1483
|
});
|
|
1431
1484
|
}
|
|
@@ -1497,15 +1550,36 @@ var files = {
|
|
|
1497
1550
|
...blob && input.file.type === "application/pdf" ? { inputMediaType: "application/pdf" } : {},
|
|
1498
1551
|
requestKey: options?.requestKey === void 0 ? routineTransport()?.key("files") ?? crypto.randomUUID() : options.requestKey
|
|
1499
1552
|
}, FILE_ORIGINAL_MAX_BYTES);
|
|
1500
|
-
if (!context2.local && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
|
|
1553
|
+
if (!context2.local && !context2.localFiles && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
|
|
1501
1554
|
let header = encodeURIComponent(JSON.stringify(metadata));
|
|
1502
1555
|
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid6();
|
|
1503
1556
|
if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
|
|
1504
|
-
|
|
1557
|
+
if (active++, context2.localFiles && !routineTransport() && metadata.size > MAX_BYTES) {
|
|
1558
|
+
let signal = context2.signal ?? new AbortController().signal, file2 = input.file, offset = 0, body = file2 instanceof Blob ? context2.signal ? file2 : file2.stream() : file2 instanceof ReadableStream ? file2 : new ReadableStream({
|
|
1559
|
+
pull(controller) {
|
|
1560
|
+
if (offset === file2.byteLength) {
|
|
1561
|
+
controller.close();
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
let end = Math.min(offset + 256 * 1024, file2.byteLength);
|
|
1565
|
+
controller.enqueue(file2.subarray(offset, end)), offset = end;
|
|
1566
|
+
}
|
|
1567
|
+
}, { highWaterMark: 0 });
|
|
1568
|
+
try {
|
|
1569
|
+
return await send("", { method: "POST", headers: {
|
|
1570
|
+
"content-type": "application/octet-stream",
|
|
1571
|
+
"x-oddington-file": header
|
|
1572
|
+
}, body }, !0, context2, signal);
|
|
1573
|
+
} finally {
|
|
1574
|
+
active--;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
return 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) => {
|
|
1505
1578
|
try {
|
|
1506
1579
|
let bytes = array3 ? input.file.slice() : await boundedBytes(
|
|
1507
1580
|
blob ? input.file.stream() : input.file,
|
|
1508
|
-
metadata.size
|
|
1581
|
+
metadata.size,
|
|
1582
|
+
signal
|
|
1509
1583
|
);
|
|
1510
1584
|
if (bytes.byteLength !== metadata.size) throw invalid6();
|
|
1511
1585
|
if (signal.aborted) throw unavailable();
|
|
@@ -1517,7 +1591,7 @@ var files = {
|
|
|
1517
1591
|
} finally {
|
|
1518
1592
|
active--;
|
|
1519
1593
|
}
|
|
1520
|
-
}).catch((error) => {
|
|
1594
|
+
}, context2.signal).catch((error) => {
|
|
1521
1595
|
throw error instanceof FileOperationError ? error : unavailable();
|
|
1522
1596
|
});
|
|
1523
1597
|
},
|
|
@@ -1561,6 +1635,24 @@ function validGoogleScopes(value) {
|
|
|
1561
1635
|
|
|
1562
1636
|
var ROUTINE_CONNECTION_CREDENTIALS_ENV = "ODDINGTON_ROUTINE_CONNECTION_CREDENTIALS";
|
|
1563
1637
|
var connectionUuid = (v) => typeof v == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(v);
|
|
1638
|
+
function runtimeConnection(lease) {
|
|
1639
|
+
return lease.provider === "gmail" ? {
|
|
1640
|
+
id: `gmail/${lease.name}`,
|
|
1641
|
+
provider: lease.provider,
|
|
1642
|
+
name: lease.name,
|
|
1643
|
+
accountEmail: lease.accountEmail,
|
|
1644
|
+
scopes: [...lease.scopes],
|
|
1645
|
+
accessToken: lease.accessToken,
|
|
1646
|
+
expiresAt: lease.expiresAt
|
|
1647
|
+
} : {
|
|
1648
|
+
id: `airtable/${lease.name}`,
|
|
1649
|
+
provider: lease.provider,
|
|
1650
|
+
name: lease.name,
|
|
1651
|
+
baseId: lease.baseId,
|
|
1652
|
+
accessToken: lease.accessToken,
|
|
1653
|
+
runExpiresAt: lease.runExpiresAt
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1564
1656
|
function parseConnectionLease(raw, now = Date.now()) {
|
|
1565
1657
|
let v = raw;
|
|
1566
1658
|
if (!v || typeof v != "object" || Array.isArray(v) || !connectionUuid(v.connectionId) || !connectionUuid(v.runId) || typeof v.name != "string" || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(v.name) || typeof v.accessToken != "string" || !/^[A-Za-z0-9._~+/-]{1,8192}={0,2}$/.test(v.accessToken))
|
|
@@ -1622,7 +1714,9 @@ function equal(a, b) {
|
|
|
1622
1714
|
));
|
|
1623
1715
|
}
|
|
1624
1716
|
function createConnections(transport) {
|
|
1625
|
-
return {
|
|
1717
|
+
return { async get() {
|
|
1718
|
+
throw new Error("Connection unavailable");
|
|
1719
|
+
}, airtable(name) {
|
|
1626
1720
|
(typeof name != "string" || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(name)) && fail2("Invalid Airtable connection name");
|
|
1627
1721
|
let call = (operation2, input) => transport(name, operation2, input);
|
|
1628
1722
|
return {
|
|
@@ -1804,46 +1898,19 @@ async function reportLocalRoutineEffect(value) {
|
|
|
1804
1898
|
await observer?.(value);
|
|
1805
1899
|
}
|
|
1806
1900
|
|
|
1807
|
-
var
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
if (installed2) return await installed2.request("airtable", { name, operation: operation2, input: serializable(input) });
|
|
1811
|
-
let managed = process.env[MANAGED_CONNECTION_CAPABILITY_ENV];
|
|
1812
|
-
if (managed) {
|
|
1813
|
-
let client = managedConnections(JSON.parse(managed)).airtable(name);
|
|
1814
|
-
return operation2 === "tables.list" ? await client.tables.list() : await client.records[operation2.slice(8)](input);
|
|
1815
|
-
}
|
|
1816
|
-
let raw = JSON.parse(process.env[ROUTINE_CONNECTION_CREDENTIALS_ENV] ?? "[]");
|
|
1817
|
-
if (!Array.isArray(raw)) throw new Error();
|
|
1818
|
-
let leases = raw.map((value) => parseConnectionLease(value));
|
|
1819
|
-
if (leases.some((lease2) => lease2.provider !== "airtable") || new Set(leases.map((lease2) => lease2.name)).size !== leases.length) throw new Error();
|
|
1820
|
-
let lease = leases.find((lease2) => lease2.name === name);
|
|
1821
|
-
if (!lease || lease.provider !== "airtable") throw new Error();
|
|
1822
|
-
let writing = ["records.create", "records.update", "records.delete"].includes(operation2), captured = serializable(input), result2;
|
|
1823
|
-
try {
|
|
1824
|
-
result2 = await executeAirtableOperation(lease, operation2, captured);
|
|
1825
|
-
} catch (error) {
|
|
1826
|
-
throw writing && error instanceof AirtableOperationError && await reportLocalRoutineEffect({
|
|
1827
|
-
type: "effect",
|
|
1828
|
-
connection: `airtable/${name}`,
|
|
1829
|
-
operation: operation2,
|
|
1830
|
-
input: captured,
|
|
1831
|
-
effect: error.effect,
|
|
1832
|
-
receipts: error.receipts
|
|
1833
|
-
}), error;
|
|
1834
|
-
}
|
|
1835
|
-
return writing && await reportLocalRoutineEffect({
|
|
1836
|
-
type: "effect",
|
|
1837
|
-
connection: `airtable/${name}`,
|
|
1838
|
-
operation: operation2,
|
|
1839
|
-
input: captured,
|
|
1840
|
-
effect: "confirmed",
|
|
1841
|
-
receipts: [result2.receipt]
|
|
1842
|
-
}), result2;
|
|
1843
|
-
} catch (error) {
|
|
1844
|
-
throw error instanceof AirtableOperationError ? error : new AirtableOperationError("Airtable connection unavailable");
|
|
1845
|
-
}
|
|
1901
|
+
var local;
|
|
1902
|
+
var airtable = /* @__PURE__ */ createConnections(async (name, operation2, input) => {
|
|
1903
|
+
throw new AirtableOperationError("Airtable connection unavailable");
|
|
1846
1904
|
});
|
|
1905
|
+
function runtimeConnections() {
|
|
1906
|
+
return {
|
|
1907
|
+
...airtable,
|
|
1908
|
+
async get(identity) {
|
|
1909
|
+
throw new Error("Connection unavailable");
|
|
1910
|
+
}
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
var connections = /* @__PURE__ */ runtimeConnections();
|
|
1847
1914
|
|
|
1848
1915
|
var LOCAL_ROUTINE_VALUE_BYTES = 256 * 1024;
|
|
1849
1916
|
|
|
@@ -2093,7 +2160,7 @@ function parseInboxCurrent(value) {
|
|
|
2093
2160
|
}
|
|
2094
2161
|
function parseInboxItem(value) {
|
|
2095
2162
|
let item = object4(json(value));
|
|
2096
|
-
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(object4(item.outcome).outcome)), "canonicalRoutineId" in item && assert(item.canonicalRoutineId === null || isAppRoutineName(item.canonicalRoutineId)), array2(item.body).forEach(block), array2(item.views).forEach((value2) => {
|
|
2163
|
+
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(object4(item.outcome).outcome)), "canonicalRoutineId" in item && assert(item.canonicalRoutineId === null || isAppRoutineName(item.canonicalRoutineId)), item.kind === "ask" ? askMetadata(item) : assert(!("tags" in item) && !("recordRefs" in item)), array2(item.body).forEach(block), array2(item.views).forEach((value2) => {
|
|
2097
2164
|
let view = object4(value2);
|
|
2098
2165
|
assert(text3(view.id) && text3(view.view) && text3(view.implementation)), json(view.input);
|
|
2099
2166
|
}), array2(item.people).forEach((value2) => {
|
|
@@ -2134,19 +2201,23 @@ function parseAnswerableQuestion(value) {
|
|
|
2134
2201
|
let entry = object4(json(value));
|
|
2135
2202
|
keys3(
|
|
2136
2203
|
entry,
|
|
2137
|
-
["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "recordRefs", "instructions"],
|
|
2138
|
-
["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable"
|
|
2204
|
+
["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "tags", "recordRefs", "instructions"],
|
|
2205
|
+
["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable"]
|
|
2139
2206
|
), assert(id2(entry.itemId) && integer(entry.revision) && text3(entry.title) && text3(entry.inboxUrl));
|
|
2140
2207
|
let link = new URL(entry.inboxUrl), slug = link.hostname.slice(0, -13);
|
|
2141
|
-
assert(link.hostname.endsWith(".oddington.ai") && slug.length <= 63 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug) && !["auth", "www", "api", "os"].includes(slug) && entry.inboxUrl === `https://${slug}.oddington.ai/inbox/${entry.itemId}`), assert(isAppRoutineName(entry.routine) && text3(entry.questionId) && entry.questionId === entry.questionId.trim() && text3(entry.prompt) && (!("instructions" in entry) || text3(entry.instructions, !0)) && typeof entry.answerable == "boolean"), responseDefinition(entry.response);
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2208
|
+
return assert(link.hostname.endsWith(".oddington.ai") && slug.length <= 63 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug) && !["auth", "www", "api", "os"].includes(slug) && entry.inboxUrl === `https://${slug}.oddington.ai/inbox/${entry.itemId}`), assert(isAppRoutineName(entry.routine) && text3(entry.questionId) && entry.questionId === entry.questionId.trim() && text3(entry.prompt) && (!("instructions" in entry) || text3(entry.instructions, !0)) && typeof entry.answerable == "boolean"), responseDefinition(entry.response), askMetadata(entry), entry;
|
|
2209
|
+
}
|
|
2210
|
+
function askMetadata(entry) {
|
|
2211
|
+
let tags = array2(entry.tags === void 0 ? [] : entry.tags);
|
|
2212
|
+
assert(tags.length <= 32 && tags.every((tag) => text3(tag) && new TextEncoder().encode(tag).byteLength <= 64)), assert(new Set(tags).size === tags.length);
|
|
2213
|
+
let refs = array2(entry.recordRefs === void 0 ? [] : entry.recordRefs);
|
|
2214
|
+
refs.forEach((value) => {
|
|
2215
|
+
let ref = object4(value);
|
|
2216
|
+
keys3(ref, ["repository", "id"]), recordReference({ repository: ref.repository, ref: ref.id });
|
|
2217
|
+
}), assert(new Set(refs.map((value) => {
|
|
2218
|
+
let ref = object4(value);
|
|
2148
2219
|
return JSON.stringify([ref.repository, ref.id]);
|
|
2149
|
-
})).size === refs.length), entry;
|
|
2220
|
+
})).size === refs.length), entry.tags = tags, entry.recordRefs = refs;
|
|
2150
2221
|
}
|
|
2151
2222
|
function parseInboxAcceptance(value) {
|
|
2152
2223
|
let accepted = object4(value);
|
|
@@ -2376,10 +2447,12 @@ function appContext(origin, active2) {
|
|
|
2376
2447
|
credentials: "omit",
|
|
2377
2448
|
redirect: "error",
|
|
2378
2449
|
cache: "no-store",
|
|
2450
|
+
...init2.body instanceof ReadableStream ? { duplex: "half" } : {},
|
|
2379
2451
|
referrerPolicy: "no-referrer",
|
|
2380
2452
|
signal,
|
|
2381
2453
|
headers: {
|
|
2382
2454
|
...init2.body === void 0 ? {} : { "content-type": "application/json" },
|
|
2455
|
+
...Object.fromEntries(new Headers(init2.headers)),
|
|
2383
2456
|
authorization: `Bearer ${candidate}`
|
|
2384
2457
|
}
|
|
2385
2458
|
});
|
|
@@ -2545,11 +2618,37 @@ function appContext(origin, active2) {
|
|
|
2545
2618
|
async function requestRoutine(key, suffix, init2 = {}) {
|
|
2546
2619
|
return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, init2);
|
|
2547
2620
|
}
|
|
2548
|
-
async function
|
|
2621
|
+
async function requestRetainedRoutine(key, suffix) {
|
|
2622
|
+
return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, {}, !1, !0);
|
|
2623
|
+
}
|
|
2624
|
+
async function requestFiles(suffix, init2, parent) {
|
|
2625
|
+
let unavailable3 = () => new FileOperationError("unsupported_context", 400);
|
|
2626
|
+
if (!current2() || !/^(?:|\/[0-9a-f-]{36}(?:\/(?:content|upload|enrichments(?:\/[^/?#]+\/content)?))?)$/i.test(suffix))
|
|
2627
|
+
throw unavailable3();
|
|
2628
|
+
let admitted = credential, signal = parent ? AbortSignal.any([access.signal, parent]) : access.signal, failure = () => current2() && !signal.aborted ? new FileOperationError("unavailable", 503, !0) : unavailable3();
|
|
2629
|
+
try {
|
|
2630
|
+
return await hostedContent("", init2, signal, (_url, request2) => untilAborted(
|
|
2631
|
+
send3(`files${suffix}`, admitted, signal, request2).then((value) => {
|
|
2632
|
+
if (signal.aborted)
|
|
2633
|
+
throw value.body?.cancel().catch(() => {
|
|
2634
|
+
}), unavailable3();
|
|
2635
|
+
return value;
|
|
2636
|
+
}),
|
|
2637
|
+
signal
|
|
2638
|
+
), () => settledAccess(signal), failure);
|
|
2639
|
+
} catch {
|
|
2640
|
+
throw failure();
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
async function requestChecked(path, init2, inbox2 = !1, retained2 = !1) {
|
|
2549
2644
|
if (!current2()) throw new Error("Local app context unavailable.");
|
|
2550
|
-
let admitted = credential, signal = access.signal, response2 = await send3(path, credential, signal, init2)
|
|
2551
|
-
|
|
2552
|
-
|
|
2645
|
+
let admitted = credential, signal = access.signal, response2 = await send3(path, credential, signal, init2), check = async () => {
|
|
2646
|
+
if (retained2) {
|
|
2647
|
+
if (signal.aborted || !current2()) throw new Error("Local app context unavailable.");
|
|
2648
|
+
} else await settledAccess(signal);
|
|
2649
|
+
};
|
|
2650
|
+
return await check(), (response2.status === 401 || !inbox2 && response2.status === 403) && admitted === credential && current2() && invalidate(), responseChecks.set(response2, async (value) => {
|
|
2651
|
+
await check(), admitted === credential && current2() && value && typeof value == "object" && "error" in value && value.error === "authority_unavailable" && invalidate();
|
|
2553
2652
|
}), response2;
|
|
2554
2653
|
}
|
|
2555
2654
|
function context2() {
|
|
@@ -2566,8 +2665,10 @@ function appContext(origin, active2) {
|
|
|
2566
2665
|
issued === credential && current2() && invalidate();
|
|
2567
2666
|
},
|
|
2568
2667
|
requestRoutine,
|
|
2668
|
+
requestRetainedRoutine,
|
|
2569
2669
|
requestData,
|
|
2570
2670
|
requestInbox,
|
|
2671
|
+
requestFiles,
|
|
2571
2672
|
requestAvailability: (key) => requestRoutine(key, "availability", { method: "GET" })
|
|
2572
2673
|
};
|
|
2573
2674
|
}
|
|
@@ -2576,22 +2677,22 @@ function appContext(origin, active2) {
|
|
|
2576
2677
|
try {
|
|
2577
2678
|
if (!alive()) throw new Error();
|
|
2578
2679
|
if (!pair) {
|
|
2579
|
-
let candidate2 = stored(),
|
|
2580
|
-
pair =
|
|
2680
|
+
let candidate2 = stored(), retained3 = readPair(candidate2);
|
|
2681
|
+
pair = retained3, binding = { ...retained3.context }, credential = retained3.credential, serialized = candidate2;
|
|
2581
2682
|
}
|
|
2582
2683
|
if (expireAccess(), binding.expiresAt <= Date.now()) {
|
|
2583
2684
|
if (await renew(), !current2()) throw new AppRenewalUnavailable();
|
|
2584
2685
|
return context2();
|
|
2585
2686
|
}
|
|
2586
2687
|
await synchronize();
|
|
2587
|
-
let candidate = stored(),
|
|
2688
|
+
let candidate = stored(), retained2 = readPair(candidate);
|
|
2588
2689
|
if (attempted = candidate ?? void 0, !current2()) throw new AppRenewalUnavailable();
|
|
2589
|
-
let value = await proof(
|
|
2690
|
+
let value = await proof(retained2.credential);
|
|
2590
2691
|
if (stored() !== candidate || serialized !== candidate)
|
|
2591
2692
|
return await synchronize(), context2();
|
|
2592
2693
|
if (!current2()) throw new Error();
|
|
2593
2694
|
if (expiry && binding && value.expiresAt > binding.expiresAt) throw new Error();
|
|
2594
|
-
return (!expiry || value.expiresAt !== binding.expiresAt) && install(value,
|
|
2695
|
+
return (!expiry || value.expiresAt !== binding.expiresAt) && install(value, retained2, candidate), context2();
|
|
2595
2696
|
} catch (error) {
|
|
2596
2697
|
if (alive() && error instanceof AppRenewalUnavailable)
|
|
2597
2698
|
throw new Error();
|
|
@@ -2606,7 +2707,12 @@ function appContext(origin, active2) {
|
|
|
2606
2707
|
}, resolve = () => resolution2 || (resolution2 = resolveOnce().finally(() => {
|
|
2607
2708
|
resolution2 = void 0;
|
|
2608
2709
|
}), resolution2);
|
|
2609
|
-
return { resolve,
|
|
2710
|
+
return { resolve, retained: async () => {
|
|
2711
|
+
if (!expiry && alive() && (binding ? current2() && resolution2 : readPair(stored()).context.expiresAt > Date.now()))
|
|
2712
|
+
return resolve();
|
|
2713
|
+
if (!expiry || !current2()) throw new Error("Local app context unavailable.");
|
|
2714
|
+
return context2();
|
|
2715
|
+
}, start: () => {
|
|
2610
2716
|
startup = setTimeout(() => {
|
|
2611
2717
|
alive() && !resolution2 && !binding && resolve().catch(() => {
|
|
2612
2718
|
});
|
|
@@ -2832,8 +2938,8 @@ function init({ auth: input }) {
|
|
|
2832
2938
|
url.protocol === "https:" && !url.port && !url.username && !url.password && !url.search && !url.hash && url.pathname === "/" && /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(slug) && slug !== "auth" && (endpoint = url.origin, workspace = slug);
|
|
2833
2939
|
} catch {
|
|
2834
2940
|
}
|
|
2835
|
-
let active2 = !0, revision = 0, person, token, binding = {},
|
|
2836
|
-
if (
|
|
2941
|
+
let active2 = !0, revision = 0, person, token, binding = {}, local3 = localOrigin ? appContext(localOrigin, () => active2) : void 0, subscription, stopDisposal, resolve = async () => {
|
|
2942
|
+
if (local3) return local3.resolve();
|
|
2837
2943
|
if (!active2 || !endpoint || !workspace || globalThis.location.origin !== endpoint) throw new Error("Hosted Data context unavailable.");
|
|
2838
2944
|
let started = revision, { data: { session }, error } = await auth2.getSession();
|
|
2839
2945
|
if (!active2 || globalThis.location.origin !== endpoint || started !== revision || error || !session || person !== void 0 && person !== session.user.id)
|
|
@@ -2852,13 +2958,13 @@ function init({ auth: input }) {
|
|
|
2852
2958
|
memberId: session.user.id,
|
|
2853
2959
|
binding
|
|
2854
2960
|
};
|
|
2855
|
-
}), dispose = () => {
|
|
2856
|
-
active2 && (active2 = !1,
|
|
2961
|
+
}, uninstall = installMemberContext(resolve, local3 ? local3.retained : resolve), dispose = () => {
|
|
2962
|
+
active2 && (active2 = !1, local3?.dispose(), revision++, subscription?.unsubscribe(), stopDisposal?.(), uninstall(), installedDispose === dispose && (installedDispose = void 0));
|
|
2857
2963
|
};
|
|
2858
2964
|
installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (subscription = auth2.onAuthStateChange((event, session) => {
|
|
2859
2965
|
let next = session?.user.id ?? null;
|
|
2860
|
-
(event === "SIGNED_OUT" || person !== void 0 && next !== person || registered && person !== void 0 && event === "SIGNED_IN" && token !== session?.access_token) && (revision++,
|
|
2861
|
-
}).data.subscription,
|
|
2966
|
+
(event === "SIGNED_OUT" || person !== void 0 && next !== person || registered && person !== void 0 && event === "SIGNED_IN" && token !== session?.access_token) && (revision++, local3?.invalidate()), person = next, token = session?.access_token;
|
|
2967
|
+
}).data.subscription, local3?.start());
|
|
2862
2968
|
}
|
|
2863
2969
|
var os = { init };
|
|
2864
2970
|
|
|
@@ -3303,16 +3409,16 @@ function current(context2) {
|
|
|
3303
3409
|
function appDescriptors() {
|
|
3304
3410
|
return globalThis[/* @__PURE__ */ Symbol.for("oddington.app.descriptor")]?.routines ?? [];
|
|
3305
3411
|
}
|
|
3306
|
-
async function
|
|
3307
|
-
let context2 = await resolveAppContext().catch(() => fail3("authority_unavailable"));
|
|
3412
|
+
async function local2(retained = !1) {
|
|
3413
|
+
let context2 = await resolveAppContext(retained).catch(() => fail3("authority_unavailable"));
|
|
3308
3414
|
return context2.kind !== "local" ? fail3("execution_unavailable") : (current(context2), context2);
|
|
3309
3415
|
}
|
|
3310
|
-
async function request(key, suffix, init2, maximum = SUMMARY_BYTES, retained) {
|
|
3416
|
+
async function request(key, suffix, init2, maximum = SUMMARY_BYTES, retained, read2 = !1) {
|
|
3311
3417
|
(!identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable");
|
|
3312
|
-
let context2 = retained ?? await
|
|
3418
|
+
let context2 = retained ?? await local2(read2);
|
|
3313
3419
|
current(context2);
|
|
3314
3420
|
try {
|
|
3315
|
-
let response2 = await context2.requestRoutine(key, suffix, init2), value = await appResponse(response2, maximum, context2.signal);
|
|
3421
|
+
let response2 = await (read2 ? context2.requestRetainedRoutine(key, suffix) : context2.requestRoutine(key, suffix, init2)), value = await appResponse(response2, maximum, context2.signal);
|
|
3316
3422
|
if (current(context2), !response2.ok) {
|
|
3317
3423
|
let reason = value?.error;
|
|
3318
3424
|
reason === "authority_unavailable" && (context2.invalidate(), fail3(reason)), (reason === "invalid_input" || reason === "execution_unavailable") && fail3(reason), fail3("execution_unavailable");
|
|
@@ -3358,11 +3464,15 @@ function structure(value) {
|
|
|
3358
3464
|
return JSON.stringify(value, (_key, item) => item && typeof item == "object" && !Array.isArray(item) ? Object.fromEntries(Object.keys(item).sort().map((key) => [key, item[key]])) : item);
|
|
3359
3465
|
}
|
|
3360
3466
|
function handle(key, id3, context2) {
|
|
3361
|
-
|
|
3362
|
-
|
|
3467
|
+
(!identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable"), (typeof id3 != "string" || !uuid.test(id3)) && fail3("invalid_input");
|
|
3468
|
+
let read2 = async () => summary(await request(key, `runs/${id3}`, void 0, SUMMARY_BYTES, context2, !0), key, id3);
|
|
3469
|
+
return routineRunHandle({
|
|
3470
|
+
async current() {
|
|
3471
|
+
return current(context2), read2();
|
|
3472
|
+
},
|
|
3363
3473
|
async step(step) {
|
|
3364
3474
|
(typeof step != "string" || !identifier.test(step)) && fail3("invalid_input");
|
|
3365
|
-
let value = await request(key, `runs/${id3}/steps/${step}`, void 0, 514 * 1024, context2);
|
|
3475
|
+
let value = await request(key, `runs/${id3}/steps/${step}`, void 0, 514 * 1024, context2, !0);
|
|
3366
3476
|
return (!only(value, "id,title,status,startedAt,finishedAt,summary,data") || value.id !== step || !validStep(value)) && fail3("execution_unavailable"), value;
|
|
3367
3477
|
},
|
|
3368
3478
|
async publish() {
|
|
@@ -3401,19 +3511,18 @@ function appRoutineBinding(key) {
|
|
|
3401
3511
|
} catch {
|
|
3402
3512
|
return fail3("invalid_input");
|
|
3403
3513
|
}
|
|
3404
|
-
let context2 = await
|
|
3514
|
+
let context2 = await local2(), run = summary(await request(key, "runs", { method: "POST", body: encoded }, SUMMARY_BYTES, context2), key);
|
|
3405
3515
|
return handle(key, run.id, context2);
|
|
3406
3516
|
},
|
|
3407
3517
|
runs: Object.freeze({
|
|
3408
3518
|
async list() {
|
|
3409
|
-
let value = await request(key, "runs", void 0, 20 * SUMMARY_BYTES);
|
|
3519
|
+
let value = await request(key, "runs", void 0, 20 * SUMMARY_BYTES, void 0, !0);
|
|
3410
3520
|
if (!Array.isArray(value) || value.length > 20) return fail3("execution_unavailable");
|
|
3411
3521
|
let runs = value.map((run) => summary(run, key));
|
|
3412
3522
|
return new Set(runs.map((run) => run.id)).size !== runs.length && fail3("execution_unavailable"), runs;
|
|
3413
3523
|
},
|
|
3414
3524
|
async get(id3) {
|
|
3415
|
-
|
|
3416
|
-
return await run.current(), run;
|
|
3525
|
+
return (typeof id3 != "string" || !uuid.test(id3)) && fail3("invalid_input"), (!identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable"), handle(key, id3, await local2(!0));
|
|
3417
3526
|
}
|
|
3418
3527
|
})
|
|
3419
3528
|
});
|
|
@@ -3460,7 +3569,7 @@ function routineDataEnvelope(command) {
|
|
|
3460
3569
|
}
|
|
3461
3570
|
|
|
3462
3571
|
function routinePublicationClient2(options = {}) {
|
|
3463
|
-
let environment = {}, installed2 = routineTransport(),
|
|
3572
|
+
let environment = {}, installed2 = routineTransport(), local3 = installed2?.request ?? void 0, workspace = installed2 ? "installed" : options.workspace ?? environment.ODDINGTON_ROUTINE_WORKSPACE, capability = options.capability ?? environment.ODDINGTON_ROUTINE_RUN;
|
|
3464
3573
|
if (!workspace || !/^[a-z0-9][a-z0-9-]*$/.test(workspace) || capability !== void 0 && !/^[0-9a-f]{64}$/.test(capability))
|
|
3465
3574
|
throw new Error("A workspace and valid optional routine capability are required");
|
|
3466
3575
|
let workingRoot = options.workingRoot ?? environment.ODDINGTON_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-oddington-run": capability } : {}, request2 = options.request ?? (capability ? async (path, init2) => {
|
|
@@ -3473,7 +3582,7 @@ function routinePublicationClient2(options = {}) {
|
|
|
3473
3582
|
throw new Error("Member publication requires a host-supplied request");
|
|
3474
3583
|
});
|
|
3475
3584
|
async function send3(operation2, body) {
|
|
3476
|
-
if (
|
|
3585
|
+
if (local3) return await local3(operation2, body);
|
|
3477
3586
|
let writing = operation2 === "records/update", reading = operation2 === "records/read", response2 = await request2(writing || reading ? "/api/data" : `/api/inbox/${operation2}`, {
|
|
3478
3587
|
method: "POST",
|
|
3479
3588
|
headers: {
|
|
@@ -3520,7 +3629,7 @@ function routinePublicationClient2(options = {}) {
|
|
|
3520
3629
|
files: {
|
|
3521
3630
|
async add(value) {
|
|
3522
3631
|
let input = validateFileAddOptions(value);
|
|
3523
|
-
if (
|
|
3632
|
+
if (local3) return validateInboxFile(await local3("files/add", input));
|
|
3524
3633
|
throw workingRoot ? new Error("Inbox file reads require a Node working root") : new Error("Inbox file reads require a working root");
|
|
3525
3634
|
}
|
|
3526
3635
|
},
|