@oddington/sdk 0.1.19 → 0.1.21
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 +87 -63
- package/dist/browser.js +584 -474
- package/dist/index.js +6 -6
- package/dist/types/packages/sdk/src/public.d.ts +87 -35
- package/dist/types/packages/sdk/src/routine-definition-types.d.ts +53 -19
- package/dist/types/shared/app-descriptor.d.ts +21 -0
- package/dist/types/shared/app-routine-contract.d.ts +1 -0
- package/dist/types/shared/inbox-contract.d.ts +5 -1
- package/dist/types/shared/inbox-member-contract.d.ts +2 -2
- package/dist/types/shared/inbox-member-types.d.ts +5 -1
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
var InboxContractError = class extends Error {
|
|
2
|
-
constructor(
|
|
3
|
-
super(
|
|
2
|
+
constructor(message2) {
|
|
3
|
+
super(message2), this.name = "InboxContractError";
|
|
4
4
|
}
|
|
5
5
|
};
|
|
6
|
-
function fail(
|
|
7
|
-
throw new InboxContractError(
|
|
6
|
+
function fail(message2) {
|
|
7
|
+
throw new InboxContractError(message2);
|
|
8
8
|
}
|
|
9
9
|
function object(value, label) {
|
|
10
10
|
return (!value || typeof value != "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) && fail(`${label} must be a plain object`), value;
|
|
@@ -12,8 +12,8 @@ function object(value, label) {
|
|
|
12
12
|
function keys(value, allowed, label) {
|
|
13
13
|
for (let key of Reflect.ownKeys(value)) {
|
|
14
14
|
(typeof key != "string" || !allowed.includes(key)) && fail(`${label} does not support ${String(key)}`);
|
|
15
|
-
let
|
|
16
|
-
(!
|
|
15
|
+
let descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
16
|
+
(!descriptor.enumerable || !("value" in descriptor)) && fail(`${label} must contain only JSON data`);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
function text(value, label) {
|
|
@@ -26,8 +26,8 @@ function id(value, label) {
|
|
|
26
26
|
function array(value, label) {
|
|
27
27
|
(!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype || Reflect.ownKeys(value).length !== value.length + 1) && fail(`${label} must be a dense array`);
|
|
28
28
|
for (let index = 0; index < value.length; index += 1) {
|
|
29
|
-
let
|
|
30
|
-
(!
|
|
29
|
+
let descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
30
|
+
(!descriptor?.enumerable || !("value" in descriptor)) && fail(`${label} must contain only JSON data`);
|
|
31
31
|
}
|
|
32
32
|
return value;
|
|
33
33
|
}
|
|
@@ -268,12 +268,12 @@ function presentation(source) {
|
|
|
268
268
|
return keys(view, ["id", "view", "input"], "view"), { id: id(view.id, "view ID"), view: id(view.view, "view name"), input: serializable(view.input) };
|
|
269
269
|
});
|
|
270
270
|
new Set(views.map((view) => view.id)).size !== views.length && fail("Duplicate view ID");
|
|
271
|
-
let
|
|
272
|
-
for (let block2 of
|
|
271
|
+
let body = source.body === void 0 ? [] : array(source.body, "body").map(validateBlock);
|
|
272
|
+
for (let block2 of body) {
|
|
273
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
|
-
return { title: text(source.title, "title"), description: text(source.description, "description"), views, body
|
|
276
|
+
return { title: text(source.title, "title"), description: text(source.description, "description"), views, body };
|
|
277
277
|
}
|
|
278
278
|
function validatePublication(value) {
|
|
279
279
|
let source = object(value, "publication");
|
|
@@ -391,44 +391,44 @@ var FileOperationError = class extends Error {
|
|
|
391
391
|
retryable;
|
|
392
392
|
}, FILE_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/, FILE_ORIGINAL_MAX_BYTES = 5 * 1024 ** 3;
|
|
393
393
|
function parseFileDescriptor(value) {
|
|
394
|
-
let
|
|
394
|
+
let invalid6 = () => {
|
|
395
395
|
throw new FileOperationError("unavailable", 503, !0);
|
|
396
396
|
};
|
|
397
|
-
if (!value || typeof value != "object" || Array.isArray(value)) return
|
|
397
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return invalid6();
|
|
398
398
|
let f = value;
|
|
399
|
-
if (Object.keys(f).sort().join(",") !== "details,enrichments,id,mediaType,name,path,sha256,size" || typeof f.id != "string" || !FILE_ID_PATTERN.test(f.id) || !safeFileName(f.name) || !safeFilePath(f.path) || !Number.isSafeInteger(f.size) || f.size < 0 || f.size > FILE_ORIGINAL_MAX_BYTES || typeof f.sha256 != "string" || !/^[0-9a-f]{64}$/.test(f.sha256) || !f.enrichments || typeof f.enrichments != "object" || Array.isArray(f.enrichments) || !f.details || typeof f.details != "object" || Array.isArray(f.details)) return
|
|
399
|
+
if (Object.keys(f).sort().join(",") !== "details,enrichments,id,mediaType,name,path,sha256,size" || typeof f.id != "string" || !FILE_ID_PATTERN.test(f.id) || !safeFileName(f.name) || !safeFilePath(f.path) || !Number.isSafeInteger(f.size) || f.size < 0 || f.size > FILE_ORIGINAL_MAX_BYTES || typeof f.sha256 != "string" || !/^[0-9a-f]{64}$/.test(f.sha256) || !f.enrichments || typeof f.enrichments != "object" || Array.isArray(f.enrichments) || !f.details || typeof f.details != "object" || Array.isArray(f.details)) return invalid6();
|
|
400
400
|
let d = f.details;
|
|
401
401
|
if (d.kind === "other") {
|
|
402
|
-
if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream") return
|
|
402
|
+
if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream") return invalid6();
|
|
403
403
|
} else if (d.kind === "csv") {
|
|
404
|
-
if (Object.keys(d).sort().join(",") !== "dataRows,delimiter,encoding,headerRow,kind" || f.mediaType !== "text/csv" || !["utf-8", "windows-1252"].includes(d.encoding) || ![",", ";", " "].includes(d.delimiter) || !Number.isSafeInteger(d.headerRow) || d.headerRow < 1 || !Number.isSafeInteger(d.dataRows) || d.dataRows < 0) return
|
|
404
|
+
if (Object.keys(d).sort().join(",") !== "dataRows,delimiter,encoding,headerRow,kind" || f.mediaType !== "text/csv" || !["utf-8", "windows-1252"].includes(d.encoding) || ![",", ";", " "].includes(d.delimiter) || !Number.isSafeInteger(d.headerRow) || d.headerRow < 1 || !Number.isSafeInteger(d.dataRows) || d.dataRows < 0) return invalid6();
|
|
405
405
|
} else if (d.kind === "pdf") {
|
|
406
|
-
if (f.mediaType !== "application/pdf" || Object.keys(d).some((key) => !["kind", "pages"].includes(key)) || "pages" in d && (!Number.isSafeInteger(d.pages) || d.pages < 1)) return
|
|
407
|
-
} else return
|
|
408
|
-
for (let [name,
|
|
409
|
-
if (!safeEnrichmentName(name)) return
|
|
410
|
-
parseEnrichmentDescriptor(
|
|
406
|
+
if (f.mediaType !== "application/pdf" || Object.keys(d).some((key) => !["kind", "pages"].includes(key)) || "pages" in d && (!Number.isSafeInteger(d.pages) || d.pages < 1)) return invalid6();
|
|
407
|
+
} else return invalid6();
|
|
408
|
+
for (let [name, descriptor] of Object.entries(f.enrichments)) {
|
|
409
|
+
if (!safeEnrichmentName(name)) return invalid6();
|
|
410
|
+
parseEnrichmentDescriptor(descriptor);
|
|
411
411
|
}
|
|
412
|
-
return new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024 ?
|
|
412
|
+
return new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024 ? invalid6() : f;
|
|
413
413
|
}
|
|
414
414
|
function parseEnrichmentDescriptor(value) {
|
|
415
|
-
let
|
|
415
|
+
let invalid6 = () => {
|
|
416
416
|
throw new FileOperationError("unavailable", 503, !0);
|
|
417
417
|
};
|
|
418
|
-
if (!value || typeof value != "object" || Array.isArray(value)) return
|
|
418
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return invalid6();
|
|
419
419
|
let d = value;
|
|
420
|
-
return Object.keys(d).sort().join(",") !== "mediaType,sha256,size" || !["application/octet-stream", "text/plain", "text/markdown", "application/json"].includes(d.mediaType) || !Number.isSafeInteger(d.size) || d.size < 0 || d.size > 16 * 1024 * 1024 || typeof d.sha256 != "string" || !/^[0-9a-f]{64}$/.test(d.sha256) ?
|
|
420
|
+
return Object.keys(d).sort().join(",") !== "mediaType,sha256,size" || !["application/octet-stream", "text/plain", "text/markdown", "application/json"].includes(d.mediaType) || !Number.isSafeInteger(d.size) || d.size < 0 || d.size > 16 * 1024 * 1024 || typeof d.sha256 != "string" || !/^[0-9a-f]{64}$/.test(d.sha256) ? invalid6() : d;
|
|
421
421
|
}
|
|
422
422
|
function safeEnrichmentName(value) {
|
|
423
423
|
return safeFileName(value) && !/^original(?:\.|$)/i.test(value);
|
|
424
424
|
}
|
|
425
425
|
function parseFileEnrichMetadata(value, maxBytes) {
|
|
426
|
-
let
|
|
426
|
+
let invalid6 = () => {
|
|
427
427
|
throw new FileOperationError("invalid_input", 400);
|
|
428
428
|
};
|
|
429
|
-
if (!value || typeof value != "object" || Array.isArray(value)) return
|
|
429
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return invalid6();
|
|
430
430
|
let d = value;
|
|
431
|
-
if (Object.keys(d).some((key) => !["name", "size", "mediaType", "replace"].includes(key)) || !safeEnrichmentName(d.name) || !Number.isSafeInteger(d.size) || d.size < 0 || d.mediaType !== void 0 && (typeof d.mediaType != "string" || d.mediaType.length > 255 || /[\u0000-\u001f\u007f]/.test(d.mediaType)) || d.replace !== void 0 && (typeof d.replace != "string" || !/^[0-9a-f]{64}$/.test(d.replace))) return
|
|
431
|
+
if (Object.keys(d).some((key) => !["name", "size", "mediaType", "replace"].includes(key)) || !safeEnrichmentName(d.name) || !Number.isSafeInteger(d.size) || d.size < 0 || d.mediaType !== void 0 && (typeof d.mediaType != "string" || d.mediaType.length > 255 || /[\u0000-\u001f\u007f]/.test(d.mediaType)) || d.replace !== void 0 && (typeof d.replace != "string" || !/^[0-9a-f]{64}$/.test(d.replace))) return invalid6();
|
|
432
432
|
if (d.size > maxBytes) throw new FileOperationError("request_too_large", 413);
|
|
433
433
|
return d;
|
|
434
434
|
}
|
|
@@ -439,23 +439,23 @@ function safeFilePath(value) {
|
|
|
439
439
|
return typeof value == "string" && value.length <= 1024 && value.split("/").every(safeFileName);
|
|
440
440
|
}
|
|
441
441
|
function parseFileCreateMetadata(value, maxBytes) {
|
|
442
|
-
let
|
|
442
|
+
let invalid6 = () => {
|
|
443
443
|
throw new FileOperationError("invalid_input", 400);
|
|
444
444
|
};
|
|
445
|
-
if (!value || typeof value != "object" || Array.isArray(value)) return
|
|
445
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return invalid6();
|
|
446
446
|
let input = value;
|
|
447
|
-
if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "inputMediaType", "size", "requestKey"].includes(key))) return
|
|
447
|
+
if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "inputMediaType", "size", "requestKey"].includes(key))) return invalid6();
|
|
448
448
|
let path = input.path === void 0 ? "Files" : input.path;
|
|
449
|
-
if (!safeFileName(input.name) || !safeFilePath(path) || path.split("/")[0].toLowerCase() === ".os" || input.storage !== void 0 && input.storage !== "remote" && input.storage !== "local" || input.inputMediaType !== void 0 && input.inputMediaType !== "application/pdf" || !Number.isSafeInteger(input.size) || input.size < 0) return
|
|
449
|
+
if (!safeFileName(input.name) || !safeFilePath(path) || path.split("/")[0].toLowerCase() === ".os" || input.storage !== void 0 && input.storage !== "remote" && input.storage !== "local" || input.inputMediaType !== void 0 && input.inputMediaType !== "application/pdf" || !Number.isSafeInteger(input.size) || input.size < 0) return invalid6();
|
|
450
450
|
if (input.size > maxBytes) throw new FileOperationError("request_too_large", 413);
|
|
451
|
-
if (typeof input.requestKey != "string" || input.requestKey.length < 1 || input.requestKey.length > 256 || input.requestKey !== input.requestKey.trim() || /[\u0000-\u001f\u007f]/.test(input.requestKey)) return
|
|
451
|
+
if (typeof input.requestKey != "string" || input.requestKey.length < 1 || input.requestKey.length > 256 || input.requestKey !== input.requestKey.trim() || /[\u0000-\u001f\u007f]/.test(input.requestKey)) return invalid6();
|
|
452
452
|
let csv;
|
|
453
453
|
if (input.csv !== void 0) {
|
|
454
|
-
if (!input.csv || typeof input.csv != "object" || Array.isArray(input.csv)) return
|
|
454
|
+
if (!input.csv || typeof input.csv != "object" || Array.isArray(input.csv)) return invalid6();
|
|
455
455
|
let hints = input.csv;
|
|
456
|
-
if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key))) return
|
|
456
|
+
if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key))) return invalid6();
|
|
457
457
|
let encoding = hints.encoding === void 0 ? "utf-8" : hints.encoding, delimiter = hints.delimiter === void 0 ? "," : hints.delimiter, headerRow = hints.headerRow === void 0 ? 1 : hints.headerRow;
|
|
458
|
-
if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", " "].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5) return
|
|
458
|
+
if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", " "].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5) return invalid6();
|
|
459
459
|
csv = { encoding, delimiter, headerRow };
|
|
460
460
|
}
|
|
461
461
|
return {
|
|
@@ -475,7 +475,11 @@ var AppRoutineContractError = class extends Error {
|
|
|
475
475
|
this.code = code;
|
|
476
476
|
}
|
|
477
477
|
code;
|
|
478
|
-
}, propertyName = /^[a-z][A-Za-z0-9]*(?![\s\S])/, stepId = /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/, routineName = /^[a-z0-9][a-z0-9-]{0,62}(?![\s\S])
|
|
478
|
+
}, propertyName = /^[a-z][A-Za-z0-9]*(?![\s\S])/, stepId = /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/, routineName = /^[a-z0-9][a-z0-9-]{0,62}(?![\s\S])/;
|
|
479
|
+
function isAppRoutineName(value) {
|
|
480
|
+
return typeof value == "string" && routineName.test(value);
|
|
481
|
+
}
|
|
482
|
+
var owns = (value, key) => Object.hasOwn(value, key), invalidContract = () => {
|
|
479
483
|
throw new AppRoutineContractError("invalid_contract");
|
|
480
484
|
}, invalidValue = () => {
|
|
481
485
|
throw new AppRoutineContractError("invalid_value");
|
|
@@ -530,7 +534,7 @@ function parseAppRoutineContract(value) {
|
|
|
530
534
|
return invalidContract();
|
|
531
535
|
}
|
|
532
536
|
}
|
|
533
|
-
if (!record(value) || !fields2(value, ["routine", "input", "steps"], ["result"]) ||
|
|
537
|
+
if (!record(value) || !fields2(value, ["routine", "input", "steps"], ["result"]) || !isAppRoutineName(value.routine) || !denseArray(value.steps) || value.steps.length < 1 || value.steps.length > 64) return invalidContract();
|
|
534
538
|
let input = schema2(value.input), result2 = owns(value, "result") ? schema2(value.result) : void 0, ids = /* @__PURE__ */ new Set(), steps = value.steps.map((step) => !record(step) || !fields2(step, ["id"], ["summary"]) || typeof step.id != "string" || !stepId.test(step.id) || ids.has(step.id) ? invalidContract() : (ids.add(step.id), { id: step.id, ...owns(step, "summary") ? { summary: schema2(step.summary) } : {} }));
|
|
535
539
|
return { routine: value.routine, input, steps, ...result2 === void 0 ? {} : { result: result2 } };
|
|
536
540
|
}
|
|
@@ -568,7 +572,49 @@ function validateRoutineSchemaValue(schema2, value) {
|
|
|
568
572
|
}
|
|
569
573
|
}
|
|
570
574
|
|
|
571
|
-
var
|
|
575
|
+
var ROUTINE_DECLARATION_SCHEMA = "https://schemas.oddington.ai/routine/v1.json";
|
|
576
|
+
var invalid = (field) => {
|
|
577
|
+
throw new Error(`Invalid routine declaration: ${field}`);
|
|
578
|
+
}, object2 = (value, fields6, field) => ((!value || typeof value != "object" || Array.isArray(value) || Object.keys(value).some((key) => !fields6.includes(key))) && invalid(field), value), routineAlias = (value) => typeof value == "string" && /^[a-z][a-z0-9-]{0,62}$/.test(value), list = (value, field, allowed) => value === void 0 ? [] : ((!Array.isArray(value) || value.length > 64 || value.some((item) => !routineAlias(item) || allowed && !allowed.includes(item)) || new Set(value).size !== value.length) && invalid(field), [...value].sort());
|
|
579
|
+
function routineAssetPattern(value) {
|
|
580
|
+
return typeof value == "string" && value.length <= 512 && !value.startsWith("/") && !value.includes("\\") && !value.includes(":") && value.split("/").every((part) => !!part && part !== "." && part !== ".." && /^[a-zA-Z0-9_.*-]+$/.test(part));
|
|
581
|
+
}
|
|
582
|
+
function parseRoutineDeclaration(value) {
|
|
583
|
+
let v = object2(value, ["$schema", "access", "runtime", "retry", "assets"], "fields");
|
|
584
|
+
v.$schema !== ROUTINE_DECLARATION_SCHEMA && invalid("$schema");
|
|
585
|
+
let access = object2(v.access === void 0 ? {} : v.access, ["repositories", "connections", "models", "files", "publish"], "access"), rawRepositories = access.repositories === void 0 ? {} : access.repositories, repositories = object2(rawRepositories, rawRepositories && typeof rawRepositories == "object" ? Object.keys(rawRepositories) : [], "access.repositories");
|
|
586
|
+
Object.keys(repositories).length > 64 && invalid("access.repositories");
|
|
587
|
+
let grants = {};
|
|
588
|
+
for (let key of Object.keys(repositories).sort())
|
|
589
|
+
(!routineAlias(key) || !["read", "write"].includes(repositories[key])) && invalid(`access.repositories.${key}`), grants[key] = repositories[key];
|
|
590
|
+
access.files !== void 0 && !["read", "read-write"].includes(access.files) && invalid("access.files");
|
|
591
|
+
let runtime = object2(v.runtime === void 0 ? {} : v.runtime, ["features", "resources", "maxDuration"], "runtime");
|
|
592
|
+
runtime.resources !== void 0 && !["standard", "large"].includes(runtime.resources) && invalid("runtime.resources");
|
|
593
|
+
let duration = runtime.maxDuration === void 0 ? "15m" : runtime.maxDuration;
|
|
594
|
+
(typeof duration != "string" || !/^(?:[1-5][0-9]|60)m$/.test(duration) || Number(duration.slice(0, -1)) < 15) && invalid("runtime.maxDuration");
|
|
595
|
+
let retry = object2(v.retry === void 0 ? {} : v.retry, ["maxAttempts"], "retry"), maxAttempts = retry.maxAttempts === void 0 ? 1 : retry.maxAttempts;
|
|
596
|
+
(!Number.isInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > 3) && invalid("retry.maxAttempts");
|
|
597
|
+
let assets = v.assets === void 0 ? [] : v.assets;
|
|
598
|
+
return (!Array.isArray(assets) || assets.length > 64 || assets.some((item) => !routineAssetPattern(item)) || new Set(assets).size !== assets.length) && invalid("assets"), {
|
|
599
|
+
$schema: ROUTINE_DECLARATION_SCHEMA,
|
|
600
|
+
access: {
|
|
601
|
+
repositories: grants,
|
|
602
|
+
connections: list(access.connections, "access.connections"),
|
|
603
|
+
models: list(access.models, "access.models"),
|
|
604
|
+
...access.files === void 0 ? {} : { files: access.files },
|
|
605
|
+
publish: list(access.publish, "access.publish", ["asks", "digests"])
|
|
606
|
+
},
|
|
607
|
+
runtime: {
|
|
608
|
+
features: list(runtime.features, "runtime.features", ["python", "documents", "browser"]),
|
|
609
|
+
resources: runtime.resources ?? "standard",
|
|
610
|
+
maxDuration: duration
|
|
611
|
+
},
|
|
612
|
+
retry: { maxAttempts },
|
|
613
|
+
assets: [...assets].sort()
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
var LIMIT = 256 * 1024, invalid2 = () => {
|
|
572
618
|
throw new AppRoutineContractError("invalid_value");
|
|
573
619
|
}, invalidContract2 = () => {
|
|
574
620
|
throw new AppRoutineContractError("invalid_contract");
|
|
@@ -582,40 +628,61 @@ function freeze(value) {
|
|
|
582
628
|
}
|
|
583
629
|
function json(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
584
630
|
if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return;
|
|
585
|
-
if (!value || typeof value != "object" || ancestors.has(value)) return
|
|
631
|
+
if (!value || typeof value != "object" || ancestors.has(value)) return invalid2();
|
|
586
632
|
let array3 = Array.isArray(value);
|
|
587
|
-
if (!array3 && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return
|
|
588
|
-
let
|
|
589
|
-
if (array3 && (
|
|
633
|
+
if (!array3 && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return invalid2();
|
|
634
|
+
let keys4 = Reflect.ownKeys(value);
|
|
635
|
+
if (array3 && (keys4.length !== value.length + 1 || !Array.from({ length: value.length }, (_, index) => Object.hasOwn(value, index)).every(Boolean))) return invalid2();
|
|
590
636
|
ancestors.add(value);
|
|
591
|
-
for (let key of
|
|
637
|
+
for (let key of keys4) {
|
|
592
638
|
if (array3 && key === "length") continue;
|
|
593
|
-
if (typeof key != "string") return
|
|
594
|
-
let
|
|
595
|
-
if (!
|
|
596
|
-
json(
|
|
639
|
+
if (typeof key != "string") return invalid2();
|
|
640
|
+
let descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
641
|
+
if (!descriptor.enumerable || !Object.hasOwn(descriptor, "value")) return invalid2();
|
|
642
|
+
json(descriptor.value, ancestors);
|
|
597
643
|
}
|
|
598
644
|
ancestors.delete(value);
|
|
599
645
|
}
|
|
600
|
-
function
|
|
601
|
-
json(value)
|
|
646
|
+
function captureJson(value) {
|
|
647
|
+
json(value);
|
|
602
648
|
let encoded = JSON.stringify(value);
|
|
603
|
-
return new TextEncoder().encode(encoded).byteLength > LIMIT ?
|
|
649
|
+
return new TextEncoder().encode(encoded).byteLength > LIMIT ? invalid2() : freeze(JSON.parse(encoded));
|
|
650
|
+
}
|
|
651
|
+
function capture(schema2, value) {
|
|
652
|
+
let captured = captureJson(value);
|
|
653
|
+
return validateRoutineSchemaValue(schema2, captured), captured;
|
|
654
|
+
}
|
|
655
|
+
var schemas = /* @__PURE__ */ new WeakMap();
|
|
656
|
+
function nestedSchema(value) {
|
|
657
|
+
let metadata = schemaMetadata(value);
|
|
658
|
+
return Object.hasOwn(metadata, "default") ? invalidContract2() : metadata.schema;
|
|
659
|
+
}
|
|
660
|
+
function schemaMetadata(value) {
|
|
661
|
+
if (!value || typeof value != "object") return invalidContract2();
|
|
662
|
+
let registered = schemas.get(value);
|
|
663
|
+
if (registered) return registered;
|
|
664
|
+
try {
|
|
665
|
+
json(value);
|
|
666
|
+
} catch {
|
|
667
|
+
return invalidContract2();
|
|
668
|
+
}
|
|
669
|
+
return { schema: parseAppRoutineContract({ routine: "definition", input: value, steps: [{ id: "inspect" }] }).input };
|
|
604
670
|
}
|
|
605
|
-
function declaration(value) {
|
|
671
|
+
function declaration(value, defaults) {
|
|
606
672
|
try {
|
|
607
673
|
json(value);
|
|
608
674
|
} catch {
|
|
609
675
|
return invalidContract2();
|
|
610
676
|
}
|
|
611
|
-
|
|
677
|
+
let parsed = freeze(parseAppRoutineContract({ routine: "definition", input: value, steps: [{ id: "inspect" }] }).input), captured = defaults ? capture(parsed, defaults.value) : void 0, builder = Object.defineProperty({ ...parsed }, "default", { value: (value2) => declaration(parsed, { value: value2 }) });
|
|
678
|
+
return schemas.set(builder, { schema: parsed, ...defaults ? { default: captured } : {} }), Object.freeze(builder);
|
|
612
679
|
}
|
|
613
680
|
var schema = {
|
|
614
681
|
object(properties) {
|
|
615
|
-
return declaration({ type: "object", properties, required: Object.keys(properties), additionalProperties: !1 });
|
|
682
|
+
return declaration({ type: "object", properties: Object.fromEntries(Object.entries(properties).map(([key, value]) => [key, nestedSchema(value)])), required: Object.keys(properties), additionalProperties: !1 });
|
|
616
683
|
},
|
|
617
684
|
array(items, options) {
|
|
618
|
-
return declaration({ type: "array", items, maxItems: options.maxItems });
|
|
685
|
+
return declaration({ type: "array", items: nestedSchema(items), maxItems: options.maxItems });
|
|
619
686
|
},
|
|
620
687
|
string(options = {}) {
|
|
621
688
|
return declaration({ type: "string", ...options });
|
|
@@ -629,33 +696,77 @@ var schema = {
|
|
|
629
696
|
boolean() {
|
|
630
697
|
return declaration({ type: "boolean" });
|
|
631
698
|
}
|
|
632
|
-
}, file = () => declaration({ type: "file" }), definitions = /* @__PURE__ */ new WeakMap()
|
|
633
|
-
|
|
699
|
+
}, file = () => declaration({ type: "file" }), definitions = /* @__PURE__ */ new WeakMap();
|
|
700
|
+
function fields3(value, allowed) {
|
|
701
|
+
if (!value || typeof value != "object" || Object.getPrototypeOf(value) !== Object.prototype || Reflect.ownKeys(value).some((key) => typeof key != "string" || allowed && !allowed.includes(key) || !Object.getOwnPropertyDescriptor(value, key).enumerable || !Object.hasOwn(Object.getOwnPropertyDescriptor(value, key), "value"))) return invalidContract2();
|
|
702
|
+
}
|
|
703
|
+
var title = (value) => typeof value == "string" && value.trim().length > 0 && value.length <= 256;
|
|
704
|
+
function accessMetadata(value) {
|
|
634
705
|
try {
|
|
635
|
-
|
|
636
|
-
|
|
706
|
+
value !== void 0 && json(value), fields3(value ?? {}, ["repositories", "connections", "models", "files", "publish"]);
|
|
707
|
+
let access = value, names = access?.connections ?? [];
|
|
708
|
+
if (!Array.isArray(names) || names.length > 64 || new Set(names).size !== names.length || names.some((name) => typeof name != "string" || name.split("/").length !== 2 || name.split("/").some((part) => !isAppRoutineName(part)))) return invalidContract2();
|
|
709
|
+
let parsed = parseRoutineDeclaration({ $schema: ROUTINE_DECLARATION_SCHEMA, access: { ...access, connections: [] } }).access;
|
|
710
|
+
return freeze({ ...parsed, connections: [...names] });
|
|
637
711
|
} catch {
|
|
638
712
|
return invalidContract2();
|
|
639
713
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
714
|
+
}
|
|
715
|
+
var defineRoutine = (definition) => {
|
|
716
|
+
if (fields3(definition, ["id", "title", "input", "steps", "result", "access", "responses", "run"]), !isAppRoutineName(definition.id) || definition.title !== void 0 && !title(definition.title) || typeof definition.run != "function") return invalidContract2();
|
|
717
|
+
let input = definition.input === void 0 ? { schema: empty, default: {} } : schemaMetadata(definition.input), result2 = definition.result === void 0 ? void 0 : schemaMetadata(definition.result).schema, access = accessMetadata(definition.access);
|
|
718
|
+
fields3(definition.steps ?? {});
|
|
719
|
+
let executable = Object.fromEntries(Object.entries(definition.steps ?? {}).map(([id3, step]) => (fields3(step, ["title", "run"]), !title(step.title) || typeof step.run != "function" ? invalidContract2() : [id3, Object.freeze({ title: step.title, run: step.run })]))), steps = Object.entries(executable).map(([id3, step]) => ({ id: id3, title: step.title }));
|
|
720
|
+
parseAppRoutineContract({
|
|
721
|
+
routine: definition.id,
|
|
722
|
+
input: input.schema,
|
|
723
|
+
steps: steps.length ? steps.map(({ id: id3 }) => ({ id: id3 })) : [{ id: "inspect" }],
|
|
724
|
+
...result2 ? { result: result2 } : {}
|
|
725
|
+
});
|
|
726
|
+
let responses = [], ids = /* @__PURE__ */ new Set();
|
|
727
|
+
if (definition.responses !== void 0) {
|
|
728
|
+
if (!Array.isArray(definition.responses) || definition.responses.length > 64 || Reflect.ownKeys(definition.responses).length !== definition.responses.length + 1) return invalidContract2();
|
|
729
|
+
for (let index = 0; index < definition.responses.length; index++) {
|
|
730
|
+
let descriptor = Object.getOwnPropertyDescriptor(definition.responses, String(index));
|
|
731
|
+
if (!descriptor || !Object.hasOwn(descriptor, "value")) return invalidContract2();
|
|
732
|
+
let response2 = descriptor.value;
|
|
733
|
+
if (fields3(response2, ["id", "results", "run"]), !isAppRoutineName(response2.id) || ids.has(response2.id)) return invalidContract2();
|
|
734
|
+
if (ids.add(response2.id), response2.results !== void 0)
|
|
735
|
+
try {
|
|
736
|
+
json(response2.results);
|
|
737
|
+
} catch {
|
|
738
|
+
return invalidContract2();
|
|
739
|
+
}
|
|
740
|
+
try {
|
|
741
|
+
responses.push(defineHandler(response2));
|
|
742
|
+
} catch {
|
|
743
|
+
return invalidContract2();
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
let contract = freeze({
|
|
748
|
+
id: definition.id,
|
|
749
|
+
...definition.title === void 0 ? {} : { title: definition.title },
|
|
750
|
+
input: input.schema,
|
|
751
|
+
...Object.hasOwn(input, "default") ? { inputDefault: input.default } : {},
|
|
752
|
+
access,
|
|
753
|
+
responses: responses.map(({ id: id3 }) => ({ id: id3 })),
|
|
754
|
+
steps,
|
|
755
|
+
...result2 ? { result: result2 } : {}
|
|
650
756
|
}), captured = Object.freeze({
|
|
651
757
|
...definition,
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
758
|
+
access,
|
|
759
|
+
steps: Object.freeze(executable),
|
|
760
|
+
responses: Object.freeze(responses),
|
|
761
|
+
...definition.input === void 0 ? {} : { input: declaration(
|
|
762
|
+
input.schema,
|
|
763
|
+
Object.hasOwn(input, "default") ? { value: input.default } : void 0
|
|
764
|
+
) },
|
|
765
|
+
...result2 === void 0 ? {} : { result: declaration(result2) },
|
|
655
766
|
// Only this authored definition is callable; no generic runner is exported.
|
|
656
|
-
run: (
|
|
767
|
+
run: (input2, os2) => executeRoutineDefinition(captured, input2, os2)
|
|
657
768
|
});
|
|
658
|
-
return definitions.set(captured, { contract, run: definition.run }), captured;
|
|
769
|
+
return definitions.set(captured, { contract, steps: executable, run: definition.run }), captured;
|
|
659
770
|
};
|
|
660
771
|
function inspectRoutineDefinition(definition) {
|
|
661
772
|
if (!definition || typeof definition != "object") return invalidContract2();
|
|
@@ -663,42 +774,62 @@ function inspectRoutineDefinition(definition) {
|
|
|
663
774
|
return registered ? registered.contract : invalidContract2();
|
|
664
775
|
}
|
|
665
776
|
function captureRoutineInput(definition, input) {
|
|
666
|
-
|
|
777
|
+
let contract = inspectRoutineDefinition(definition);
|
|
778
|
+
return capture(contract.input, input === void 0 && Object.hasOwn(contract, "inputDefault") ? contract.inputDefault : input);
|
|
667
779
|
}
|
|
668
780
|
async function executeRoutineDefinition(definition, input, runtime) {
|
|
669
|
-
let captured = captureRoutineInput(definition, input), { contract, run } = definitions.get(definition), active2 = !0, broken = !1,
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
781
|
+
let captured = captureRoutineInput(definition, input), { contract, steps, run } = definitions.get(definition), active2 = !0, accepting = !0, broken = !1, work = Promise.resolve(), called = /* @__PURE__ */ new Set(), reached = /* @__PURE__ */ new Set(), guarded = (value, receiver) => typeof value == "function" ? (...args) => {
|
|
782
|
+
if (!active2 || broken) throw new Error("Run authority ended");
|
|
783
|
+
return guarded(Reflect.apply(value, receiver, args));
|
|
784
|
+
} : value && typeof value == "object" && !(value instanceof Promise) ? new Proxy({ ...value }, {
|
|
785
|
+
// Copy the surface so wrapping a frozen host capability does not violate
|
|
786
|
+
// Proxy invariants; methods still receive their original host receiver.
|
|
787
|
+
get(_target, key) {
|
|
788
|
+
return guarded(Reflect.get(value, key, value), value);
|
|
789
|
+
}
|
|
790
|
+
}) : value, qualify = (value) => value.questions === void 0 ? value : { ...value, questions: value.questions.map((question2) => question2.handler ? contract.responses.some((handler) => handler.id === question2.handler.id) ? { ...question2, handler: { ...question2.handler, id: `${contract.id}/${question2.handler.id}` } } : invalid2() : question2) }, os2 = Object.freeze({
|
|
791
|
+
...guarded({
|
|
792
|
+
...runtime,
|
|
793
|
+
run: freeze({ ...runtime.run }),
|
|
794
|
+
inbox: { ...runtime.inbox, publishAsk: (value, options) => runtime.inbox.publishAsk(qualify(value), options) }
|
|
795
|
+
}),
|
|
796
|
+
step(id3, ...input2) {
|
|
797
|
+
let saved;
|
|
681
798
|
try {
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
if (step.summary === void 0) {
|
|
685
|
-
if (summary.length) return invalid();
|
|
686
|
-
} else value = capture(step.summary, summary[0]);
|
|
799
|
+
if (!active2 || !accepting || broken || !Object.hasOwn(steps, id3) || called.has(id3) || input2.length > 1) return invalid2();
|
|
800
|
+
input2.length && (saved = captureJson(input2[0])), called.add(id3);
|
|
687
801
|
} catch (error) {
|
|
688
802
|
return broken = !0, Promise.reject(error);
|
|
689
803
|
}
|
|
690
|
-
let
|
|
691
|
-
|
|
804
|
+
let next = work.then(async () => {
|
|
805
|
+
if (broken) return invalid2();
|
|
806
|
+
reached.add(id3);
|
|
807
|
+
try {
|
|
808
|
+
await runtime.step(id3, { status: "running" });
|
|
809
|
+
let output = await steps[id3].run(saved, os2);
|
|
810
|
+
if (fields3(output, ["summary", "data"]), !Object.hasOwn(output, "summary") || !Object.hasOwn(output, "data")) return invalid2();
|
|
811
|
+
let summary2 = captureJson(output.summary), data3 = captureJson(output.data);
|
|
812
|
+
return await runtime.step(id3, { status: "completed", summary: summary2, data: data3 }), freeze({ summary: summary2, data: data3 });
|
|
813
|
+
} catch (error) {
|
|
814
|
+
throw broken = !0, await runtime.step(id3, { status: "failed" }), error;
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
return work = next.then(() => {
|
|
818
|
+
}, () => {
|
|
692
819
|
broken = !0;
|
|
693
|
-
}),
|
|
820
|
+
}), next;
|
|
694
821
|
}
|
|
695
|
-
});
|
|
822
|
+
}), result2, failure;
|
|
696
823
|
try {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
active2 = !1;
|
|
824
|
+
result2 = await run(captured, os2);
|
|
825
|
+
} catch (error) {
|
|
826
|
+
failure = error, broken = !0;
|
|
701
827
|
}
|
|
828
|
+
accepting = !1, await work, active2 = !1;
|
|
829
|
+
for (let step of contract.steps) reached.has(step.id) || await runtime.step(step.id, { status: "skipped" });
|
|
830
|
+
if (broken) throw failure ?? new AppRoutineContractError("invalid_value");
|
|
831
|
+
if (contract.result !== void 0) return capture(contract.result, result2);
|
|
832
|
+
if (result2 !== void 0) return invalid2();
|
|
702
833
|
}
|
|
703
834
|
|
|
704
835
|
var DataOperationError = class extends Error {
|
|
@@ -716,46 +847,46 @@ var DataOperationError = class extends Error {
|
|
|
716
847
|
component;
|
|
717
848
|
};
|
|
718
849
|
|
|
719
|
-
var
|
|
850
|
+
var invalid3 = () => {
|
|
720
851
|
throw new DataOperationError("invalid_query");
|
|
721
852
|
}, historyText = (value) => typeof value == "string" && !/[\u0000\uD800-\uDFFF]/u.test(value);
|
|
722
853
|
function historyVersion(value) {
|
|
723
854
|
return historyText(value) && value.length > 0 && new TextEncoder().encode(value).length <= 1024 && !/[\u0000-\u001f\u007f-\u009f]/.test(value) && !/^[0-9a-f]{40}$/i.test(value);
|
|
724
855
|
}
|
|
725
856
|
function historyProperties(value) {
|
|
726
|
-
if (!value || typeof value != "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) return
|
|
857
|
+
if (!value || typeof value != "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) return invalid3();
|
|
727
858
|
let descriptors = Object.getOwnPropertyDescriptors(value);
|
|
728
|
-
return Reflect.ownKeys(value).some((key) => typeof key != "string" || !descriptors[key]?.enumerable || !Object.hasOwn(descriptors[key], "value")) ?
|
|
859
|
+
return Reflect.ownKeys(value).some((key) => typeof key != "string" || !descriptors[key]?.enumerable || !Object.hasOwn(descriptors[key], "value")) ? invalid3() : descriptors;
|
|
729
860
|
}
|
|
730
861
|
var historyCollection = (value) => typeof value == "string" && value.length <= 512 && /^[_a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(value), historyCursor = (value) => typeof value == "string" && value.length <= 128 * 1024 && /^history-cursor-v1\.[A-Za-z0-9_-]{1,64}\.[A-Za-z0-9_-]{16}\.[A-Za-z0-9_-]+$/.test(value);
|
|
731
862
|
function historyArray(value) {
|
|
732
|
-
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) return
|
|
863
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) return invalid3();
|
|
733
864
|
let descriptors = Object.getOwnPropertyDescriptors(value);
|
|
734
|
-
if (Reflect.ownKeys(value).length !== value.length + 1) return
|
|
865
|
+
if (Reflect.ownKeys(value).length !== value.length + 1) return invalid3();
|
|
735
866
|
let result2 = [];
|
|
736
867
|
for (let i = 0; i < value.length; i++) {
|
|
737
|
-
let
|
|
738
|
-
if (!
|
|
739
|
-
result2.push(
|
|
868
|
+
let descriptor = descriptors[i];
|
|
869
|
+
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value")) return invalid3();
|
|
870
|
+
result2.push(descriptor.value);
|
|
740
871
|
}
|
|
741
872
|
return result2;
|
|
742
873
|
}
|
|
743
874
|
function captureOptions(value, changes) {
|
|
744
875
|
if (value === void 0) return {};
|
|
745
876
|
let descriptors = historyProperties(value), result2 = {}, allowed = changes ? ["collections", "refs", "from", "through", "limit", "after"] : ["limit", "before"];
|
|
746
|
-
if (Object.keys(descriptors).some((key) => !allowed.includes(key))) return
|
|
877
|
+
if (Object.keys(descriptors).some((key) => !allowed.includes(key))) return invalid3();
|
|
747
878
|
for (let key of allowed) {
|
|
748
879
|
if (!Object.hasOwn(descriptors, key)) continue;
|
|
749
880
|
let scalar = descriptors[key].value;
|
|
750
881
|
if (key === "collections" || key === "refs") {
|
|
751
882
|
let values = historyArray(scalar);
|
|
752
|
-
if (!values.length || values.length > (key === "collections" ? 16 : 100) || !values.every(key === "collections" ? historyCollection : validRecordRef) || new Set(values).size !== values.length) return
|
|
883
|
+
if (!values.length || values.length > (key === "collections" ? 16 : 100) || !values.every(key === "collections" ? historyCollection : validRecordRef) || new Set(values).size !== values.length) return invalid3();
|
|
753
884
|
result2[key] = values;
|
|
754
885
|
} else if (key === "limit") {
|
|
755
|
-
if (!Number.isInteger(scalar) || scalar < 1 || scalar > (changes ? 500 : 100)) return
|
|
886
|
+
if (!Number.isInteger(scalar) || scalar < 1 || scalar > (changes ? 500 : 100)) return invalid3();
|
|
756
887
|
result2.limit = scalar;
|
|
757
888
|
} else {
|
|
758
|
-
if (!(key === "after" ? historyCursor(scalar) : historyVersion(scalar))) return
|
|
889
|
+
if (!(key === "after" ? historyCursor(scalar) : historyVersion(scalar))) return invalid3();
|
|
759
890
|
result2[key] = scalar;
|
|
760
891
|
}
|
|
761
892
|
}
|
|
@@ -763,39 +894,39 @@ function captureOptions(value, changes) {
|
|
|
763
894
|
}
|
|
764
895
|
var captureHistoryListOptions = (value) => captureOptions(value, !1), captureHistoryChangesOptions = (value) => captureOptions(value, !0);
|
|
765
896
|
function captureHistoryInstant(value) {
|
|
766
|
-
if (!historyText(value) || value.length > 1024) return
|
|
897
|
+
if (!historyText(value) || value.length > 1024) return invalid3();
|
|
767
898
|
let match = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.\d+)?([Zz]|([+-])(\d{2}):(\d{2}))$/.exec(value);
|
|
768
|
-
if (!match) return
|
|
899
|
+
if (!match) return invalid3();
|
|
769
900
|
let [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number), days = new Date(Date.UTC(year, month, 0));
|
|
770
|
-
return days.setUTCFullYear(year), year < 1 || month < 1 || month > 12 || day < 1 || day > days.getUTCDate() || hour > 23 || minute > 59 || second > 59 || Number(match[9] ?? 0) > 23 || Number(match[10] ?? 0) > 59 ?
|
|
901
|
+
return days.setUTCFullYear(year), year < 1 || month < 1 || month > 12 || day < 1 || day > days.getUTCDate() || hour > 23 || minute > 59 || second > 59 || Number(match[9] ?? 0) > 23 || Number(match[10] ?? 0) > 59 ? invalid3() : value;
|
|
771
902
|
}
|
|
772
903
|
|
|
773
|
-
var
|
|
904
|
+
var invalid4 = () => {
|
|
774
905
|
throw new DataOperationError("invalid_query");
|
|
775
906
|
};
|
|
776
907
|
function captureRecordsSearchInput(query, options) {
|
|
777
|
-
if (!historyText(query)) return
|
|
908
|
+
if (!historyText(query)) return invalid4();
|
|
778
909
|
let length = [...query.trim()].length;
|
|
779
|
-
if (length < 1 || length > 256) return
|
|
910
|
+
if (length < 1 || length > 256) return invalid4();
|
|
780
911
|
if (options === void 0) return { query };
|
|
781
912
|
let descriptors = historyProperties(options);
|
|
782
|
-
if (Object.keys(descriptors).some((key) => !["collections", "limit"].includes(key))) return
|
|
913
|
+
if (Object.keys(descriptors).some((key) => !["collections", "limit"].includes(key))) return invalid4();
|
|
783
914
|
let captured = {};
|
|
784
915
|
if (Object.hasOwn(descriptors, "collections")) {
|
|
785
916
|
let supplied = descriptors.collections.value;
|
|
786
|
-
if (!Array.isArray(supplied) || supplied.length < 1 || supplied.length > 16 || Reflect.ownKeys(supplied).length !== supplied.length + 1) return
|
|
917
|
+
if (!Array.isArray(supplied) || supplied.length < 1 || supplied.length > 16 || Reflect.ownKeys(supplied).length !== supplied.length + 1) return invalid4();
|
|
787
918
|
let collections = [];
|
|
788
919
|
for (let index = 0; index < supplied.length; index++) {
|
|
789
|
-
let
|
|
790
|
-
if (!
|
|
791
|
-
collections.push(
|
|
920
|
+
let descriptor = Object.getOwnPropertyDescriptor(supplied, String(index));
|
|
921
|
+
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value") || !historyText(descriptor.value)) return invalid4();
|
|
922
|
+
collections.push(descriptor.value);
|
|
792
923
|
}
|
|
793
|
-
if (new Set(collections).size !== collections.length) return
|
|
924
|
+
if (new Set(collections).size !== collections.length) return invalid4();
|
|
794
925
|
captured.collections = collections;
|
|
795
926
|
}
|
|
796
927
|
if (Object.hasOwn(descriptors, "limit")) {
|
|
797
928
|
let supplied = descriptors.limit.value;
|
|
798
|
-
if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100) return
|
|
929
|
+
if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100) return invalid4();
|
|
799
930
|
captured.limit = supplied;
|
|
800
931
|
}
|
|
801
932
|
return { query, options: captured };
|
|
@@ -826,8 +957,8 @@ function captureDataDelete(record3) {
|
|
|
826
957
|
return !validRecordRef(identity.$ref) || typeof identity.$version != "string" || !identity.$version.length || identity.$version.length > 512 ? invalidChange() : { ref: identity.$ref, expectedVersion: identity.$version };
|
|
827
958
|
}
|
|
828
959
|
function captureDataUpdate(record3, set) {
|
|
829
|
-
let identity = captureDataDelete(record3),
|
|
830
|
-
return !Object.keys(
|
|
960
|
+
let identity = captureDataDelete(record3), fields6 = mapping(set);
|
|
961
|
+
return !Object.keys(fields6).length || Object.keys(fields6).some((key) => key.startsWith("$") || ["id", "type"].includes(key)) ? invalidChange() : { ...identity, set: captureValue(fields6) };
|
|
831
962
|
}
|
|
832
963
|
function captureIdentities(value, update, allowEmpty = !0) {
|
|
833
964
|
if (!Array.isArray(value) || !allowEmpty && !value.length || value.length > 1e4) return invalidChange();
|
|
@@ -846,14 +977,14 @@ function captureDataCreate(value) {
|
|
|
846
977
|
let row = mapping(value);
|
|
847
978
|
if (!validRecordRef(row.$ref) || Object.keys(row).some((key) => key.startsWith("$") && !["$ref", "$filing"].includes(key)))
|
|
848
979
|
return invalidChange();
|
|
849
|
-
let { $ref: ref, $filing, ...
|
|
980
|
+
let { $ref: ref, $filing, ...fields6 } = row, filing;
|
|
850
981
|
if ($filing !== void 0) {
|
|
851
982
|
let components = mapping($filing);
|
|
852
983
|
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)))
|
|
853
984
|
return invalidChange();
|
|
854
985
|
filing = { ...components };
|
|
855
986
|
}
|
|
856
|
-
return { ref, fields: captureValue(
|
|
987
|
+
return { ref, fields: captureValue(fields6), ...filing ? { filing } : {} };
|
|
857
988
|
}
|
|
858
989
|
function captureDataChanges(updatesValue, createsValue = [], deletesValue = []) {
|
|
859
990
|
let updates = captureDataUpdates(updatesValue, !0);
|
|
@@ -861,8 +992,8 @@ function captureDataChanges(updatesValue, createsValue = [], deletesValue = [])
|
|
|
861
992
|
let creates = createsValue.map((item) => {
|
|
862
993
|
let row = mapping(item);
|
|
863
994
|
if (Object.keys(row).some((key) => !["ref", "fields", "filing"].includes(key)) || !Object.hasOwn(row, "ref") || !Object.hasOwn(row, "fields")) return invalidChange();
|
|
864
|
-
let
|
|
865
|
-
return Object.keys(
|
|
995
|
+
let fields6 = mapping(row.fields);
|
|
996
|
+
return Object.keys(fields6).some((key) => key.startsWith("$")) ? invalidChange() : captureDataCreate({ ...fields6, $ref: row.ref, ...Object.hasOwn(row, "filing") ? { $filing: row.filing } : {} });
|
|
866
997
|
}), deletes = captureIdentities(deletesValue, !1), refs = [...updates, ...creates, ...deletes].map((item) => item.ref);
|
|
867
998
|
return !refs.length || refs.length > 1e4 || new Set(refs).size !== refs.length ? invalidChange() : { updates, creates, deletes };
|
|
868
999
|
}
|
|
@@ -1047,7 +1178,7 @@ var data = {
|
|
|
1047
1178
|
}
|
|
1048
1179
|
};
|
|
1049
1180
|
|
|
1050
|
-
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,
|
|
1181
|
+
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, invalid5 = () => new FileOperationError("invalid_input", 400), unavailable = () => new FileOperationError("unavailable", 503, !0), failures = {
|
|
1051
1182
|
400: ["invalid_input", "unsupported_context"],
|
|
1052
1183
|
401: ["unauthenticated"],
|
|
1053
1184
|
403: ["access_denied"],
|
|
@@ -1064,7 +1195,7 @@ async function boundedBytes(stream, limit) {
|
|
|
1064
1195
|
for (; ; ) {
|
|
1065
1196
|
let { done, value } = await reader.read();
|
|
1066
1197
|
if (done) break;
|
|
1067
|
-
if (!(value instanceof Uint8Array)) throw
|
|
1198
|
+
if (!(value instanceof Uint8Array)) throw invalid5();
|
|
1068
1199
|
if (size += value.byteLength, size > limit) throw new FileOperationError("request_too_large", 413);
|
|
1069
1200
|
bytes.set(value, size - value.byteLength);
|
|
1070
1201
|
}
|
|
@@ -1115,7 +1246,7 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1115
1246
|
reader?.releaseLock();
|
|
1116
1247
|
}
|
|
1117
1248
|
}
|
|
1118
|
-
},
|
|
1249
|
+
}, body = new ReadableStream({
|
|
1119
1250
|
async pull(controller) {
|
|
1120
1251
|
try {
|
|
1121
1252
|
reader ??= source.getReader();
|
|
@@ -1129,7 +1260,7 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1129
1260
|
}
|
|
1130
1261
|
},
|
|
1131
1262
|
cancel
|
|
1132
|
-
}, { highWaterMark: 0 }), wrapped = new Response(
|
|
1263
|
+
}, { highWaterMark: 0 }), wrapped = new Response(body, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
|
|
1133
1264
|
for (let key of ["url", "redirected", "type"])
|
|
1134
1265
|
Object.defineProperty(wrapped, key, { value: response2[key] });
|
|
1135
1266
|
return wrapped;
|
|
@@ -1137,7 +1268,7 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1137
1268
|
throw detach(), delivery.abort(error), error;
|
|
1138
1269
|
}
|
|
1139
1270
|
}
|
|
1140
|
-
async function send(suffix, init2,
|
|
1271
|
+
async function send(suffix, init2, descriptor, initial, parent) {
|
|
1141
1272
|
let original = initial, checkCurrent = (context2 = original) => {
|
|
1142
1273
|
if (parent?.aborted) throw unavailable();
|
|
1143
1274
|
if (!original.isCurrent() || context2.url !== original.url) throw new FileOperationError("unsupported_context", 400);
|
|
@@ -1148,20 +1279,20 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1148
1279
|
checkCurrent(context2);
|
|
1149
1280
|
try {
|
|
1150
1281
|
let response2 = await (async () => {
|
|
1151
|
-
let url = `${context2.url}${suffix}`,
|
|
1282
|
+
let url = `${context2.url}${suffix}`, request2 = {
|
|
1152
1283
|
...init2,
|
|
1153
1284
|
signal: parent,
|
|
1154
1285
|
headers: { ...context2.headers, ...init2.headers },
|
|
1155
1286
|
redirect: "error",
|
|
1156
1287
|
cache: "no-store"
|
|
1157
1288
|
};
|
|
1158
|
-
return
|
|
1289
|
+
return descriptor ? fetch(url, request2) : hostedContent(url, request2, parent);
|
|
1159
1290
|
})();
|
|
1160
1291
|
if (!response2.ok) {
|
|
1161
1292
|
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
1293
|
throw code ? new FileOperationError(code, response2.status, code === "capacity" || code === "unavailable") : unavailable();
|
|
1163
1294
|
}
|
|
1164
|
-
if (response2.status !== (
|
|
1295
|
+
if (response2.status !== (descriptor === 204 ? 204 : 200) || descriptor === 204 && response2.body !== null)
|
|
1165
1296
|
throw response2.body?.cancel().catch(() => {
|
|
1166
1297
|
}), unavailable();
|
|
1167
1298
|
try {
|
|
@@ -1170,13 +1301,13 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1170
1301
|
throw response2.body?.cancel().catch(() => {
|
|
1171
1302
|
}), error;
|
|
1172
1303
|
}
|
|
1173
|
-
if (
|
|
1174
|
-
if (!
|
|
1175
|
-
let value = await result(response2,
|
|
1176
|
-
if (
|
|
1304
|
+
if (descriptor === 204) return;
|
|
1305
|
+
if (!descriptor) return response2;
|
|
1306
|
+
let value = await result(response2, descriptor === "control" ? CONTROL_RESULT_BYTES : RESULT_BYTES);
|
|
1307
|
+
if (descriptor === "control")
|
|
1177
1308
|
return checkCurrent(), value;
|
|
1178
1309
|
let parsed;
|
|
1179
|
-
if (
|
|
1310
|
+
if (descriptor === "enrichment") {
|
|
1180
1311
|
if (!value || typeof value != "object" || Array.isArray(value)) throw unavailable();
|
|
1181
1312
|
let { name, ...metadata } = value;
|
|
1182
1313
|
if (!safeEnrichmentName(name)) throw unavailable();
|
|
@@ -1191,22 +1322,22 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1191
1322
|
throw unavailable();
|
|
1192
1323
|
}
|
|
1193
1324
|
function idPath(id3) {
|
|
1194
|
-
if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw
|
|
1325
|
+
if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw invalid5();
|
|
1195
1326
|
return `/${id3}`;
|
|
1196
1327
|
}
|
|
1197
1328
|
async function multipartCreate(input, metadata, exchange, release = () => {
|
|
1198
1329
|
active--;
|
|
1199
1330
|
}, upload) {
|
|
1200
|
-
let route = upload ? `${idPath(upload.file.id)}/upload/multipart` : "/multipart", ticket, reader, chunk, offset = 0, receipts = [], pending = /* @__PURE__ */ new Set(),
|
|
1331
|
+
let route = upload ? `${idPath(upload.file.id)}/upload/multipart` : "/multipart", ticket, reader, chunk, offset = 0, receipts = [], pending = /* @__PURE__ */ new Set(), request2 = (work, timeout = TIMEOUT_MS) => timed((signal) => {
|
|
1201
1332
|
let task = work(signal);
|
|
1202
1333
|
return pending.add(task), task.then(() => pending.delete(task), () => pending.delete(task)), task;
|
|
1203
|
-
}, void 0, timeout), control = (
|
|
1334
|
+
}, void 0, timeout), control = (body) => ({
|
|
1204
1335
|
method: "POST",
|
|
1205
1336
|
headers: { "content-type": "application/json", ...ticket ? { "x-oddington-transfer": ticket } : {} },
|
|
1206
|
-
body: JSON.stringify(
|
|
1337
|
+
body: JSON.stringify(body)
|
|
1207
1338
|
});
|
|
1208
1339
|
try {
|
|
1209
|
-
let start = await
|
|
1340
|
+
let start = await request2((signal) => exchange(`${route}/start`, control(upload?.file ?? metadata), "control", signal));
|
|
1210
1341
|
if (!start || typeof start != "object" || Array.isArray(start)) throw unavailable();
|
|
1211
1342
|
let session = start;
|
|
1212
1343
|
if (Object.keys(session).sort().join(",") !== "partBytes,ticket" || session.partBytes !== PART_BYTES || typeof session.ticket != "string" || !session.ticket || session.ticket.length > 64 * 1024) throw unavailable();
|
|
@@ -1214,7 +1345,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1214
1345
|
let lastProgress = Date.now(), next = async () => {
|
|
1215
1346
|
try {
|
|
1216
1347
|
if (Date.now() - lastProgress >= TIMEOUT_MS) throw unavailable();
|
|
1217
|
-
let value = await
|
|
1348
|
+
let value = await request2(() => reader.read(), Math.max(1, TIMEOUT_MS - (Date.now() - lastProgress)));
|
|
1218
1349
|
return value.value?.byteLength && (lastProgress = Date.now()), value;
|
|
1219
1350
|
} catch (error) {
|
|
1220
1351
|
throw await reader.cancel(error).catch(() => {
|
|
@@ -1226,7 +1357,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1226
1357
|
if (input.file instanceof Uint8Array) part = input.file.subarray(sent, sent + length).slice();
|
|
1227
1358
|
else if (input.file instanceof Blob) {
|
|
1228
1359
|
let slice = input.file.slice(sent, sent + length);
|
|
1229
|
-
part = new Uint8Array(await
|
|
1360
|
+
part = new Uint8Array(await request2(() => slice.arrayBuffer()));
|
|
1230
1361
|
} else {
|
|
1231
1362
|
part = new Uint8Array(length);
|
|
1232
1363
|
let filled = 0;
|
|
@@ -1234,20 +1365,20 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1234
1365
|
if (!chunk || offset === chunk.byteLength) {
|
|
1235
1366
|
chunk = void 0, offset = 0;
|
|
1236
1367
|
let value2 = await next();
|
|
1237
|
-
if (value2.done || !(value2.value instanceof Uint8Array) || (chunk = value2.value, chunk.byteLength > metadata.size - sent - filled)) throw
|
|
1368
|
+
if (value2.done || !(value2.value instanceof Uint8Array) || (chunk = value2.value, chunk.byteLength > metadata.size - sent - filled)) throw invalid5();
|
|
1238
1369
|
}
|
|
1239
1370
|
let take = Math.min(length - filled, chunk.byteLength - offset);
|
|
1240
1371
|
part.set(chunk.subarray(offset, offset + take), filled), filled += take, offset += take, offset === chunk.byteLength && (chunk = void 0, offset = 0);
|
|
1241
1372
|
}
|
|
1242
1373
|
}
|
|
1243
|
-
if (part.byteLength !== length) throw
|
|
1374
|
+
if (part.byteLength !== length) throw invalid5();
|
|
1244
1375
|
if (reader && sent + length === metadata.size)
|
|
1245
1376
|
for (lastProgress = Date.now(); ; ) {
|
|
1246
1377
|
let value2 = await next();
|
|
1247
1378
|
if (value2.done) break;
|
|
1248
|
-
if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw
|
|
1379
|
+
if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw invalid5();
|
|
1249
1380
|
}
|
|
1250
|
-
let value = await
|
|
1381
|
+
let value = await request2((signal) => exchange(`${route}/part`, {
|
|
1251
1382
|
method: "POST",
|
|
1252
1383
|
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket, "x-oddington-part": String(partNumber) },
|
|
1253
1384
|
body: part.buffer
|
|
@@ -1258,9 +1389,9 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1258
1389
|
receipts.push({ partNumber, etag: receipt.etag }), sent += length, lastProgress = Date.now();
|
|
1259
1390
|
}
|
|
1260
1391
|
if (upload) for (let name of Object.keys(upload.file.enrichments)) {
|
|
1261
|
-
let bytes = await
|
|
1262
|
-
if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw
|
|
1263
|
-
await
|
|
1392
|
+
let bytes = await request2(() => upload.enrichment(name));
|
|
1393
|
+
if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw invalid5();
|
|
1394
|
+
await request2((signal) => exchange(`${route}/enrichments/${encodeURIComponent(name)}`, {
|
|
1264
1395
|
method: "POST",
|
|
1265
1396
|
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket },
|
|
1266
1397
|
body: bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)
|
|
@@ -1269,13 +1400,13 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1269
1400
|
await upload?.beforeComplete();
|
|
1270
1401
|
let completion = control({ parts: receipts });
|
|
1271
1402
|
if (new TextEncoder().encode(completion.body).byteLength > 128 * 1024) throw unavailable();
|
|
1272
|
-
return parseFileDescriptor(await
|
|
1403
|
+
return parseFileDescriptor(await request2(
|
|
1273
1404
|
(signal) => exchange(`${route}/complete`, completion, !0, signal),
|
|
1274
1405
|
TIMEOUT_MS + Math.ceil(metadata.size / (1024 * 1024)) * 1e3
|
|
1275
1406
|
));
|
|
1276
1407
|
} catch (error) {
|
|
1277
1408
|
throw reader && await reader.cancel(error).catch(() => {
|
|
1278
|
-
}), ticket && await
|
|
1409
|
+
}), ticket && await request2((signal) => exchange(`${route}/abort`, control({}), "control", signal)).catch(() => {
|
|
1279
1410
|
}), error instanceof FileOperationError ? error : unavailable();
|
|
1280
1411
|
} finally {
|
|
1281
1412
|
chunk = void 0, reader?.releaseLock(), pending.size ? Promise.allSettled([...pending]).then(release) : release();
|
|
@@ -1297,7 +1428,7 @@ async function operation(work, initial, parent) {
|
|
|
1297
1428
|
function contentPath(id3, name) {
|
|
1298
1429
|
let path = idPath(id3);
|
|
1299
1430
|
if (name === void 0) return `${path}/content`;
|
|
1300
|
-
if (!safeEnrichmentName(name)) throw
|
|
1431
|
+
if (!safeEnrichmentName(name)) throw invalid5();
|
|
1301
1432
|
return `${path}/enrichments/${encodeURIComponent(name)}/content`;
|
|
1302
1433
|
}
|
|
1303
1434
|
async function read(id3, names) {
|
|
@@ -1306,12 +1437,12 @@ async function read(id3, names) {
|
|
|
1306
1437
|
let path = contentPath(id3, names);
|
|
1307
1438
|
return operation((context3, signal) => send(path, { method: "GET" }, !1, context3, signal), context2);
|
|
1308
1439
|
}
|
|
1309
|
-
if (!Array.isArray(names)) throw
|
|
1440
|
+
if (!Array.isArray(names)) throw invalid5();
|
|
1310
1441
|
let distinct = [], seen = /* @__PURE__ */ new Set();
|
|
1311
1442
|
for (let name of names) {
|
|
1312
|
-
if (typeof name != "string" || !safeEnrichmentName(name)) throw
|
|
1443
|
+
if (typeof name != "string" || !safeEnrichmentName(name)) throw invalid5();
|
|
1313
1444
|
if (!seen.has(name)) {
|
|
1314
|
-
if (seen.size === 16) throw
|
|
1445
|
+
if (seen.size === 16) throw invalid5();
|
|
1315
1446
|
seen.add(name), distinct.push(name);
|
|
1316
1447
|
}
|
|
1317
1448
|
}
|
|
@@ -1346,11 +1477,11 @@ var files = {
|
|
|
1346
1477
|
async create(input, options) {
|
|
1347
1478
|
let context2 = await resolveFilesContext();
|
|
1348
1479
|
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")))
|
|
1349
|
-
throw
|
|
1480
|
+
throw invalid5();
|
|
1350
1481
|
let blob = input.file instanceof Blob, array3 = input.file instanceof Uint8Array, stream = input.file instanceof ReadableStream;
|
|
1351
|
-
if (!blob && !array3 && !stream) throw
|
|
1482
|
+
if (!blob && !array3 && !stream) throw invalid5();
|
|
1352
1483
|
let intrinsic = blob ? input.file.size : array3 ? input.file.byteLength : void 0;
|
|
1353
|
-
if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw
|
|
1484
|
+
if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw invalid5();
|
|
1354
1485
|
let name = input.name;
|
|
1355
1486
|
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));
|
|
1356
1487
|
let metadata = parseFileCreateMetadata({
|
|
@@ -1364,7 +1495,7 @@ var files = {
|
|
|
1364
1495
|
}, FILE_ORIGINAL_MAX_BYTES);
|
|
1365
1496
|
if (!context2.local && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
|
|
1366
1497
|
let header = encodeURIComponent(JSON.stringify(metadata));
|
|
1367
|
-
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw
|
|
1498
|
+
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid5();
|
|
1368
1499
|
if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
|
|
1369
1500
|
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) => {
|
|
1370
1501
|
try {
|
|
@@ -1372,7 +1503,7 @@ var files = {
|
|
|
1372
1503
|
blob ? input.file.stream() : input.file,
|
|
1373
1504
|
metadata.size
|
|
1374
1505
|
);
|
|
1375
|
-
if (bytes.byteLength !== metadata.size) throw
|
|
1506
|
+
if (bytes.byteLength !== metadata.size) throw invalid5();
|
|
1376
1507
|
if (signal.aborted) throw unavailable();
|
|
1377
1508
|
return await send("", {
|
|
1378
1509
|
method: "POST",
|
|
@@ -1388,7 +1519,7 @@ var files = {
|
|
|
1388
1519
|
},
|
|
1389
1520
|
async enrich(input) {
|
|
1390
1521
|
let context2 = await resolveFilesContext();
|
|
1391
|
-
if (!input || typeof input != "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "name", "content", "mediaType", "replace"].includes(key)) || typeof input.content != "string" && !(input.content instanceof Uint8Array)) throw
|
|
1522
|
+
if (!input || typeof input != "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "name", "content", "mediaType", "replace"].includes(key)) || typeof input.content != "string" && !(input.content instanceof Uint8Array)) throw invalid5();
|
|
1392
1523
|
let path = `${idPath(input.file)}/enrichments`;
|
|
1393
1524
|
if (typeof input.content == "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
|
|
1394
1525
|
throw new FileOperationError("request_too_large", 413);
|
|
@@ -1405,7 +1536,7 @@ var files = {
|
|
|
1405
1536
|
...input.mediaType === void 0 ? {} : { mediaType: input.mediaType },
|
|
1406
1537
|
...input.replace === void 0 ? {} : { replace: input.replace }
|
|
1407
1538
|
}, MAX_BYTES), header = encodeURIComponent(JSON.stringify(metadata));
|
|
1408
|
-
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw
|
|
1539
|
+
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid5();
|
|
1409
1540
|
let result2 = await send(path, { method: "POST", headers: {
|
|
1410
1541
|
"content-type": "application/octet-stream",
|
|
1411
1542
|
"x-oddington-enrichment": header
|
|
@@ -1441,8 +1572,8 @@ function parseConnectionLease(raw, now = Date.now()) {
|
|
|
1441
1572
|
}
|
|
1442
1573
|
|
|
1443
1574
|
var AirtableOperationError = class extends Error {
|
|
1444
|
-
constructor(
|
|
1445
|
-
super(
|
|
1575
|
+
constructor(message2, effect = "unapplied", receipts = []) {
|
|
1576
|
+
super(message2);
|
|
1446
1577
|
this.effect = effect;
|
|
1447
1578
|
this.receipts = receipts;
|
|
1448
1579
|
this.name = "AirtableOperationError";
|
|
@@ -1452,10 +1583,10 @@ var AirtableOperationError = class extends Error {
|
|
|
1452
1583
|
};
|
|
1453
1584
|
|
|
1454
1585
|
var recordId = (v) => typeof v == "string" && /^rec[A-Za-z0-9]+$/.test(v), tableId = (v) => typeof v == "string" && /^tbl[A-Za-z0-9]+$/.test(v);
|
|
1455
|
-
function fail2(
|
|
1456
|
-
throw new AirtableOperationError(
|
|
1586
|
+
function fail2(message2) {
|
|
1587
|
+
throw new AirtableOperationError(message2);
|
|
1457
1588
|
}
|
|
1458
|
-
function
|
|
1589
|
+
function object3(v) {
|
|
1459
1590
|
return (!v || typeof v != "object" || Array.isArray(v) || ![null, Object.prototype].includes(Object.getPrototypeOf(v))) && fail2("Invalid Airtable data"), v;
|
|
1460
1591
|
}
|
|
1461
1592
|
function keys2(v, allowed, required = allowed) {
|
|
@@ -1464,8 +1595,8 @@ function keys2(v, allowed, required = allowed) {
|
|
|
1464
1595
|
function text2(v) {
|
|
1465
1596
|
return typeof v == "string" && v.length > 0 && v.length <= 1024;
|
|
1466
1597
|
}
|
|
1467
|
-
function
|
|
1468
|
-
let result2 =
|
|
1598
|
+
function fields4(v, nonempty = !1) {
|
|
1599
|
+
let result2 = object3(v);
|
|
1469
1600
|
(nonempty && !Object.keys(result2).length || Object.keys(result2).some((k) => !text2(k))) && fail2("Invalid Airtable fields");
|
|
1470
1601
|
try {
|
|
1471
1602
|
return serializable(result2);
|
|
@@ -1474,8 +1605,8 @@ function fields3(v, nonempty = !1) {
|
|
|
1474
1605
|
}
|
|
1475
1606
|
}
|
|
1476
1607
|
function record2(v) {
|
|
1477
|
-
let r =
|
|
1478
|
-
return (!recordId(r.id) || r.createdTime !== void 0 && (typeof r.createdTime != "string" || !Number.isFinite(Date.parse(r.createdTime)))) && fail2("Malformed Airtable record"), { id: r.id, ...r.createdTime === void 0 ? {} : { createdTime: r.createdTime }, fields:
|
|
1608
|
+
let r = object3(v);
|
|
1609
|
+
return (!recordId(r.id) || r.createdTime !== void 0 && (typeof r.createdTime != "string" || !Number.isFinite(Date.parse(r.createdTime)))) && fail2("Malformed Airtable record"), { id: r.id, ...r.createdTime === void 0 ? {} : { createdTime: r.createdTime }, fields: fields4(r.fields) };
|
|
1479
1610
|
}
|
|
1480
1611
|
function equal(a, b) {
|
|
1481
1612
|
if (a === b) return !0;
|
|
@@ -1507,7 +1638,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1507
1638
|
(!/^[a-z0-9][a-z0-9-]{0,62}$/.test(name) || !/^app[A-Za-z0-9]+$/.test(baseId) || !/^[A-Za-z0-9._~+/-]{1,8192}={0,2}$/.test(accessToken)) && fail2("Airtable connection unavailable");
|
|
1508
1639
|
let input;
|
|
1509
1640
|
try {
|
|
1510
|
-
input =
|
|
1641
|
+
input = object3(serializable(raw));
|
|
1511
1642
|
} catch {
|
|
1512
1643
|
return fail2("Invalid Airtable input");
|
|
1513
1644
|
}
|
|
@@ -1519,7 +1650,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1519
1650
|
operation: operation2.slice(8),
|
|
1520
1651
|
records: ids2.map((id3) => ({ id: id3 }))
|
|
1521
1652
|
});
|
|
1522
|
-
async function
|
|
1653
|
+
async function request2(path2, init2 = {}, write = !1) {
|
|
1523
1654
|
let response2;
|
|
1524
1655
|
try {
|
|
1525
1656
|
response2 = await (options.fetch ?? fetch)(`https://api.airtable.com/v0/${path2}`, {
|
|
@@ -1536,7 +1667,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1536
1667
|
}), new AirtableOperationError("Airtable request rejected", write && (response2.status >= 500 || response2.status === 408 || response2.status < 400) ? "uncertain" : "unapplied");
|
|
1537
1668
|
try {
|
|
1538
1669
|
if (!response2.headers.get("content-type")?.toLowerCase().includes("application/json")) throw new Error();
|
|
1539
|
-
let value =
|
|
1670
|
+
let value = object3(await response2.json()), safe = serializable(value);
|
|
1540
1671
|
if (Object.hasOwn(value, "error") || JSON.stringify(safe).includes(accessToken)) throw new Error();
|
|
1541
1672
|
return value;
|
|
1542
1673
|
} catch {
|
|
@@ -1547,13 +1678,13 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1547
1678
|
keys2(input, []);
|
|
1548
1679
|
let tables = [], seen = /* @__PURE__ */ new Set(), offset;
|
|
1549
1680
|
do {
|
|
1550
|
-
let query2 = new URLSearchParams(offset ? { offset } : {}), page = await
|
|
1681
|
+
let query2 = new URLSearchParams(offset ? { offset } : {}), page = await request2(`meta/bases/${baseId}/tables?${query2}`);
|
|
1551
1682
|
Array.isArray(page.tables) || fail2("Malformed Airtable tables");
|
|
1552
1683
|
for (let value of page.tables) {
|
|
1553
|
-
let t =
|
|
1684
|
+
let t = object3(value);
|
|
1554
1685
|
(!tableId(t.id) || !text2(t.name) || !text2(t.primaryFieldId) || !Array.isArray(t.fields) || tables.some((existing) => existing.id === t.id)) && fail2("Malformed Airtable table");
|
|
1555
1686
|
let metadata = t.fields.map((value2) => {
|
|
1556
|
-
let f =
|
|
1687
|
+
let f = object3(value2);
|
|
1557
1688
|
return (typeof f.id != "string" || !/^fld[A-Za-z0-9]+$/.test(f.id) || !text2(f.name) || !text2(f.type)) && fail2("Malformed Airtable field"), { id: f.id, name: f.name, type: f.type, ...f.options === void 0 ? {} : { options: serializable(f.options) } };
|
|
1558
1689
|
});
|
|
1559
1690
|
(!metadata.some((f) => f.id === t.primaryFieldId) || new Set(metadata.map((f) => f.id)).size !== metadata.length) && fail2("Malformed Airtable fields"), tables.push({ id: t.id, name: t.name, primaryFieldId: t.primaryFieldId, fields: metadata });
|
|
@@ -1566,7 +1697,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1566
1697
|
let path = `${baseId}/${encodeURIComponent(input.table)}`;
|
|
1567
1698
|
if (operation2 === "records.get") {
|
|
1568
1699
|
keys2(input, ["table", "id"]), recordId(input.id) || fail2("Invalid Airtable record ID");
|
|
1569
|
-
let result3 = record2(await
|
|
1700
|
+
let result3 = record2(await request2(`${path}/${input.id}`));
|
|
1570
1701
|
return result3.id !== input.id && fail2("Malformed Airtable record"), result3;
|
|
1571
1702
|
}
|
|
1572
1703
|
if (operation2 === "records.list") {
|
|
@@ -1576,7 +1707,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1576
1707
|
let query2 = new URLSearchParams();
|
|
1577
1708
|
for (let field of input.fields ?? []) query2.append("fields[]", field);
|
|
1578
1709
|
offset && query2.set("offset", offset);
|
|
1579
|
-
let page = await
|
|
1710
|
+
let page = await request2(`${path}?${query2}`);
|
|
1580
1711
|
Array.isArray(page.records) || fail2("Malformed Airtable records");
|
|
1581
1712
|
for (let value of page.records) {
|
|
1582
1713
|
let r = record2(value);
|
|
@@ -1588,15 +1719,15 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1588
1719
|
}
|
|
1589
1720
|
mutation || fail2("Unsupported Airtable operation"), keys2(input, ["table", "records"]), (!Array.isArray(input.records) || !input.records.length || input.records.length > 10) && fail2("Invalid Airtable batch");
|
|
1590
1721
|
let kind = operation2.slice(8), ids = /* @__PURE__ */ new Set(), records = input.records.map((value) => {
|
|
1591
|
-
let r =
|
|
1592
|
-
if (keys2(r, kind === "create" ? ["fields"] : kind === "update" ? ["id", "expected", "set"] : ["id", "expected"]), kind === "create") return { fields:
|
|
1722
|
+
let r = object3(value);
|
|
1723
|
+
if (keys2(r, kind === "create" ? ["fields"] : kind === "update" ? ["id", "expected", "set"] : ["id", "expected"]), kind === "create") return { fields: fields4(r.fields, !0) };
|
|
1593
1724
|
(!recordId(r.id) || ids.has(r.id)) && fail2("Invalid Airtable batch record ID"), ids.add(r.id);
|
|
1594
|
-
let set = kind === "update" ?
|
|
1595
|
-
return set && Object.values(set).some((value2) => value2 === null) && fail2("Airtable guard null cannot be an update value"), { id: r.id, expected:
|
|
1725
|
+
let set = kind === "update" ? fields4(r.set, !0) : void 0;
|
|
1726
|
+
return set && Object.values(set).some((value2) => value2 === null) && fail2("Airtable guard null cannot be an update value"), { id: r.id, expected: fields4(r.expected), ...set ? { set } : {} };
|
|
1596
1727
|
});
|
|
1597
1728
|
for (let r of records) {
|
|
1598
1729
|
if (!("id" in r)) continue;
|
|
1599
|
-
let current2 = record2(await
|
|
1730
|
+
let current2 = record2(await request2(`${path}/${r.id}`));
|
|
1600
1731
|
current2.id !== r.id && fail2("Malformed Airtable record");
|
|
1601
1732
|
for (let [key, value] of Object.entries(r.expected))
|
|
1602
1733
|
(value === null ? Object.hasOwn(current2.fields, key) : !Object.hasOwn(current2.fields, key) || !equal(current2.fields[key], value)) && fail2("Airtable reviewed values are stale");
|
|
@@ -1604,14 +1735,14 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1604
1735
|
await options.beforeMutation?.();
|
|
1605
1736
|
let query = new URLSearchParams();
|
|
1606
1737
|
if (kind === "delete") for (let id3 of ids) query.append("records[]", id3);
|
|
1607
|
-
let result2 = await
|
|
1738
|
+
let result2 = await request2(`${path}${kind === "delete" ? `?${query}` : ""}`, {
|
|
1608
1739
|
method: kind === "create" ? "POST" : kind === "update" ? "PATCH" : "DELETE",
|
|
1609
1740
|
...kind === "delete" ? {} : { body: JSON.stringify({ records: records.map((r) => "id" in r ? { id: r.id, fields: r.set } : r) }) }
|
|
1610
1741
|
}, !0), acknowledged = [], returned = [];
|
|
1611
1742
|
try {
|
|
1612
1743
|
if (!Array.isArray(result2.records)) throw new Error();
|
|
1613
1744
|
for (let value of result2.records) {
|
|
1614
|
-
let r =
|
|
1745
|
+
let r = object3(value);
|
|
1615
1746
|
if (!recordId(r.id) || acknowledged.includes(r.id) || kind !== "create" && !ids.has(r.id) || kind === "delete" && r.deleted !== !0) throw new Error();
|
|
1616
1747
|
acknowledged.push(r.id), kind !== "delete" && returned.push(record2(r));
|
|
1617
1748
|
}
|
|
@@ -1713,8 +1844,8 @@ var connections = /* @__PURE__ */ createConnections(async (name, operation2, inp
|
|
|
1713
1844
|
var LOCAL_ROUTINE_VALUE_BYTES = 256 * 1024;
|
|
1714
1845
|
|
|
1715
1846
|
var RECORD_WRITE_INPUT_LIMIT = 8 * 1024 * 1024, RoutineRecordWriteError = class extends Error {
|
|
1716
|
-
constructor(
|
|
1717
|
-
super(
|
|
1847
|
+
constructor(message2, effect) {
|
|
1848
|
+
super(message2);
|
|
1718
1849
|
this.effect = effect;
|
|
1719
1850
|
this.name = "RoutineRecordWriteError";
|
|
1720
1851
|
}
|
|
@@ -1765,10 +1896,10 @@ function validateRecordChange(value) {
|
|
|
1765
1896
|
return writes.length && validateRecordWrite({ repository: input.repository, records: writes }), deletes.length && validateRecordDelete({ repository: input.repository, records: deletes }), structuredClone(input);
|
|
1766
1897
|
}
|
|
1767
1898
|
function validateRoutineRecordWrite(value) {
|
|
1768
|
-
let
|
|
1769
|
-
if (!
|
|
1899
|
+
let body = serializable(value);
|
|
1900
|
+
if (!body || typeof body != "object" || Array.isArray(body) || Object.keys(body).sort().join(",") !== "input,requestKey" || typeof body.requestKey != "string" || !body.requestKey.trim() || body.requestKey !== body.requestKey.trim() || body.requestKey.length > 512)
|
|
1770
1901
|
throw new InboxContractError("A stable routine request key is required");
|
|
1771
|
-
return { input: validateRecordChange(
|
|
1902
|
+
return { input: validateRecordChange(body.input), requestKey: body.requestKey };
|
|
1772
1903
|
}
|
|
1773
1904
|
function validCreatePath(value) {
|
|
1774
1905
|
return value === value.trim() && value.endsWith(".md") && !value.startsWith("/") && value.split("/").every((segment) => !!segment && ![".", ".."].includes(segment) && /^[a-zA-Z0-9_.-]+$/.test(segment));
|
|
@@ -1804,10 +1935,10 @@ var operations = {
|
|
|
1804
1935
|
function assert(value) {
|
|
1805
1936
|
if (!value) throw new Error("Invalid Inbox result");
|
|
1806
1937
|
}
|
|
1807
|
-
function
|
|
1938
|
+
function object4(value) {
|
|
1808
1939
|
return assert(value && typeof value == "object" && !Array.isArray(value) && [Object.prototype, null].includes(Object.getPrototypeOf(value)) && Reflect.ownKeys(value).every((key) => {
|
|
1809
|
-
let
|
|
1810
|
-
return !!
|
|
1940
|
+
let descriptor = typeof key == "string" ? Object.getOwnPropertyDescriptor(value, key) : void 0;
|
|
1941
|
+
return !!descriptor?.enumerable && "value" in descriptor;
|
|
1811
1942
|
})), value;
|
|
1812
1943
|
}
|
|
1813
1944
|
function keys3(value, allowed, required = allowed) {
|
|
@@ -1830,41 +1961,41 @@ function optionalDate(value) {
|
|
|
1830
1961
|
}
|
|
1831
1962
|
function array2(value) {
|
|
1832
1963
|
return assert(Array.isArray(value) && Object.getPrototypeOf(value) === Array.prototype && Reflect.ownKeys(value).length === value.length + 1 && value.every((_entry, index) => {
|
|
1833
|
-
let
|
|
1834
|
-
return !!
|
|
1964
|
+
let descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
1965
|
+
return !!descriptor?.enumerable && "value" in descriptor;
|
|
1835
1966
|
})), value;
|
|
1836
1967
|
}
|
|
1837
1968
|
function json2(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
1838
1969
|
if (value === null || typeof value == "boolean" || typeof value == "string" || typeof value == "number" && Number.isFinite(value)) return value;
|
|
1839
1970
|
assert(value && typeof value == "object" && !ancestors.has(value)), ancestors.add(value);
|
|
1840
1971
|
try {
|
|
1841
|
-
return Array.isArray(value) ? array2(value).map((entry) => json2(entry, ancestors)) : Object.fromEntries(Object.entries(
|
|
1972
|
+
return Array.isArray(value) ? array2(value).map((entry) => json2(entry, ancestors)) : Object.fromEntries(Object.entries(object4(value)).map(([key, entry]) => [key, json2(entry, ancestors)]));
|
|
1842
1973
|
} finally {
|
|
1843
1974
|
ancestors.delete(value);
|
|
1844
1975
|
}
|
|
1845
1976
|
}
|
|
1846
1977
|
function recordReference(value) {
|
|
1847
|
-
let record3 =
|
|
1978
|
+
let record3 = object4(value);
|
|
1848
1979
|
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;
|
|
1849
1980
|
}
|
|
1850
1981
|
function responseDefinition(value) {
|
|
1851
|
-
let definition =
|
|
1982
|
+
let definition = object4(value);
|
|
1852
1983
|
keys3(definition, ["type", "source"]), assert(definition.type === "selection");
|
|
1853
|
-
let source =
|
|
1984
|
+
let source = object4(definition.source);
|
|
1854
1985
|
if (source.type === "authored") {
|
|
1855
1986
|
keys3(source, ["type", "options", "suggestions", "search"], ["type", "options"]);
|
|
1856
1987
|
let options = array2(source.options);
|
|
1857
1988
|
assert(options.length > 0);
|
|
1858
1989
|
let values = options.map((value2) => {
|
|
1859
|
-
let option =
|
|
1990
|
+
let option = object4(value2);
|
|
1860
1991
|
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) {
|
|
1861
|
-
let note =
|
|
1992
|
+
let note = object4(option.note);
|
|
1862
1993
|
keys3(note, ["placeholder"]), assert(text3(note.placeholder));
|
|
1863
1994
|
}
|
|
1864
1995
|
return option.value;
|
|
1865
1996
|
});
|
|
1866
1997
|
if (assert(new Set(values).size === values.length), "search" in source || "suggestions" in source) {
|
|
1867
|
-
let search =
|
|
1998
|
+
let search = object4(source.search);
|
|
1868
1999
|
keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text3(search.triggerLabel) && text3(search.placeholder) && text3(search.emptyLabel));
|
|
1869
2000
|
let suggestions2 = array2(source.suggestions);
|
|
1870
2001
|
assert(suggestions2.length <= 8 && suggestions2.every((value2) => text3(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
|
|
@@ -1872,16 +2003,16 @@ function responseDefinition(value) {
|
|
|
1872
2003
|
return;
|
|
1873
2004
|
}
|
|
1874
2005
|
assert(source.type === "records"), keys3(source, ["type", "collection", "refPrefix", "where", "display", "suggestions"], ["type", "collection", "display"]);
|
|
1875
|
-
let collection =
|
|
2006
|
+
let collection = object4(source.collection);
|
|
1876
2007
|
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));
|
|
1877
|
-
let where =
|
|
2008
|
+
let where = object4(source.where ?? {});
|
|
1878
2009
|
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))));
|
|
1879
|
-
let display =
|
|
2010
|
+
let display = object4(source.display);
|
|
1880
2011
|
keys3(display, ["labelFields"]);
|
|
1881
2012
|
let labels = array2(display.labelFields);
|
|
1882
2013
|
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)));
|
|
1883
2014
|
let suggestions = array2(source.suggestions ?? []), refs = suggestions.map((value2) => {
|
|
1884
|
-
let suggestion =
|
|
2015
|
+
let suggestion = object4(value2);
|
|
1885
2016
|
keys3(suggestion, ["record", "reason"], ["record"]);
|
|
1886
2017
|
let record3 = recordReference(suggestion.record);
|
|
1887
2018
|
return assert(record3.repository === collection.repository), "reason" in suggestion && assert(text3(suggestion.reason)), record3.ref;
|
|
@@ -1889,20 +2020,20 @@ function responseDefinition(value) {
|
|
|
1889
2020
|
assert(suggestions.length <= 8 && new Set(refs).size === refs.length);
|
|
1890
2021
|
}
|
|
1891
2022
|
function inboxFile(value) {
|
|
1892
|
-
let file2 =
|
|
2023
|
+
let file2 = object4(value);
|
|
1893
2024
|
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));
|
|
1894
|
-
let details =
|
|
2025
|
+
let details = object4(file2.details);
|
|
1895
2026
|
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)));
|
|
1896
2027
|
}
|
|
1897
|
-
function
|
|
2028
|
+
function fields5(value) {
|
|
1898
2029
|
let labels = array2(value).map((value2) => {
|
|
1899
|
-
let field =
|
|
2030
|
+
let field = object4(value2);
|
|
1900
2031
|
return keys3(field, ["label", "value"]), assert(text3(field.label) && text3(field.value)), field.label;
|
|
1901
2032
|
});
|
|
1902
2033
|
assert(new Set(labels).size === labels.length);
|
|
1903
2034
|
}
|
|
1904
2035
|
function block(value) {
|
|
1905
|
-
let entry =
|
|
2036
|
+
let entry = object4(value);
|
|
1906
2037
|
if (entry.kind === "rich-text") {
|
|
1907
2038
|
keys3(entry, ["kind", "markdown"]), assert(text3(entry.markdown));
|
|
1908
2039
|
return;
|
|
@@ -1918,112 +2049,112 @@ function block(value) {
|
|
|
1918
2049
|
["kind", "label", "initiallyExpanded", ...entry.kind === "record" ? ["record", "view"] : entry.kind === "records" ? ["records", "view"] : ["files"]],
|
|
1919
2050
|
["kind", "label", entry.kind === "record" ? "record" : entry.kind === "records" ? "records" : "files"]
|
|
1920
2051
|
), 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") {
|
|
1921
|
-
let record3 =
|
|
1922
|
-
keys3(record3, ["ref", "title", "fields"]), assert(text3(record3.ref) && record3.ref === record3.ref.trim() && text3(record3.title)),
|
|
2052
|
+
let record3 = object4(entry.record);
|
|
2053
|
+
keys3(record3, ["ref", "title", "fields"]), assert(text3(record3.ref) && record3.ref === record3.ref.trim() && text3(record3.title)), fields5(record3.fields);
|
|
1923
2054
|
return;
|
|
1924
2055
|
}
|
|
1925
2056
|
if (entry.kind === "records") {
|
|
1926
2057
|
let records = array2(entry.records), refs = records.map((value2) => {
|
|
1927
|
-
let record3 =
|
|
1928
|
-
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 &&
|
|
2058
|
+
let record3 = object4(value2);
|
|
2059
|
+
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 && fields5(record3.facts), "view" in record3 && assert(text3(record3.view) && record3.view === record3.view.trim()), record3.ref;
|
|
1929
2060
|
});
|
|
1930
2061
|
assert(records.length > 0 && new Set(refs).size === refs.length);
|
|
1931
2062
|
return;
|
|
1932
2063
|
}
|
|
1933
2064
|
let files3 = array2(entry.files);
|
|
1934
|
-
files3.forEach(inboxFile), assert(files3.length > 0 && new Set(files3.map((value2) =>
|
|
2065
|
+
files3.forEach(inboxFile), assert(files3.length > 0 && new Set(files3.map((value2) => object4(value2).id)).size === files3.length);
|
|
1935
2066
|
}
|
|
1936
2067
|
function response(value) {
|
|
1937
|
-
let answer =
|
|
2068
|
+
let answer = object4(value);
|
|
1938
2069
|
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;
|
|
1939
2070
|
}
|
|
1940
|
-
function parseInboxRequest(value) {
|
|
2071
|
+
function parseInboxRequest(value, questionListContext = "local") {
|
|
1941
2072
|
try {
|
|
1942
|
-
let envelope =
|
|
2073
|
+
let envelope = object4(value);
|
|
1943
2074
|
assert(Object.keys(envelope).sort().join(",") === "input,operation"), assert(typeof envelope.operation == "string" && Object.hasOwn(operations, envelope.operation));
|
|
1944
|
-
let operation2 = envelope.operation, input =
|
|
1945
|
-
assert(required.every((key) => Object.hasOwn(input, key)) && Object.keys(input).every((key) => required.includes(key) || operation2 === "questions.searchRecords" && key === "selected" || (operation2 === "items.list" || operation2 === "questions.list") && key === "beforeNumber"));
|
|
2075
|
+
let operation2 = envelope.operation, input = { ...object4(envelope.input) }, required = operations[operation2];
|
|
2076
|
+
assert(required.every((key) => Object.hasOwn(input, key)) && Object.keys(input).every((key) => required.includes(key) || operation2 === "questions.searchRecords" && key === "selected" || (operation2 === "items.list" || operation2 === "questions.list") && key === "beforeNumber" || operation2 === "questions.list" && questionListContext === "hosted" && key === "routines")), operation2 === "questions.list" && questionListContext === "hosted" && (assert(Object.hasOwn(input, "routines")), assert(array2(input.routines).every(isAppRoutineName)));
|
|
1946
2077
|
for (let key of ["itemId", "personId", "fileId"]) key in input && assert(id2(input[key]));
|
|
1947
|
-
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 };
|
|
2078
|
+
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), "routines" in input && (input.routines = [...new Set(input.routines)]), { operation: operation2, input };
|
|
1948
2079
|
} catch {
|
|
1949
2080
|
throw new InboxOperationError(400, "invalid_input");
|
|
1950
2081
|
}
|
|
1951
2082
|
}
|
|
1952
2083
|
function parseInboxCurrent(value) {
|
|
1953
|
-
let current2 =
|
|
2084
|
+
let current2 = object4(value), workspace = object4(current2.workspace), viewer = object4(current2.viewer);
|
|
1954
2085
|
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)), {
|
|
1955
2086
|
workspace: { id: workspace.id, slug: workspace.slug, name: workspace.name, locale: workspace.locale, timezone: workspace.timezone },
|
|
1956
2087
|
viewer: { id: viewer.id, name: viewer.name, email: viewer.email }
|
|
1957
2088
|
};
|
|
1958
2089
|
}
|
|
1959
2090
|
function parseInboxItem(value) {
|
|
1960
|
-
let item =
|
|
1961
|
-
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(
|
|
1962
|
-
let view =
|
|
2091
|
+
let item = object4(json2(value));
|
|
2092
|
+
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)), array2(item.body).forEach(block), array2(item.views).forEach((value2) => {
|
|
2093
|
+
let view = object4(value2);
|
|
1963
2094
|
assert(text3(view.id) && text3(view.view) && text3(view.implementation)), json2(view.input);
|
|
1964
2095
|
}), array2(item.people).forEach((value2) => {
|
|
1965
|
-
let person =
|
|
2096
|
+
let person = object4(value2);
|
|
1966
2097
|
assert(id2(person.id) && text3(person.name));
|
|
1967
2098
|
}), array2(item.questions).forEach((value2) => {
|
|
1968
|
-
let question2 =
|
|
2099
|
+
let question2 = object4(value2);
|
|
1969
2100
|
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) {
|
|
1970
|
-
let accepted =
|
|
2101
|
+
let accepted = object4(question2.acceptedResponse);
|
|
1971
2102
|
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));
|
|
1972
2103
|
}
|
|
1973
2104
|
if (question2.execution !== null) {
|
|
1974
|
-
let execution =
|
|
2105
|
+
let execution = object4(question2.execution);
|
|
1975
2106
|
if (assert(id2(execution.id) && ["pending", "running", "completed", "failed"].includes(String(execution.state)) && integer(execution.attempt, 0)), "consequence" in execution) {
|
|
1976
|
-
let consequence =
|
|
2107
|
+
let consequence = object4(execution.consequence);
|
|
1977
2108
|
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) => {
|
|
1978
|
-
let receipt =
|
|
2109
|
+
let receipt = object4(value3);
|
|
1979
2110
|
assert(text3(receipt.repository) && text3(receipt.commit) && text3(receipt.diff, !0));
|
|
1980
2111
|
});
|
|
1981
2112
|
}
|
|
1982
2113
|
}
|
|
1983
2114
|
}), array2(item.linkedAsks).forEach((value2) => {
|
|
1984
|
-
let linked =
|
|
2115
|
+
let linked = object4(value2);
|
|
1985
2116
|
if (assert(id2(linked.id)), linked.state === "unavailable") assert(typeof linked.done == "boolean");
|
|
1986
2117
|
else if (assert(["yours", "done", "open", "theirs"].includes(String(linked.state)) && text3(linked.title)), linked.state === "theirs") {
|
|
1987
|
-
let assignee =
|
|
2118
|
+
let assignee = object4(linked.assignee);
|
|
1988
2119
|
assert(id2(assignee.id) && text3(assignee.name));
|
|
1989
2120
|
}
|
|
1990
2121
|
}), array2(item.activity).forEach((value2) => {
|
|
1991
|
-
let
|
|
1992
|
-
assert(integer(
|
|
2122
|
+
let event = object4(value2);
|
|
2123
|
+
assert(integer(event.id) && text3(event.type) && (event.actorId === null || id2(event.actorId)) && (event.questionId === null || text3(event.questionId)) && integer(event.revision) && date(event.createdAt)), object4(event.data);
|
|
1993
2124
|
}), array2(item.work).forEach((value2) => {
|
|
1994
|
-
let work =
|
|
2125
|
+
let work = object4(value2);
|
|
1995
2126
|
assert(id2(work.id) && text3(work.questionId) && text3(work.reason) && optionalDate(work.settledAt));
|
|
1996
2127
|
}), item;
|
|
1997
2128
|
}
|
|
1998
2129
|
function parseAnswerableQuestion(value) {
|
|
1999
|
-
let entry =
|
|
2130
|
+
let entry = object4(json2(value));
|
|
2000
2131
|
keys3(entry, ["item", "origin", "question", "recordRefs"]);
|
|
2001
|
-
let item =
|
|
2132
|
+
let item = object4(entry.item);
|
|
2002
2133
|
keys3(item, ["id", "number", "revision", "title", "href"]), assert(id2(item.id) && integer(item.number) && integer(item.revision) && text3(item.title) && text3(item.href));
|
|
2003
2134
|
let link = new URL(item.href), slug = link.hostname.slice(0, -13);
|
|
2004
2135
|
assert(link.hostname.endsWith(".oddington.ai") && slug.length <= 63 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug) && !["auth", "www", "api", "os"].includes(slug) && item.href === `https://${slug}.oddington.ai/inbox/${item.id}`);
|
|
2005
|
-
let origin =
|
|
2136
|
+
let origin = object4(entry.origin);
|
|
2006
2137
|
keys3(origin, ["routine"]), assert(text3(origin.routine) && origin.routine === origin.routine.trim());
|
|
2007
|
-
let question2 =
|
|
2138
|
+
let question2 = object4(entry.question);
|
|
2008
2139
|
keys3(question2, ["id", "prompt", "instructions", "response"]), assert(text3(question2.id) && question2.id === question2.id.trim() && text3(question2.prompt) && (question2.instructions === null || text3(question2.instructions, !0))), responseDefinition(question2.response);
|
|
2009
2140
|
let refs = array2(entry.recordRefs);
|
|
2010
2141
|
return assert(refs.every((ref) => text3(ref) && ref === ref.trim()) && new Set(refs).size === refs.length), entry;
|
|
2011
2142
|
}
|
|
2012
2143
|
function parseInboxAcceptance(value) {
|
|
2013
|
-
let accepted =
|
|
2144
|
+
let accepted = object4(value);
|
|
2014
2145
|
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;
|
|
2015
2146
|
}
|
|
2016
2147
|
function parseInboxResult(operation2, value) {
|
|
2017
2148
|
if (operation2 === "current") return parseInboxCurrent(value);
|
|
2018
2149
|
if (operation2 === "questions.list") {
|
|
2019
|
-
let page =
|
|
2150
|
+
let page = object4(value);
|
|
2020
2151
|
keys3(page, ["questions", "nextBeforeNumber"]);
|
|
2021
2152
|
let questions = array2(page.questions).map(parseAnswerableQuestion);
|
|
2022
2153
|
return assert(page.nextBeforeNumber === null || integer(page.nextBeforeNumber)), { questions, nextBeforeNumber: page.nextBeforeNumber };
|
|
2023
2154
|
}
|
|
2024
2155
|
if (operation2 === "items.read") return parseInboxItem(value);
|
|
2025
2156
|
if (operation2 === "items.list") {
|
|
2026
|
-
let page =
|
|
2157
|
+
let page = object4(value), items = array2(page.items).map(parseInboxItem);
|
|
2027
2158
|
return assert(items.length <= 100 && (page.nextBeforeNumber === null || integer(page.nextBeforeNumber))), { items, nextBeforeNumber: page.nextBeforeNumber };
|
|
2028
2159
|
}
|
|
2029
2160
|
if (operation2 === "items.see") {
|
|
@@ -2031,30 +2162,30 @@ function parseInboxResult(operation2, value) {
|
|
|
2031
2162
|
return;
|
|
2032
2163
|
}
|
|
2033
2164
|
if (operation2 === "items.markDigestRead") {
|
|
2034
|
-
let read2 =
|
|
2165
|
+
let read2 = object4(value);
|
|
2035
2166
|
return assert(integer(read2.activityId) && date(read2.readAt)), read2;
|
|
2036
2167
|
}
|
|
2037
2168
|
if (operation2 === "items.rename" || operation2 === "items.setLifecycle") {
|
|
2038
|
-
let update =
|
|
2169
|
+
let update = object4(value), item = parseInboxItem(update.item);
|
|
2039
2170
|
return assert((update.activityId === null || integer(update.activityId)) && optionalDate(update.changedAt)), { ...update, item };
|
|
2040
2171
|
}
|
|
2041
2172
|
if (operation2 === "items.listRecipientCandidates") {
|
|
2042
2173
|
let candidates = array2(value);
|
|
2043
2174
|
return candidates.forEach((value2) => {
|
|
2044
|
-
let person =
|
|
2175
|
+
let person = object4(value2);
|
|
2045
2176
|
assert(id2(person.id) && text3(person.name) && text3(person.email));
|
|
2046
|
-
}), assert(new Set(candidates.map((value2) =>
|
|
2177
|
+
}), assert(new Set(candidates.map((value2) => object4(value2).id)).size === candidates.length), candidates;
|
|
2047
2178
|
}
|
|
2048
2179
|
if (operation2 === "items.addRecipient") {
|
|
2049
|
-
let addition =
|
|
2180
|
+
let addition = object4(value), item = parseInboxItem(addition.item);
|
|
2050
2181
|
return assert(id2(addition.addedPersonId) && item.people.some((person) => person.id === addition.addedPersonId)), { ...addition, item };
|
|
2051
2182
|
}
|
|
2052
2183
|
if (operation2 === "questions.answer") return parseInboxAcceptance(value);
|
|
2053
2184
|
if (operation2 === "questions.searchRecords") {
|
|
2054
|
-
let result2 =
|
|
2185
|
+
let result2 = object4(value);
|
|
2055
2186
|
assert(text3(result2.recordType) && integer(result2.eligibleCount, 0) && integer(result2.matchCount, 0) && Number(result2.matchCount) <= Number(result2.eligibleCount));
|
|
2056
2187
|
let labeled = (value2) => {
|
|
2057
|
-
let record3 =
|
|
2188
|
+
let record3 = object4(value2);
|
|
2058
2189
|
recordReference({ repository: record3.repository, ref: record3.ref }), assert(text3(record3.label)), "reason" in record3 && assert(text3(record3.reason));
|
|
2059
2190
|
};
|
|
2060
2191
|
return array2(result2.matches).forEach(labeled), array2(result2.suggestions).forEach(labeled), "selected" in result2 && labeled(result2.selected), result2;
|
|
@@ -2062,9 +2193,9 @@ function parseInboxResult(operation2, value) {
|
|
|
2062
2193
|
throw new Error("File content is not a JSON result");
|
|
2063
2194
|
}
|
|
2064
2195
|
|
|
2065
|
-
async function limitedBody(
|
|
2066
|
-
if (!
|
|
2067
|
-
let reader =
|
|
2196
|
+
async function limitedBody(request2, limit, timeoutMs) {
|
|
2197
|
+
if (!request2.body) return new Uint8Array();
|
|
2198
|
+
let reader = request2.body.getReader(), expired = !1, timer = timeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
2068
2199
|
expired = !0, reader.cancel().catch(() => {
|
|
2069
2200
|
});
|
|
2070
2201
|
}, timeoutMs), chunks = [], length = 0;
|
|
@@ -2209,7 +2340,7 @@ function appContext(origin, active2) {
|
|
|
2209
2340
|
}
|
|
2210
2341
|
}, cancel = () => {
|
|
2211
2342
|
controller.abort(), access.abort(), clearTimeout(expiry), clearTimeout(startup), clearTimeout(renewalTimer), clearInterval(monitor), globalThis.removeEventListener?.("storage", storageChanged);
|
|
2212
|
-
for (let
|
|
2343
|
+
for (let event of ["pageshow", "focus", "visibilitychange"]) globalThis.removeEventListener?.(event, wake);
|
|
2213
2344
|
}, invalidate = () => {
|
|
2214
2345
|
denied = !0, cancel();
|
|
2215
2346
|
try {
|
|
@@ -2222,7 +2353,7 @@ function appContext(origin, active2) {
|
|
|
2222
2353
|
} catch {
|
|
2223
2354
|
return !1;
|
|
2224
2355
|
}
|
|
2225
|
-
}, sameSession = (value) => !binding || ["appId", "memberId", "workspace", "sessionId"].every((key) => value[key] === binding[key]),
|
|
2356
|
+
}, sameSession = (value) => !binding || ["appId", "memberId", "workspace", "sessionId"].every((key) => value[key] === binding[key]), bounded2 = (value) => validBinding(value) && value.expiresAt > Date.now() && value.expiresAt <= Date.now() + 6e5 && sameSession(value), readPair = (candidate) => {
|
|
2226
2357
|
let value = JSON.parse(candidate ?? "null");
|
|
2227
2358
|
if (!validPair(value) || value.context.expiresAt > Date.now() + 6e5 || !sameSession(value.context)) throw new Error();
|
|
2228
2359
|
return value;
|
|
@@ -2257,7 +2388,7 @@ function appContext(origin, active2) {
|
|
|
2257
2388
|
if (response2.status >= 500) throw new AppRenewalUnavailable();
|
|
2258
2389
|
if (!response2.ok) throw new Error();
|
|
2259
2390
|
let value = await appResponse(response2, 4096, signal);
|
|
2260
|
-
if (!alive() || !
|
|
2391
|
+
if (!alive() || !bounded2(value)) throw new Error();
|
|
2261
2392
|
return value;
|
|
2262
2393
|
}
|
|
2263
2394
|
function install(value, candidate, raw) {
|
|
@@ -2329,7 +2460,7 @@ function appContext(origin, active2) {
|
|
|
2329
2460
|
return;
|
|
2330
2461
|
}
|
|
2331
2462
|
if (!response2.ok) throw new Error();
|
|
2332
|
-
if (!alive() || !validPair(value) || !
|
|
2463
|
+
if (!alive() || !validPair(value) || !bounded2(value.context) || (/* @__PURE__ */ new Set([value.credential, value.renewalCredential, pair.credential, pair.renewalCredential])).size !== 4) throw new Error();
|
|
2333
2464
|
if (stored() !== previous) {
|
|
2334
2465
|
await synchronize(requestController.signal);
|
|
2335
2466
|
return;
|
|
@@ -2378,7 +2509,7 @@ function appContext(origin, active2) {
|
|
|
2378
2509
|
alive() && resolve().catch(() => {
|
|
2379
2510
|
});
|
|
2380
2511
|
};
|
|
2381
|
-
for (let
|
|
2512
|
+
for (let event of ["pageshow", "focus", "visibilitychange"]) globalThis.addEventListener?.(event, wake);
|
|
2382
2513
|
let dispose = () => {
|
|
2383
2514
|
disposed = !0, cancel();
|
|
2384
2515
|
};
|
|
@@ -2493,13 +2624,13 @@ function hostFailure(error, context2) {
|
|
|
2493
2624
|
return !context2.isCurrent() || context2.expiresAt <= Date.now() || error instanceof InboxContextError && error.status === 401 ? stale() : error instanceof InboxContextError && error.status === 403 ? new InboxOperationError(403, "access_denied") : unavailable2();
|
|
2494
2625
|
}
|
|
2495
2626
|
async function send2(operation2, input) {
|
|
2496
|
-
let envelope = parseInboxRequest({ operation: operation2, input }), context2;
|
|
2627
|
+
let envelope = operation2 === "questions.list" ? void 0 : parseInboxRequest({ operation: operation2, input }), context2;
|
|
2497
2628
|
try {
|
|
2498
2629
|
context2 = await resolveAppContext();
|
|
2499
2630
|
} catch {
|
|
2500
2631
|
throw stale();
|
|
2501
2632
|
}
|
|
2502
|
-
if (context2.kind === "local") {
|
|
2633
|
+
if (envelope ??= parseInboxRequest({ operation: operation2, input }, context2.kind === "local" ? "local" : "hosted"), context2.kind === "local") {
|
|
2503
2634
|
if (!isAppQuestionOperation(operation2)) throw new InboxOperationError(403, "access_denied");
|
|
2504
2635
|
let check2 = () => {
|
|
2505
2636
|
if (!context2.isCurrent() || context2.signal.aborted || context2.expiresAt <= Date.now()) throw stale();
|
|
@@ -2563,7 +2694,7 @@ async function send2(operation2, input) {
|
|
|
2563
2694
|
} finally {
|
|
2564
2695
|
reader?.releaseLock();
|
|
2565
2696
|
}
|
|
2566
|
-
},
|
|
2697
|
+
}, body = new ReadableStream({
|
|
2567
2698
|
async pull(controller) {
|
|
2568
2699
|
try {
|
|
2569
2700
|
check(), reader ??= source.getReader();
|
|
@@ -2581,7 +2712,7 @@ async function send2(operation2, input) {
|
|
|
2581
2712
|
},
|
|
2582
2713
|
cancel
|
|
2583
2714
|
}, { highWaterMark: 0 });
|
|
2584
|
-
return new Response(
|
|
2715
|
+
return new Response(body, { status: response2.status, headers: response2.headers });
|
|
2585
2716
|
}
|
|
2586
2717
|
let bytes = await limitedBody(response2, INBOX_RESULT_BYTES);
|
|
2587
2718
|
if (check(), !bytes) throw unavailable2();
|
|
@@ -2636,13 +2767,17 @@ var inbox = {
|
|
|
2636
2767
|
addRecipient: async (input) => await send2("items.addRecipient", input)
|
|
2637
2768
|
},
|
|
2638
2769
|
questions: {
|
|
2639
|
-
async list() {
|
|
2640
|
-
let
|
|
2770
|
+
async list(input) {
|
|
2771
|
+
let supplied = input === void 0 ? void 0 : parseInboxRequest({ operation: "questions.list", input }, "hosted").input;
|
|
2772
|
+
if (supplied && Object.hasOwn(supplied, "beforeNumber")) throw new InboxOperationError(400, "invalid_input");
|
|
2773
|
+
let routines = supplied ? Object.freeze(supplied.routines) : void 0, questions = [], beforeNumber, initial;
|
|
2641
2774
|
try {
|
|
2642
2775
|
initial = await resolveAppContext();
|
|
2643
2776
|
} catch {
|
|
2644
2777
|
throw stale();
|
|
2645
2778
|
}
|
|
2779
|
+
if (initial.kind === "local" ? input !== void 0 : routines === void 0)
|
|
2780
|
+
throw new InboxOperationError(400, "invalid_input");
|
|
2646
2781
|
let host;
|
|
2647
2782
|
try {
|
|
2648
2783
|
host = initial.kind !== "local" && await resolveHostedInboxContext(initial);
|
|
@@ -2655,8 +2790,11 @@ var inbox = {
|
|
|
2655
2790
|
};
|
|
2656
2791
|
do {
|
|
2657
2792
|
check();
|
|
2658
|
-
let page = await send2("questions.list",
|
|
2659
|
-
|
|
2793
|
+
let page = await send2("questions.list", {
|
|
2794
|
+
...routines === void 0 ? {} : { routines },
|
|
2795
|
+
...beforeNumber === void 0 ? {} : { beforeNumber }
|
|
2796
|
+
});
|
|
2797
|
+
if (check(), page.questions.some((question2) => question2.item.href !== `https://${initial.workspace}.oddington.ai/inbox/${question2.item.id}` || routines !== void 0 && !routines.includes(question2.origin.routine)) || beforeNumber !== void 0 && (page.questions.some((question2) => question2.item.number >= beforeNumber) || page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber)) throw unavailable2();
|
|
2660
2798
|
if (questions.push(...page.questions), page.nextBeforeNumber === null) return questions;
|
|
2661
2799
|
beforeNumber = page.nextBeforeNumber;
|
|
2662
2800
|
} while (!0);
|
|
@@ -2693,8 +2831,8 @@ function init({ auth: input }) {
|
|
|
2693
2831
|
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);
|
|
2694
2832
|
} catch {
|
|
2695
2833
|
}
|
|
2696
|
-
let active2 = !0, revision = 0, person, token, binding = {},
|
|
2697
|
-
if (
|
|
2834
|
+
let active2 = !0, revision = 0, person, token, binding = {}, local2 = localOrigin ? appContext(localOrigin, () => active2) : void 0, subscription, stopDisposal, uninstall = installMemberContext(async () => {
|
|
2835
|
+
if (local2) return local2.resolve();
|
|
2698
2836
|
if (!active2 || !endpoint || !workspace || globalThis.location.origin !== endpoint) throw new Error("Hosted Data context unavailable.");
|
|
2699
2837
|
let started = revision, { data: { session }, error } = await auth2.getSession();
|
|
2700
2838
|
if (!active2 || globalThis.location.origin !== endpoint || started !== revision || error || !session || person !== void 0 && person !== session.user.id)
|
|
@@ -2714,12 +2852,12 @@ function init({ auth: input }) {
|
|
|
2714
2852
|
binding
|
|
2715
2853
|
};
|
|
2716
2854
|
}), dispose = () => {
|
|
2717
|
-
active2 && (active2 = !1,
|
|
2855
|
+
active2 && (active2 = !1, local2?.dispose(), revision++, subscription?.unsubscribe(), stopDisposal?.(), uninstall(), installedDispose === dispose && (installedDispose = void 0));
|
|
2718
2856
|
};
|
|
2719
|
-
installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (subscription = auth2.onAuthStateChange((
|
|
2857
|
+
installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (subscription = auth2.onAuthStateChange((event, session) => {
|
|
2720
2858
|
let next = session?.user.id ?? null;
|
|
2721
|
-
(
|
|
2722
|
-
}).data.subscription,
|
|
2859
|
+
(event === "SIGNED_OUT" || person !== void 0 && next !== person || registered && person !== void 0 && event === "SIGNED_IN" && token !== session?.access_token) && (revision++, local2?.invalidate()), person = next, token = session?.access_token;
|
|
2860
|
+
}).data.subscription, local2?.start());
|
|
2723
2861
|
}
|
|
2724
2862
|
var os = { init };
|
|
2725
2863
|
|
|
@@ -2769,19 +2907,19 @@ function createBrowserAuth(runtime) {
|
|
|
2769
2907
|
} catch {
|
|
2770
2908
|
}
|
|
2771
2909
|
}
|
|
2772
|
-
function notify(c,
|
|
2910
|
+
function notify(c, event) {
|
|
2773
2911
|
for (let listener of c.sessions)
|
|
2774
2912
|
try {
|
|
2775
|
-
listener(
|
|
2913
|
+
listener(event, event === "SIGNED_OUT" ? null : c.session);
|
|
2776
2914
|
} catch {
|
|
2777
2915
|
}
|
|
2778
2916
|
}
|
|
2779
2917
|
function expire(c) {
|
|
2780
2918
|
!c.active || !c.session && c.state.status === "expired" || (c.revision++, c.timer && clearTimeout(c.timer), c.session = null, publish(c, { status: "expired" }), notify(c, "SIGNED_OUT"));
|
|
2781
2919
|
}
|
|
2782
|
-
function accept(c,
|
|
2783
|
-
if (!c.active ||
|
|
2784
|
-
let replaced = c.session?.user?.id !== session?.user?.id ||
|
|
2920
|
+
function accept(c, event, session) {
|
|
2921
|
+
if (!c.active || event === "INITIAL_SESSION" && c.state.status !== "initializing" || event === "TOKEN_REFRESHED" && !c.session && c.state.status !== "initializing") return;
|
|
2922
|
+
let replaced = c.session?.user?.id !== session?.user?.id || event === "SIGNED_OUT" || !!(event === "SIGNED_IN" && c.session && session?.access_token !== c.session.access_token);
|
|
2785
2923
|
replaced && c.revision++, c.timer && clearTimeout(c.timer);
|
|
2786
2924
|
let pending = c.state.pending;
|
|
2787
2925
|
if (!session) {
|
|
@@ -2794,7 +2932,7 @@ function createBrowserAuth(runtime) {
|
|
|
2794
2932
|
}
|
|
2795
2933
|
c.session = session;
|
|
2796
2934
|
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 });
|
|
2797
|
-
publish(c, { status: "signed_in", account, ...pending ? { pending } : {} }), notify(c,
|
|
2935
|
+
publish(c, { status: "signed_in", account, ...pending ? { pending } : {} }), notify(c, event);
|
|
2798
2936
|
let checkExpiry = () => {
|
|
2799
2937
|
if (!c.active || !c.session) return;
|
|
2800
2938
|
let remaining = c.session.expires_at * 1e3 - Date.now();
|
|
@@ -2834,8 +2972,8 @@ function createBrowserAuth(runtime) {
|
|
|
2834
2972
|
c.provider.dispose();
|
|
2835
2973
|
return;
|
|
2836
2974
|
}
|
|
2837
|
-
let subscription = c.provider.onAuthStateChange((
|
|
2838
|
-
c.state.status === "initializing" && c.state.pending === "sign_out" || accept(c,
|
|
2975
|
+
let subscription = c.provider.onAuthStateChange((event, session) => {
|
|
2976
|
+
c.state.status === "initializing" && c.state.pending === "sign_out" || accept(c, event, session);
|
|
2839
2977
|
}).data.subscription;
|
|
2840
2978
|
c.unsubscribe = () => subscription.unsubscribe();
|
|
2841
2979
|
let started = c.revision, { data: data3, error } = await c.provider.getSession();
|
|
@@ -2997,7 +3135,7 @@ function createBrowserAuth(runtime) {
|
|
|
2997
3135
|
if (!active2)
|
|
2998
3136
|
return callback("SIGNED_OUT", null), { data: { subscription: { unsubscribe() {
|
|
2999
3137
|
} } } };
|
|
3000
|
-
let listener = (
|
|
3138
|
+
let listener = (event, session) => callback(event, session);
|
|
3001
3139
|
return coordinator.sessions.add(listener), sessionObservers.add(listener), callback("INITIAL_SESSION", coordinator.session), { data: { subscription: { unsubscribe() {
|
|
3002
3140
|
coordinator.sessions.delete(listener), sessionObservers.delete(listener);
|
|
3003
3141
|
} } } };
|
|
@@ -3070,19 +3208,19 @@ async function provider(configuration, guard) {
|
|
|
3070
3208
|
}
|
|
3071
3209
|
},
|
|
3072
3210
|
fetch: Object.assign(async (input, init2) => {
|
|
3073
|
-
let revision = guard.revision(),
|
|
3074
|
-
throw
|
|
3211
|
+
let revision = guard.revision(), request2 = String(input).startsWith(`${configuration.providerUrl}/auth/v1/oauth/authorizations/`) ? authorizationRequest : void 0, rejectStale = () => {
|
|
3212
|
+
throw request2 && (request2.rejected = !0), new BrowserAuthError("stale");
|
|
3075
3213
|
};
|
|
3076
|
-
|
|
3077
|
-
let response2 = await fetch(input, { ...init2, redirect: "error" }),
|
|
3078
|
-
(!guard.current(revision) ||
|
|
3214
|
+
request2 && (!request2.current() || !guard.canAuthorize(new Headers(init2?.headers).get("authorization")?.replace(/^Bearer /, "") ?? "")) && rejectStale();
|
|
3215
|
+
let response2 = await fetch(input, { ...init2, redirect: "error" }), body = await response2.arrayBuffer();
|
|
3216
|
+
(!guard.current(revision) || request2 && !request2.current()) && rejectStale();
|
|
3079
3217
|
let result2 = new Response(
|
|
3080
|
-
[204, 205, 304].includes(response2.status) ? null :
|
|
3218
|
+
[204, 205, 304].includes(response2.status) ? null : body,
|
|
3081
3219
|
{ status: response2.status, statusText: response2.statusText, headers: response2.headers }
|
|
3082
3220
|
), json3 = result2.json.bind(result2);
|
|
3083
3221
|
return result2.json = async () => {
|
|
3084
3222
|
let value = await json3();
|
|
3085
|
-
return (!guard.current(revision) ||
|
|
3223
|
+
return (!guard.current(revision) || request2 && !request2.current()) && rejectStale(), value && typeof value.access_token == "string" && provenance.set(value.access_token, revision), value;
|
|
3086
3224
|
}, result2;
|
|
3087
3225
|
}, { preconnect: fetch.preconnect })
|
|
3088
3226
|
});
|
|
@@ -3091,15 +3229,15 @@ async function provider(configuration, guard) {
|
|
|
3091
3229
|
authorizationQueue = new Promise((resolve) => {
|
|
3092
3230
|
release = resolve;
|
|
3093
3231
|
}), await previous;
|
|
3094
|
-
let
|
|
3095
|
-
authorizationRequest =
|
|
3232
|
+
let request2 = { current: current2, rejected: !1 };
|
|
3233
|
+
authorizationRequest = request2;
|
|
3096
3234
|
try {
|
|
3097
3235
|
if (!current2()) throw new BrowserAuthError("stale");
|
|
3098
3236
|
let result2 = await (kind === "get" ? client.oauth.getAuthorizationDetails(id3) : kind === "approve" ? client.oauth.approveAuthorization(id3, { skipBrowserRedirect: !0 }) : client.oauth.denyAuthorization(id3, { skipBrowserRedirect: !0 }));
|
|
3099
|
-
if (
|
|
3237
|
+
if (request2.rejected || !current2()) throw new BrowserAuthError("stale");
|
|
3100
3238
|
return result2;
|
|
3101
3239
|
} catch (error) {
|
|
3102
|
-
throw
|
|
3240
|
+
throw request2.rejected || !current2() ? new BrowserAuthError("stale") : error;
|
|
3103
3241
|
} finally {
|
|
3104
3242
|
authorizationRequest = void 0, release();
|
|
3105
3243
|
}
|
|
@@ -3111,9 +3249,9 @@ async function provider(configuration, guard) {
|
|
|
3111
3249
|
deny: (id3, current2) => authorization("deny", id3, current2)
|
|
3112
3250
|
},
|
|
3113
3251
|
getSession: () => client.getSession(),
|
|
3114
|
-
onAuthStateChange: (callback) => client.onAuthStateChange((
|
|
3252
|
+
onAuthStateChange: (callback) => client.onAuthStateChange((event, session) => {
|
|
3115
3253
|
let revision = session ? provenance.get(session.access_token) : void 0;
|
|
3116
|
-
revision !== void 0 && !guard.current(revision) || (callback(
|
|
3254
|
+
revision !== void 0 && !guard.current(revision) || (callback(event, session), session && provenance.delete(session.access_token));
|
|
3117
3255
|
}),
|
|
3118
3256
|
signInWithOtp: (input) => client.signInWithOtp(input),
|
|
3119
3257
|
verifyOtp: (input) => client.verifyOtp(input),
|
|
@@ -3132,188 +3270,160 @@ async function provider(configuration, guard) {
|
|
|
3132
3270
|
}
|
|
3133
3271
|
var auth = /* @__PURE__ */ createBrowserAuth({ provider, failure: (reason) => new BrowserAuthError(reason) });
|
|
3134
3272
|
|
|
3135
|
-
var identifier = /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/, uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}
|
|
3273
|
+
var identifier = /^[a-z0-9]+(?:-[a-z0-9]+)*(?![\s\S])/, uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}(?![\s\S])/i, SUMMARY_BYTES = 17 * 1024 * 1024, AppRoutineError = class extends Error {
|
|
3136
3274
|
constructor(reason) {
|
|
3137
3275
|
super(reason);
|
|
3138
3276
|
this.reason = reason;
|
|
3139
3277
|
this.name = "AppRoutineError";
|
|
3140
3278
|
}
|
|
3141
3279
|
reason;
|
|
3142
|
-
}
|
|
3143
|
-
function fail3(reason) {
|
|
3280
|
+
}, fail3 = (reason) => {
|
|
3144
3281
|
throw new AppRoutineError(reason);
|
|
3145
|
-
}
|
|
3146
|
-
function object4(value) {
|
|
3147
|
-
return !!value && typeof value == "object" && !Array.isArray(value);
|
|
3148
|
-
}
|
|
3149
|
-
function keys4(value, expected) {
|
|
3150
|
-
return Object.keys(value).sort().join(",") === expected;
|
|
3151
|
-
}
|
|
3282
|
+
};
|
|
3152
3283
|
function current(context2) {
|
|
3153
3284
|
(!context2.isCurrent() || context2.signal.aborted) && fail3("authority_unavailable");
|
|
3154
3285
|
}
|
|
3155
|
-
|
|
3286
|
+
function appDescriptors() {
|
|
3287
|
+
return globalThis[/* @__PURE__ */ Symbol.for("oddington.app.descriptor")]?.routines ?? [];
|
|
3288
|
+
}
|
|
3289
|
+
async function local() {
|
|
3290
|
+
let context2 = await resolveAppContext().catch(() => fail3("authority_unavailable"));
|
|
3291
|
+
return context2.kind !== "local" ? fail3("execution_unavailable") : (current(context2), context2);
|
|
3292
|
+
}
|
|
3293
|
+
async function request(key, suffix, init2, maximum = SUMMARY_BYTES, retained) {
|
|
3294
|
+
(!identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable");
|
|
3295
|
+
let context2 = retained ?? await local();
|
|
3296
|
+
current(context2);
|
|
3156
3297
|
try {
|
|
3157
|
-
let value = await appResponse(response2, maximum, context2.signal);
|
|
3158
|
-
|
|
3298
|
+
let response2 = await context2.requestRoutine(key, suffix, init2), value = await appResponse(response2, maximum, context2.signal);
|
|
3299
|
+
if (current(context2), !response2.ok) {
|
|
3300
|
+
let reason = value?.error;
|
|
3301
|
+
reason === "authority_unavailable" && (context2.invalidate(), fail3(reason)), (reason === "invalid_input" || reason === "execution_unavailable") && fail3(reason), fail3("execution_unavailable");
|
|
3302
|
+
}
|
|
3303
|
+
return value;
|
|
3159
3304
|
} catch (error) {
|
|
3160
|
-
if (current(context2), error instanceof
|
|
3161
|
-
|
|
3305
|
+
if (current(context2), error instanceof AppRoutineError) throw error;
|
|
3306
|
+
fail3("execution_unavailable");
|
|
3162
3307
|
}
|
|
3163
3308
|
}
|
|
3164
|
-
function
|
|
3165
|
-
|
|
3309
|
+
function summary(value, key, id3) {
|
|
3310
|
+
let run = value;
|
|
3311
|
+
return (!only(run, "id,routine,placement,status,createdAt,startedAt,finishedAt,steps,result,failure,publication") || typeof run.id != "string" || !uuid.test(run.id) || id3 !== void 0 && run.id !== id3 || run.routine !== key || run.placement !== "local" || !["queued", "running", "succeeded", "failed"].includes(run.status) || !timestamp(run.createdAt) || !optionalTimes(run) || !Array.isArray(run.steps) || run.steps.length > 64 || run.steps.some((step) => !only(step, "id,title,status,startedAt,finishedAt,summary,detailAvailable") || typeof step.detailAvailable != "boolean" || !validStep(step)) || new Set(run.steps.map((step) => step.id)).size !== run.steps.length || Object.hasOwn(run, "result") && (run.status !== "succeeded" || !bounded(run.result)) || run.failure !== void 0 && (run.status !== "failed" || !only(run.failure, "message") || !message(run.failure.message)) || run.publication !== void 0 && (run.status !== "succeeded" || !validPublication(run.publication))) && fail3("execution_unavailable"), run;
|
|
3166
3312
|
}
|
|
3167
|
-
function
|
|
3168
|
-
return
|
|
3313
|
+
function only(value, allowed) {
|
|
3314
|
+
return !!value && typeof value == "object" && !Array.isArray(value) && Object.keys(value).every((key) => allowed.split(",").includes(key));
|
|
3169
3315
|
}
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
if (
|
|
3188
|
-
|
|
3189
|
-
if (
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
context2.signal.addEventListener("abort", abort, { once: !0 });
|
|
3201
|
-
}), current(context2);
|
|
3202
|
-
}
|
|
3203
|
-
function handle(context2, run, steps) {
|
|
3316
|
+
var timestamp = (value) => typeof value == "string" && value.length <= 32 && Number.isFinite(Date.parse(value)), message = (value) => typeof value == "string" && value.length > 0 && value.length <= 512, bounded = (value) => new TextEncoder().encode(JSON.stringify(value)).byteLength <= 256 * 1024;
|
|
3317
|
+
function optionalTimes(value) {
|
|
3318
|
+
return (value.startedAt === void 0 || timestamp(value.startedAt)) && (value.finishedAt === void 0 || timestamp(value.finishedAt));
|
|
3319
|
+
}
|
|
3320
|
+
function validStep(step) {
|
|
3321
|
+
return typeof step.id == "string" && identifier.test(step.id) && typeof step.title == "string" && step.title.length > 0 && step.title.length <= 256 && ["pending", "running", "completed", "failed", "skipped"].includes(step.status) && optionalTimes(step) && (!Object.hasOwn(step, "summary") || bounded(step.summary)) && (!Object.hasOwn(step, "data") || bounded(step.data));
|
|
3322
|
+
}
|
|
3323
|
+
function validPublication(value) {
|
|
3324
|
+
return value && only(value, value.state === "failed" ? "state,message" : "state") && (["not_needed", "ready", "published"].includes(value.state) || value.state === "failed" && message(value.message));
|
|
3325
|
+
}
|
|
3326
|
+
function jsonInput(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
3327
|
+
if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return;
|
|
3328
|
+
if (!value || typeof value != "object" || ancestors.has(value)) return fail3("invalid_input");
|
|
3329
|
+
let array3 = Array.isArray(value), keys4 = Reflect.ownKeys(value);
|
|
3330
|
+
if (!array3 && ![Object.prototype, null].includes(Object.getPrototypeOf(value)) || array3 && (keys4.length !== value.length + 1 || !Array.from({ length: value.length }, (_, index) => Object.hasOwn(value, index)).every(Boolean))) return fail3("invalid_input");
|
|
3331
|
+
ancestors.add(value);
|
|
3332
|
+
for (let key of keys4) {
|
|
3333
|
+
if (array3 && key === "length") continue;
|
|
3334
|
+
let descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
3335
|
+
if (typeof key != "string" || !descriptor.enumerable || !Object.hasOwn(descriptor, "value")) return fail3("invalid_input");
|
|
3336
|
+
jsonInput(descriptor.value, ancestors);
|
|
3337
|
+
}
|
|
3338
|
+
ancestors.delete(value);
|
|
3339
|
+
}
|
|
3340
|
+
function structure(value) {
|
|
3341
|
+
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);
|
|
3342
|
+
}
|
|
3343
|
+
function handle(key, id3, context2) {
|
|
3344
|
+
(typeof id3 != "string" || !uuid.test(id3)) && fail3("invalid_input");
|
|
3345
|
+
let read2 = async () => summary(await request(key, `runs/${id3}`, void 0, SUMMARY_BYTES, context2), key, id3);
|
|
3204
3346
|
return Object.freeze({
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
let
|
|
3208
|
-
for (;
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
response2 = await context2.requestRoutine(run.key, `runs/${run.runId}/events?after=${cursor}`);
|
|
3213
|
-
} catch {
|
|
3214
|
-
current(context2), await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
3215
|
-
continue;
|
|
3216
|
-
}
|
|
3217
|
-
if (response2.status >= 500) {
|
|
3218
|
-
await response2.body?.cancel(), await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
3219
|
-
continue;
|
|
3220
|
-
}
|
|
3221
|
-
let value;
|
|
3222
|
-
try {
|
|
3223
|
-
value = await body(context2, response2, 80 * 1024);
|
|
3224
|
-
} catch (error) {
|
|
3225
|
-
if (!(error instanceof AppResponseReadError)) throw error;
|
|
3226
|
-
await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
3227
|
-
continue;
|
|
3228
|
-
}
|
|
3229
|
-
(!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");
|
|
3230
|
-
let delivery = [];
|
|
3231
|
-
for (let raw of value.events) {
|
|
3232
|
-
let publicEvent = event(raw, run, steps), encoded = JSON.stringify(raw), sequence = raw.sequence;
|
|
3233
|
-
if (sequence <= cursor) {
|
|
3234
|
-
seen[sequence - 1] !== encoded && fail3("execution_unavailable");
|
|
3235
|
-
continue;
|
|
3236
|
-
}
|
|
3237
|
-
(terminal || sequence !== cursor + 1 || sequence > 256 || (cursor === 0 ? publicEvent.type !== "started" : publicEvent.type === "started")) && fail3("execution_unavailable"), retainedBytes += new TextEncoder().encode(encoded).byteLength, retainedBytes > 1024 * 1024 && fail3("execution_unavailable"), seen.push(encoded), cursor = sequence, terminal = publicEvent.type === "finished", delivery.push(publicEvent);
|
|
3238
|
-
}
|
|
3239
|
-
(value.after !== cursor || value.terminal !== terminal) && fail3("execution_unavailable");
|
|
3240
|
-
for (let item of delivery)
|
|
3241
|
-
current(context2), yield item;
|
|
3242
|
-
delay = 100, terminal || await pause(context2, delivery.length ? 100 : 250);
|
|
3347
|
+
current: read2,
|
|
3348
|
+
async *watch() {
|
|
3349
|
+
let previous;
|
|
3350
|
+
for (; ; ) {
|
|
3351
|
+
let state = await read2(), encoded = JSON.stringify(state);
|
|
3352
|
+
if (encoded !== previous && (previous = encoded, yield state), state.status === "succeeded" || state.status === "failed") return;
|
|
3353
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
3243
3354
|
}
|
|
3244
3355
|
},
|
|
3245
|
-
async
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
fail3("execution_unavailable");
|
|
3253
|
-
}
|
|
3356
|
+
async step(step) {
|
|
3357
|
+
(typeof step != "string" || !identifier.test(step)) && fail3("invalid_input");
|
|
3358
|
+
let value = await request(key, `runs/${id3}/steps/${step}`, void 0, 514 * 1024, context2);
|
|
3359
|
+
return (!only(value, "id,title,status,startedAt,finishedAt,summary,data") || value.id !== step || !validStep(value)) && fail3("execution_unavailable"), value;
|
|
3360
|
+
},
|
|
3361
|
+
async publish() {
|
|
3362
|
+
return summary(await request(key, `runs/${id3}/publish`, { method: "POST" }, SUMMARY_BYTES, context2), key, id3);
|
|
3254
3363
|
}
|
|
3255
3364
|
});
|
|
3256
3365
|
}
|
|
3257
|
-
async function
|
|
3258
|
-
let
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
let runs = value2.runs.map((run) => descriptor(run, key));
|
|
3266
|
-
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));
|
|
3267
|
-
}
|
|
3268
|
-
let available = await body(context2, await context2.requestAvailability(key), 16 * 1024);
|
|
3269
|
-
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");
|
|
3270
|
-
let steps = [...available.steps], encoded;
|
|
3271
|
-
try {
|
|
3272
|
-
encoded = JSON.stringify(input), (encoded === void 0 || new TextEncoder().encode(encoded).byteLength > 16 * 1024) && fail3("invalid_input");
|
|
3273
|
-
} catch {
|
|
3274
|
-
fail3("invalid_input");
|
|
3275
|
-
}
|
|
3276
|
-
let value = await body(context2, await context2.requestRoutine(key, "runs", {
|
|
3277
|
-
method: "POST",
|
|
3278
|
-
body: `{"input":${encoded}}`
|
|
3279
|
-
}), 16 * 1024);
|
|
3280
|
-
return handle(context2, descriptor(value, key), steps);
|
|
3281
|
-
} catch (error) {
|
|
3282
|
-
if (context2 && current(context2), error instanceof AppRoutineError) throw error;
|
|
3283
|
-
return fail3(context2 ? "execution_unavailable" : "authority_unavailable");
|
|
3284
|
-
}
|
|
3285
|
-
}
|
|
3286
|
-
|
|
3287
|
-
var authorityUnavailable = () => ({ available: !1, reason: "authority_unavailable" }), MAX_RESPONSE_BYTES = 16 * 1024;
|
|
3288
|
-
async function availability(key) {
|
|
3366
|
+
async function describeAppRoutine(key) {
|
|
3367
|
+
let descriptor = appDescriptors().find((item) => item.id === key);
|
|
3368
|
+
if (!descriptor) return fail3("authority_unavailable");
|
|
3369
|
+
let unavailable3 = () => ({
|
|
3370
|
+
...structuredClone(descriptor),
|
|
3371
|
+
connections: descriptor.connections.map((connection) => ({ ...connection, available: !1 })),
|
|
3372
|
+
readiness: { state: "unavailable", reason: "capability_unavailable", message: "Routine capability unavailable." }
|
|
3373
|
+
});
|
|
3289
3374
|
try {
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
if (context2.kind !== "local") return { available: !1, reason: "execution_unavailable" };
|
|
3293
|
-
let response2 = await context2.requestAvailability(key);
|
|
3294
|
-
if (!response2.ok || response2.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() !== "application/json")
|
|
3295
|
-
return authorityUnavailable();
|
|
3296
|
-
let value = await appResponse(response2, MAX_RESPONSE_BYTES, context2.signal);
|
|
3297
|
-
if (!context2.isCurrent() || !value || typeof value != "object" || Array.isArray(value)) return authorityUnavailable();
|
|
3298
|
-
let result2 = value;
|
|
3299
|
-
return result2.available === !1 && Object.keys(result2).sort().join(",") === "available,reason" && (result2.reason === "not_enabled" || 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] };
|
|
3375
|
+
let value = await request(key, "describe", void 0, 1048576);
|
|
3376
|
+
return (!only(value, "id,title,input,connections,steps,readiness") || !value.readiness || !Array.isArray(value.connections) || structure({ ...value, readiness: void 0, connections: value.connections.map(({ available, ...item }) => item) }) !== structure(descriptor) || value.connections.some((item) => typeof item.available != "boolean") || !(value.readiness.state === "ready" && only(value.readiness, "state,placement") && value.readiness.placement === "local" || value.readiness.state === "unavailable" && only(value.readiness, "state,reason,message") && ["not_deployed", "definition_invalid", "capability_unavailable"].includes(value.readiness.reason) && message(value.readiness.message))) && fail3("execution_unavailable"), value;
|
|
3300
3377
|
} catch {
|
|
3301
|
-
return
|
|
3378
|
+
return unavailable3();
|
|
3302
3379
|
}
|
|
3303
3380
|
}
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
}
|
|
3381
|
+
function appRoutineBinding(key) {
|
|
3382
|
+
return Object.freeze({
|
|
3383
|
+
describe: () => describeAppRoutine(key),
|
|
3384
|
+
async run(...args) {
|
|
3385
|
+
args.length > 1 && fail3("invalid_input");
|
|
3386
|
+
let encoded;
|
|
3387
|
+
try {
|
|
3388
|
+
if (args[0] === void 0) encoded = "{}";
|
|
3389
|
+
else {
|
|
3390
|
+
jsonInput(args[0]);
|
|
3391
|
+
let input = JSON.stringify(args[0]);
|
|
3392
|
+
new TextEncoder().encode(input).byteLength > 256 * 1024 && fail3("invalid_input"), encoded = `{"input":${input}}`;
|
|
3393
|
+
}
|
|
3394
|
+
} catch {
|
|
3395
|
+
return fail3("invalid_input");
|
|
3396
|
+
}
|
|
3397
|
+
let context2 = await local(), run = summary(await request(key, "runs", { method: "POST", body: encoded }, SUMMARY_BYTES, context2), key);
|
|
3398
|
+
return handle(key, run.id, context2);
|
|
3399
|
+
},
|
|
3400
|
+
runs: Object.freeze({
|
|
3401
|
+
async list() {
|
|
3402
|
+
let value = await request(key, "runs", void 0, 20 * SUMMARY_BYTES);
|
|
3403
|
+
if (!Array.isArray(value) || value.length > 20) return fail3("execution_unavailable");
|
|
3404
|
+
let runs = value.map((run) => summary(run, key));
|
|
3405
|
+
return new Set(runs.map((run) => run.id)).size !== runs.length && fail3("execution_unavailable"), runs;
|
|
3406
|
+
},
|
|
3407
|
+
async get(id3) {
|
|
3408
|
+
let run = handle(key, id3, await local());
|
|
3409
|
+
return await run.current(), run;
|
|
3410
|
+
}
|
|
3411
|
+
})
|
|
3412
|
+
});
|
|
3413
|
+
}
|
|
3414
|
+
|
|
3415
|
+
var app = Object.freeze({
|
|
3416
|
+
listRoutines: () => Promise.all(appDescriptors().map(({ id: id3 }) => describeAppRoutine(id3))),
|
|
3417
|
+
routines: new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
3418
|
+
get(_target, key) {
|
|
3419
|
+
if (!(typeof key != "string" || !appDescriptors().some((item) => item.id === key)))
|
|
3420
|
+
return appRoutineBinding(key);
|
|
3421
|
+
},
|
|
3422
|
+
set: () => !1,
|
|
3423
|
+
defineProperty: () => !1,
|
|
3424
|
+
deleteProperty: () => !1
|
|
3425
|
+
})
|
|
3426
|
+
});
|
|
3317
3427
|
|
|
3318
3428
|
var LIMIT2 = 16 * 1024, context;
|
|
3319
3429
|
var appRun = {
|
|
@@ -3343,10 +3453,10 @@ function routineDataEnvelope(command) {
|
|
|
3343
3453
|
}
|
|
3344
3454
|
|
|
3345
3455
|
function routinePublicationClient2(options = {}) {
|
|
3346
|
-
let environment = {}, installed2 = routineTransport(),
|
|
3456
|
+
let environment = {}, installed2 = routineTransport(), local2 = installed2?.request ?? void 0, workspace = installed2 ? "installed" : options.workspace ?? environment.ODDINGTON_ROUTINE_WORKSPACE, capability = options.capability ?? environment.ODDINGTON_ROUTINE_RUN;
|
|
3347
3457
|
if (!workspace || !/^[a-z0-9][a-z0-9-]*$/.test(workspace) || capability !== void 0 && !/^[0-9a-f]{64}$/.test(capability))
|
|
3348
3458
|
throw new Error("A workspace and valid optional routine capability are required");
|
|
3349
|
-
let workingRoot = options.workingRoot ?? environment.ODDINGTON_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-oddington-run": capability } : {},
|
|
3459
|
+
let workingRoot = options.workingRoot ?? environment.ODDINGTON_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-oddington-run": capability } : {}, request2 = options.request ?? (capability ? async (path, init2) => {
|
|
3350
3460
|
if (path === "/api/data") return fetch(`https://${workspace}.oddington.ai/api/data`, { ...init2, redirect: "error" });
|
|
3351
3461
|
let origin = `https://${workspace}.oddington.ai`, target = new URL(path, `${origin}/`);
|
|
3352
3462
|
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")
|
|
@@ -3355,16 +3465,16 @@ function routinePublicationClient2(options = {}) {
|
|
|
3355
3465
|
} : async () => {
|
|
3356
3466
|
throw new Error("Member publication requires a host-supplied request");
|
|
3357
3467
|
});
|
|
3358
|
-
async function send3(operation2,
|
|
3359
|
-
if (
|
|
3360
|
-
let writing = operation2 === "records/update", reading = operation2 === "records/read", response2 = await
|
|
3468
|
+
async function send3(operation2, body) {
|
|
3469
|
+
if (local2) return await local2(operation2, body);
|
|
3470
|
+
let writing = operation2 === "records/update", reading = operation2 === "records/read", response2 = await request2(writing || reading ? "/api/data" : `/api/inbox/${operation2}`, {
|
|
3361
3471
|
method: "POST",
|
|
3362
3472
|
headers: {
|
|
3363
3473
|
"content-type": "application/json",
|
|
3364
3474
|
...headers,
|
|
3365
3475
|
...writing || reading ? { "x-oddington-workspace": workspace, "x-oddington-captured-records": "1" } : {}
|
|
3366
3476
|
},
|
|
3367
|
-
body: JSON.stringify(writing ? routineDataEnvelope(validateRoutineRecordWrite(
|
|
3477
|
+
body: JSON.stringify(writing ? routineDataEnvelope(validateRoutineRecordWrite(body)) : reading ? { operation: "records.select", request: validateRecordRead(body) } : body)
|
|
3368
3478
|
}), result2 = await response2.json();
|
|
3369
3479
|
if (!response2.ok && operation2 === "records/update")
|
|
3370
3480
|
throw new RoutineRecordWriteError(result2.error ?? "Could not confirm routine preparation", result2.effect ?? "uncertain");
|
|
@@ -3372,11 +3482,11 @@ function routinePublicationClient2(options = {}) {
|
|
|
3372
3482
|
return result2;
|
|
3373
3483
|
}
|
|
3374
3484
|
let transport = {
|
|
3375
|
-
async publish(
|
|
3376
|
-
return await send3("publish",
|
|
3485
|
+
async publish(body) {
|
|
3486
|
+
return await send3("publish", body);
|
|
3377
3487
|
},
|
|
3378
|
-
async resolve(
|
|
3379
|
-
await send3("resolve",
|
|
3488
|
+
async resolve(body) {
|
|
3489
|
+
await send3("resolve", body);
|
|
3380
3490
|
}
|
|
3381
3491
|
};
|
|
3382
3492
|
async function readRecords(input) {
|
|
@@ -3403,12 +3513,12 @@ function routinePublicationClient2(options = {}) {
|
|
|
3403
3513
|
files: {
|
|
3404
3514
|
async add(value) {
|
|
3405
3515
|
let input = validateFileAddOptions(value);
|
|
3406
|
-
if (
|
|
3516
|
+
if (local2) return validateInboxFile(await local2("files/add", input));
|
|
3407
3517
|
throw workingRoot ? new Error("Inbox file reads require a Node working root") : new Error("Inbox file reads require a working root");
|
|
3408
3518
|
}
|
|
3409
3519
|
},
|
|
3410
|
-
async check(
|
|
3411
|
-
await send3("check", { requestKey:
|
|
3520
|
+
async check(body) {
|
|
3521
|
+
await send3("check", { requestKey: body.requestKey, item: validatePublication(body.item) });
|
|
3412
3522
|
}
|
|
3413
3523
|
};
|
|
3414
3524
|
}
|