@oddington/sdk 0.1.20 → 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 +77 -60
- package/dist/browser.js +562 -463
- 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/inbox-contract.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 {
|
|
@@ -572,7 +572,49 @@ function validateRoutineSchemaValue(schema2, value) {
|
|
|
572
572
|
}
|
|
573
573
|
}
|
|
574
574
|
|
|
575
|
-
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 = () => {
|
|
576
618
|
throw new AppRoutineContractError("invalid_value");
|
|
577
619
|
}, invalidContract2 = () => {
|
|
578
620
|
throw new AppRoutineContractError("invalid_contract");
|
|
@@ -586,40 +628,61 @@ function freeze(value) {
|
|
|
586
628
|
}
|
|
587
629
|
function json(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
588
630
|
if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return;
|
|
589
|
-
if (!value || typeof value != "object" || ancestors.has(value)) return
|
|
631
|
+
if (!value || typeof value != "object" || ancestors.has(value)) return invalid2();
|
|
590
632
|
let array3 = Array.isArray(value);
|
|
591
|
-
if (!array3 && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return
|
|
592
|
-
let
|
|
593
|
-
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();
|
|
594
636
|
ancestors.add(value);
|
|
595
|
-
for (let key of
|
|
637
|
+
for (let key of keys4) {
|
|
596
638
|
if (array3 && key === "length") continue;
|
|
597
|
-
if (typeof key != "string") return
|
|
598
|
-
let
|
|
599
|
-
if (!
|
|
600
|
-
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);
|
|
601
643
|
}
|
|
602
644
|
ancestors.delete(value);
|
|
603
645
|
}
|
|
604
|
-
function
|
|
605
|
-
json(value)
|
|
646
|
+
function captureJson(value) {
|
|
647
|
+
json(value);
|
|
606
648
|
let encoded = JSON.stringify(value);
|
|
607
|
-
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 };
|
|
608
670
|
}
|
|
609
|
-
function declaration(value) {
|
|
671
|
+
function declaration(value, defaults) {
|
|
610
672
|
try {
|
|
611
673
|
json(value);
|
|
612
674
|
} catch {
|
|
613
675
|
return invalidContract2();
|
|
614
676
|
}
|
|
615
|
-
|
|
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);
|
|
616
679
|
}
|
|
617
680
|
var schema = {
|
|
618
681
|
object(properties) {
|
|
619
|
-
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 });
|
|
620
683
|
},
|
|
621
684
|
array(items, options) {
|
|
622
|
-
return declaration({ type: "array", items, maxItems: options.maxItems });
|
|
685
|
+
return declaration({ type: "array", items: nestedSchema(items), maxItems: options.maxItems });
|
|
623
686
|
},
|
|
624
687
|
string(options = {}) {
|
|
625
688
|
return declaration({ type: "string", ...options });
|
|
@@ -633,33 +696,77 @@ var schema = {
|
|
|
633
696
|
boolean() {
|
|
634
697
|
return declaration({ type: "boolean" });
|
|
635
698
|
}
|
|
636
|
-
}, file = () => declaration({ type: "file" }), definitions = /* @__PURE__ */ new WeakMap()
|
|
637
|
-
|
|
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) {
|
|
638
705
|
try {
|
|
639
|
-
|
|
640
|
-
|
|
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] });
|
|
641
711
|
} catch {
|
|
642
712
|
return invalidContract2();
|
|
643
713
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
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 } : {}
|
|
654
756
|
}), captured = Object.freeze({
|
|
655
757
|
...definition,
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
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) },
|
|
659
766
|
// Only this authored definition is callable; no generic runner is exported.
|
|
660
|
-
run: (
|
|
767
|
+
run: (input2, os2) => executeRoutineDefinition(captured, input2, os2)
|
|
661
768
|
});
|
|
662
|
-
return definitions.set(captured, { contract, run: definition.run }), captured;
|
|
769
|
+
return definitions.set(captured, { contract, steps: executable, run: definition.run }), captured;
|
|
663
770
|
};
|
|
664
771
|
function inspectRoutineDefinition(definition) {
|
|
665
772
|
if (!definition || typeof definition != "object") return invalidContract2();
|
|
@@ -667,42 +774,62 @@ function inspectRoutineDefinition(definition) {
|
|
|
667
774
|
return registered ? registered.contract : invalidContract2();
|
|
668
775
|
}
|
|
669
776
|
function captureRoutineInput(definition, input) {
|
|
670
|
-
|
|
777
|
+
let contract = inspectRoutineDefinition(definition);
|
|
778
|
+
return capture(contract.input, input === void 0 && Object.hasOwn(contract, "inputDefault") ? contract.inputDefault : input);
|
|
671
779
|
}
|
|
672
780
|
async function executeRoutineDefinition(definition, input, runtime) {
|
|
673
|
-
let captured = captureRoutineInput(definition, input), { contract, run } = definitions.get(definition), active2 = !0, broken = !1,
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
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;
|
|
685
798
|
try {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
if (step.summary === void 0) {
|
|
689
|
-
if (summary.length) return invalid();
|
|
690
|
-
} 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);
|
|
691
801
|
} catch (error) {
|
|
692
802
|
return broken = !0, Promise.reject(error);
|
|
693
803
|
}
|
|
694
|
-
let
|
|
695
|
-
|
|
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
|
+
}, () => {
|
|
696
819
|
broken = !0;
|
|
697
|
-
}),
|
|
820
|
+
}), next;
|
|
698
821
|
}
|
|
699
|
-
});
|
|
822
|
+
}), result2, failure;
|
|
700
823
|
try {
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
active2 = !1;
|
|
824
|
+
result2 = await run(captured, os2);
|
|
825
|
+
} catch (error) {
|
|
826
|
+
failure = error, broken = !0;
|
|
705
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();
|
|
706
833
|
}
|
|
707
834
|
|
|
708
835
|
var DataOperationError = class extends Error {
|
|
@@ -720,46 +847,46 @@ var DataOperationError = class extends Error {
|
|
|
720
847
|
component;
|
|
721
848
|
};
|
|
722
849
|
|
|
723
|
-
var
|
|
850
|
+
var invalid3 = () => {
|
|
724
851
|
throw new DataOperationError("invalid_query");
|
|
725
852
|
}, historyText = (value) => typeof value == "string" && !/[\u0000\uD800-\uDFFF]/u.test(value);
|
|
726
853
|
function historyVersion(value) {
|
|
727
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);
|
|
728
855
|
}
|
|
729
856
|
function historyProperties(value) {
|
|
730
|
-
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();
|
|
731
858
|
let descriptors = Object.getOwnPropertyDescriptors(value);
|
|
732
|
-
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;
|
|
733
860
|
}
|
|
734
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);
|
|
735
862
|
function historyArray(value) {
|
|
736
|
-
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) return
|
|
863
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) return invalid3();
|
|
737
864
|
let descriptors = Object.getOwnPropertyDescriptors(value);
|
|
738
|
-
if (Reflect.ownKeys(value).length !== value.length + 1) return
|
|
865
|
+
if (Reflect.ownKeys(value).length !== value.length + 1) return invalid3();
|
|
739
866
|
let result2 = [];
|
|
740
867
|
for (let i = 0; i < value.length; i++) {
|
|
741
|
-
let
|
|
742
|
-
if (!
|
|
743
|
-
result2.push(
|
|
868
|
+
let descriptor = descriptors[i];
|
|
869
|
+
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value")) return invalid3();
|
|
870
|
+
result2.push(descriptor.value);
|
|
744
871
|
}
|
|
745
872
|
return result2;
|
|
746
873
|
}
|
|
747
874
|
function captureOptions(value, changes) {
|
|
748
875
|
if (value === void 0) return {};
|
|
749
876
|
let descriptors = historyProperties(value), result2 = {}, allowed = changes ? ["collections", "refs", "from", "through", "limit", "after"] : ["limit", "before"];
|
|
750
|
-
if (Object.keys(descriptors).some((key) => !allowed.includes(key))) return
|
|
877
|
+
if (Object.keys(descriptors).some((key) => !allowed.includes(key))) return invalid3();
|
|
751
878
|
for (let key of allowed) {
|
|
752
879
|
if (!Object.hasOwn(descriptors, key)) continue;
|
|
753
880
|
let scalar = descriptors[key].value;
|
|
754
881
|
if (key === "collections" || key === "refs") {
|
|
755
882
|
let values = historyArray(scalar);
|
|
756
|
-
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();
|
|
757
884
|
result2[key] = values;
|
|
758
885
|
} else if (key === "limit") {
|
|
759
|
-
if (!Number.isInteger(scalar) || scalar < 1 || scalar > (changes ? 500 : 100)) return
|
|
886
|
+
if (!Number.isInteger(scalar) || scalar < 1 || scalar > (changes ? 500 : 100)) return invalid3();
|
|
760
887
|
result2.limit = scalar;
|
|
761
888
|
} else {
|
|
762
|
-
if (!(key === "after" ? historyCursor(scalar) : historyVersion(scalar))) return
|
|
889
|
+
if (!(key === "after" ? historyCursor(scalar) : historyVersion(scalar))) return invalid3();
|
|
763
890
|
result2[key] = scalar;
|
|
764
891
|
}
|
|
765
892
|
}
|
|
@@ -767,39 +894,39 @@ function captureOptions(value, changes) {
|
|
|
767
894
|
}
|
|
768
895
|
var captureHistoryListOptions = (value) => captureOptions(value, !1), captureHistoryChangesOptions = (value) => captureOptions(value, !0);
|
|
769
896
|
function captureHistoryInstant(value) {
|
|
770
|
-
if (!historyText(value) || value.length > 1024) return
|
|
897
|
+
if (!historyText(value) || value.length > 1024) return invalid3();
|
|
771
898
|
let match = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.\d+)?([Zz]|([+-])(\d{2}):(\d{2}))$/.exec(value);
|
|
772
|
-
if (!match) return
|
|
899
|
+
if (!match) return invalid3();
|
|
773
900
|
let [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number), days = new Date(Date.UTC(year, month, 0));
|
|
774
|
-
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;
|
|
775
902
|
}
|
|
776
903
|
|
|
777
|
-
var
|
|
904
|
+
var invalid4 = () => {
|
|
778
905
|
throw new DataOperationError("invalid_query");
|
|
779
906
|
};
|
|
780
907
|
function captureRecordsSearchInput(query, options) {
|
|
781
|
-
if (!historyText(query)) return
|
|
908
|
+
if (!historyText(query)) return invalid4();
|
|
782
909
|
let length = [...query.trim()].length;
|
|
783
|
-
if (length < 1 || length > 256) return
|
|
910
|
+
if (length < 1 || length > 256) return invalid4();
|
|
784
911
|
if (options === void 0) return { query };
|
|
785
912
|
let descriptors = historyProperties(options);
|
|
786
|
-
if (Object.keys(descriptors).some((key) => !["collections", "limit"].includes(key))) return
|
|
913
|
+
if (Object.keys(descriptors).some((key) => !["collections", "limit"].includes(key))) return invalid4();
|
|
787
914
|
let captured = {};
|
|
788
915
|
if (Object.hasOwn(descriptors, "collections")) {
|
|
789
916
|
let supplied = descriptors.collections.value;
|
|
790
|
-
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();
|
|
791
918
|
let collections = [];
|
|
792
919
|
for (let index = 0; index < supplied.length; index++) {
|
|
793
|
-
let
|
|
794
|
-
if (!
|
|
795
|
-
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);
|
|
796
923
|
}
|
|
797
|
-
if (new Set(collections).size !== collections.length) return
|
|
924
|
+
if (new Set(collections).size !== collections.length) return invalid4();
|
|
798
925
|
captured.collections = collections;
|
|
799
926
|
}
|
|
800
927
|
if (Object.hasOwn(descriptors, "limit")) {
|
|
801
928
|
let supplied = descriptors.limit.value;
|
|
802
|
-
if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100) return
|
|
929
|
+
if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100) return invalid4();
|
|
803
930
|
captured.limit = supplied;
|
|
804
931
|
}
|
|
805
932
|
return { query, options: captured };
|
|
@@ -830,8 +957,8 @@ function captureDataDelete(record3) {
|
|
|
830
957
|
return !validRecordRef(identity.$ref) || typeof identity.$version != "string" || !identity.$version.length || identity.$version.length > 512 ? invalidChange() : { ref: identity.$ref, expectedVersion: identity.$version };
|
|
831
958
|
}
|
|
832
959
|
function captureDataUpdate(record3, set) {
|
|
833
|
-
let identity = captureDataDelete(record3),
|
|
834
|
-
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) };
|
|
835
962
|
}
|
|
836
963
|
function captureIdentities(value, update, allowEmpty = !0) {
|
|
837
964
|
if (!Array.isArray(value) || !allowEmpty && !value.length || value.length > 1e4) return invalidChange();
|
|
@@ -850,14 +977,14 @@ function captureDataCreate(value) {
|
|
|
850
977
|
let row = mapping(value);
|
|
851
978
|
if (!validRecordRef(row.$ref) || Object.keys(row).some((key) => key.startsWith("$") && !["$ref", "$filing"].includes(key)))
|
|
852
979
|
return invalidChange();
|
|
853
|
-
let { $ref: ref, $filing, ...
|
|
980
|
+
let { $ref: ref, $filing, ...fields6 } = row, filing;
|
|
854
981
|
if ($filing !== void 0) {
|
|
855
982
|
let components = mapping($filing);
|
|
856
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)))
|
|
857
984
|
return invalidChange();
|
|
858
985
|
filing = { ...components };
|
|
859
986
|
}
|
|
860
|
-
return { ref, fields: captureValue(
|
|
987
|
+
return { ref, fields: captureValue(fields6), ...filing ? { filing } : {} };
|
|
861
988
|
}
|
|
862
989
|
function captureDataChanges(updatesValue, createsValue = [], deletesValue = []) {
|
|
863
990
|
let updates = captureDataUpdates(updatesValue, !0);
|
|
@@ -865,8 +992,8 @@ function captureDataChanges(updatesValue, createsValue = [], deletesValue = [])
|
|
|
865
992
|
let creates = createsValue.map((item) => {
|
|
866
993
|
let row = mapping(item);
|
|
867
994
|
if (Object.keys(row).some((key) => !["ref", "fields", "filing"].includes(key)) || !Object.hasOwn(row, "ref") || !Object.hasOwn(row, "fields")) return invalidChange();
|
|
868
|
-
let
|
|
869
|
-
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 } : {} });
|
|
870
997
|
}), deletes = captureIdentities(deletesValue, !1), refs = [...updates, ...creates, ...deletes].map((item) => item.ref);
|
|
871
998
|
return !refs.length || refs.length > 1e4 || new Set(refs).size !== refs.length ? invalidChange() : { updates, creates, deletes };
|
|
872
999
|
}
|
|
@@ -1051,7 +1178,7 @@ var data = {
|
|
|
1051
1178
|
}
|
|
1052
1179
|
};
|
|
1053
1180
|
|
|
1054
|
-
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 = {
|
|
1055
1182
|
400: ["invalid_input", "unsupported_context"],
|
|
1056
1183
|
401: ["unauthenticated"],
|
|
1057
1184
|
403: ["access_denied"],
|
|
@@ -1068,7 +1195,7 @@ async function boundedBytes(stream, limit) {
|
|
|
1068
1195
|
for (; ; ) {
|
|
1069
1196
|
let { done, value } = await reader.read();
|
|
1070
1197
|
if (done) break;
|
|
1071
|
-
if (!(value instanceof Uint8Array)) throw
|
|
1198
|
+
if (!(value instanceof Uint8Array)) throw invalid5();
|
|
1072
1199
|
if (size += value.byteLength, size > limit) throw new FileOperationError("request_too_large", 413);
|
|
1073
1200
|
bytes.set(value, size - value.byteLength);
|
|
1074
1201
|
}
|
|
@@ -1119,7 +1246,7 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1119
1246
|
reader?.releaseLock();
|
|
1120
1247
|
}
|
|
1121
1248
|
}
|
|
1122
|
-
},
|
|
1249
|
+
}, body = new ReadableStream({
|
|
1123
1250
|
async pull(controller) {
|
|
1124
1251
|
try {
|
|
1125
1252
|
reader ??= source.getReader();
|
|
@@ -1133,7 +1260,7 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1133
1260
|
}
|
|
1134
1261
|
},
|
|
1135
1262
|
cancel
|
|
1136
|
-
}, { highWaterMark: 0 }), wrapped = new Response(
|
|
1263
|
+
}, { highWaterMark: 0 }), wrapped = new Response(body, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
|
|
1137
1264
|
for (let key of ["url", "redirected", "type"])
|
|
1138
1265
|
Object.defineProperty(wrapped, key, { value: response2[key] });
|
|
1139
1266
|
return wrapped;
|
|
@@ -1141,7 +1268,7 @@ async function hostedContent(url, init2, parent, upstream = fetch) {
|
|
|
1141
1268
|
throw detach(), delivery.abort(error), error;
|
|
1142
1269
|
}
|
|
1143
1270
|
}
|
|
1144
|
-
async function send(suffix, init2,
|
|
1271
|
+
async function send(suffix, init2, descriptor, initial, parent) {
|
|
1145
1272
|
let original = initial, checkCurrent = (context2 = original) => {
|
|
1146
1273
|
if (parent?.aborted) throw unavailable();
|
|
1147
1274
|
if (!original.isCurrent() || context2.url !== original.url) throw new FileOperationError("unsupported_context", 400);
|
|
@@ -1152,20 +1279,20 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1152
1279
|
checkCurrent(context2);
|
|
1153
1280
|
try {
|
|
1154
1281
|
let response2 = await (async () => {
|
|
1155
|
-
let url = `${context2.url}${suffix}`,
|
|
1282
|
+
let url = `${context2.url}${suffix}`, request2 = {
|
|
1156
1283
|
...init2,
|
|
1157
1284
|
signal: parent,
|
|
1158
1285
|
headers: { ...context2.headers, ...init2.headers },
|
|
1159
1286
|
redirect: "error",
|
|
1160
1287
|
cache: "no-store"
|
|
1161
1288
|
};
|
|
1162
|
-
return
|
|
1289
|
+
return descriptor ? fetch(url, request2) : hostedContent(url, request2, parent);
|
|
1163
1290
|
})();
|
|
1164
1291
|
if (!response2.ok) {
|
|
1165
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);
|
|
1166
1293
|
throw code ? new FileOperationError(code, response2.status, code === "capacity" || code === "unavailable") : unavailable();
|
|
1167
1294
|
}
|
|
1168
|
-
if (response2.status !== (
|
|
1295
|
+
if (response2.status !== (descriptor === 204 ? 204 : 200) || descriptor === 204 && response2.body !== null)
|
|
1169
1296
|
throw response2.body?.cancel().catch(() => {
|
|
1170
1297
|
}), unavailable();
|
|
1171
1298
|
try {
|
|
@@ -1174,13 +1301,13 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1174
1301
|
throw response2.body?.cancel().catch(() => {
|
|
1175
1302
|
}), error;
|
|
1176
1303
|
}
|
|
1177
|
-
if (
|
|
1178
|
-
if (!
|
|
1179
|
-
let value = await result(response2,
|
|
1180
|
-
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")
|
|
1181
1308
|
return checkCurrent(), value;
|
|
1182
1309
|
let parsed;
|
|
1183
|
-
if (
|
|
1310
|
+
if (descriptor === "enrichment") {
|
|
1184
1311
|
if (!value || typeof value != "object" || Array.isArray(value)) throw unavailable();
|
|
1185
1312
|
let { name, ...metadata } = value;
|
|
1186
1313
|
if (!safeEnrichmentName(name)) throw unavailable();
|
|
@@ -1195,22 +1322,22 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1195
1322
|
throw unavailable();
|
|
1196
1323
|
}
|
|
1197
1324
|
function idPath(id3) {
|
|
1198
|
-
if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw
|
|
1325
|
+
if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw invalid5();
|
|
1199
1326
|
return `/${id3}`;
|
|
1200
1327
|
}
|
|
1201
1328
|
async function multipartCreate(input, metadata, exchange, release = () => {
|
|
1202
1329
|
active--;
|
|
1203
1330
|
}, upload) {
|
|
1204
|
-
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) => {
|
|
1205
1332
|
let task = work(signal);
|
|
1206
1333
|
return pending.add(task), task.then(() => pending.delete(task), () => pending.delete(task)), task;
|
|
1207
|
-
}, void 0, timeout), control = (
|
|
1334
|
+
}, void 0, timeout), control = (body) => ({
|
|
1208
1335
|
method: "POST",
|
|
1209
1336
|
headers: { "content-type": "application/json", ...ticket ? { "x-oddington-transfer": ticket } : {} },
|
|
1210
|
-
body: JSON.stringify(
|
|
1337
|
+
body: JSON.stringify(body)
|
|
1211
1338
|
});
|
|
1212
1339
|
try {
|
|
1213
|
-
let start = await
|
|
1340
|
+
let start = await request2((signal) => exchange(`${route}/start`, control(upload?.file ?? metadata), "control", signal));
|
|
1214
1341
|
if (!start || typeof start != "object" || Array.isArray(start)) throw unavailable();
|
|
1215
1342
|
let session = start;
|
|
1216
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();
|
|
@@ -1218,7 +1345,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1218
1345
|
let lastProgress = Date.now(), next = async () => {
|
|
1219
1346
|
try {
|
|
1220
1347
|
if (Date.now() - lastProgress >= TIMEOUT_MS) throw unavailable();
|
|
1221
|
-
let value = await
|
|
1348
|
+
let value = await request2(() => reader.read(), Math.max(1, TIMEOUT_MS - (Date.now() - lastProgress)));
|
|
1222
1349
|
return value.value?.byteLength && (lastProgress = Date.now()), value;
|
|
1223
1350
|
} catch (error) {
|
|
1224
1351
|
throw await reader.cancel(error).catch(() => {
|
|
@@ -1230,7 +1357,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1230
1357
|
if (input.file instanceof Uint8Array) part = input.file.subarray(sent, sent + length).slice();
|
|
1231
1358
|
else if (input.file instanceof Blob) {
|
|
1232
1359
|
let slice = input.file.slice(sent, sent + length);
|
|
1233
|
-
part = new Uint8Array(await
|
|
1360
|
+
part = new Uint8Array(await request2(() => slice.arrayBuffer()));
|
|
1234
1361
|
} else {
|
|
1235
1362
|
part = new Uint8Array(length);
|
|
1236
1363
|
let filled = 0;
|
|
@@ -1238,20 +1365,20 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1238
1365
|
if (!chunk || offset === chunk.byteLength) {
|
|
1239
1366
|
chunk = void 0, offset = 0;
|
|
1240
1367
|
let value2 = await next();
|
|
1241
|
-
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();
|
|
1242
1369
|
}
|
|
1243
1370
|
let take = Math.min(length - filled, chunk.byteLength - offset);
|
|
1244
1371
|
part.set(chunk.subarray(offset, offset + take), filled), filled += take, offset += take, offset === chunk.byteLength && (chunk = void 0, offset = 0);
|
|
1245
1372
|
}
|
|
1246
1373
|
}
|
|
1247
|
-
if (part.byteLength !== length) throw
|
|
1374
|
+
if (part.byteLength !== length) throw invalid5();
|
|
1248
1375
|
if (reader && sent + length === metadata.size)
|
|
1249
1376
|
for (lastProgress = Date.now(); ; ) {
|
|
1250
1377
|
let value2 = await next();
|
|
1251
1378
|
if (value2.done) break;
|
|
1252
|
-
if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw
|
|
1379
|
+
if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw invalid5();
|
|
1253
1380
|
}
|
|
1254
|
-
let value = await
|
|
1381
|
+
let value = await request2((signal) => exchange(`${route}/part`, {
|
|
1255
1382
|
method: "POST",
|
|
1256
1383
|
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket, "x-oddington-part": String(partNumber) },
|
|
1257
1384
|
body: part.buffer
|
|
@@ -1262,9 +1389,9 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1262
1389
|
receipts.push({ partNumber, etag: receipt.etag }), sent += length, lastProgress = Date.now();
|
|
1263
1390
|
}
|
|
1264
1391
|
if (upload) for (let name of Object.keys(upload.file.enrichments)) {
|
|
1265
|
-
let bytes = await
|
|
1266
|
-
if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw
|
|
1267
|
-
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)}`, {
|
|
1268
1395
|
method: "POST",
|
|
1269
1396
|
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket },
|
|
1270
1397
|
body: bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)
|
|
@@ -1273,13 +1400,13 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1273
1400
|
await upload?.beforeComplete();
|
|
1274
1401
|
let completion = control({ parts: receipts });
|
|
1275
1402
|
if (new TextEncoder().encode(completion.body).byteLength > 128 * 1024) throw unavailable();
|
|
1276
|
-
return parseFileDescriptor(await
|
|
1403
|
+
return parseFileDescriptor(await request2(
|
|
1277
1404
|
(signal) => exchange(`${route}/complete`, completion, !0, signal),
|
|
1278
1405
|
TIMEOUT_MS + Math.ceil(metadata.size / (1024 * 1024)) * 1e3
|
|
1279
1406
|
));
|
|
1280
1407
|
} catch (error) {
|
|
1281
1408
|
throw reader && await reader.cancel(error).catch(() => {
|
|
1282
|
-
}), ticket && await
|
|
1409
|
+
}), ticket && await request2((signal) => exchange(`${route}/abort`, control({}), "control", signal)).catch(() => {
|
|
1283
1410
|
}), error instanceof FileOperationError ? error : unavailable();
|
|
1284
1411
|
} finally {
|
|
1285
1412
|
chunk = void 0, reader?.releaseLock(), pending.size ? Promise.allSettled([...pending]).then(release) : release();
|
|
@@ -1301,7 +1428,7 @@ async function operation(work, initial, parent) {
|
|
|
1301
1428
|
function contentPath(id3, name) {
|
|
1302
1429
|
let path = idPath(id3);
|
|
1303
1430
|
if (name === void 0) return `${path}/content`;
|
|
1304
|
-
if (!safeEnrichmentName(name)) throw
|
|
1431
|
+
if (!safeEnrichmentName(name)) throw invalid5();
|
|
1305
1432
|
return `${path}/enrichments/${encodeURIComponent(name)}/content`;
|
|
1306
1433
|
}
|
|
1307
1434
|
async function read(id3, names) {
|
|
@@ -1310,12 +1437,12 @@ async function read(id3, names) {
|
|
|
1310
1437
|
let path = contentPath(id3, names);
|
|
1311
1438
|
return operation((context3, signal) => send(path, { method: "GET" }, !1, context3, signal), context2);
|
|
1312
1439
|
}
|
|
1313
|
-
if (!Array.isArray(names)) throw
|
|
1440
|
+
if (!Array.isArray(names)) throw invalid5();
|
|
1314
1441
|
let distinct = [], seen = /* @__PURE__ */ new Set();
|
|
1315
1442
|
for (let name of names) {
|
|
1316
|
-
if (typeof name != "string" || !safeEnrichmentName(name)) throw
|
|
1443
|
+
if (typeof name != "string" || !safeEnrichmentName(name)) throw invalid5();
|
|
1317
1444
|
if (!seen.has(name)) {
|
|
1318
|
-
if (seen.size === 16) throw
|
|
1445
|
+
if (seen.size === 16) throw invalid5();
|
|
1319
1446
|
seen.add(name), distinct.push(name);
|
|
1320
1447
|
}
|
|
1321
1448
|
}
|
|
@@ -1350,11 +1477,11 @@ var files = {
|
|
|
1350
1477
|
async create(input, options) {
|
|
1351
1478
|
let context2 = await resolveFilesContext();
|
|
1352
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")))
|
|
1353
|
-
throw
|
|
1480
|
+
throw invalid5();
|
|
1354
1481
|
let blob = input.file instanceof Blob, array3 = input.file instanceof Uint8Array, stream = input.file instanceof ReadableStream;
|
|
1355
|
-
if (!blob && !array3 && !stream) throw
|
|
1482
|
+
if (!blob && !array3 && !stream) throw invalid5();
|
|
1356
1483
|
let intrinsic = blob ? input.file.size : array3 ? input.file.byteLength : void 0;
|
|
1357
|
-
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();
|
|
1358
1485
|
let name = input.name;
|
|
1359
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));
|
|
1360
1487
|
let metadata = parseFileCreateMetadata({
|
|
@@ -1368,7 +1495,7 @@ var files = {
|
|
|
1368
1495
|
}, FILE_ORIGINAL_MAX_BYTES);
|
|
1369
1496
|
if (!context2.local && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
|
|
1370
1497
|
let header = encodeURIComponent(JSON.stringify(metadata));
|
|
1371
|
-
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw
|
|
1498
|
+
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid5();
|
|
1372
1499
|
if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
|
|
1373
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) => {
|
|
1374
1501
|
try {
|
|
@@ -1376,7 +1503,7 @@ var files = {
|
|
|
1376
1503
|
blob ? input.file.stream() : input.file,
|
|
1377
1504
|
metadata.size
|
|
1378
1505
|
);
|
|
1379
|
-
if (bytes.byteLength !== metadata.size) throw
|
|
1506
|
+
if (bytes.byteLength !== metadata.size) throw invalid5();
|
|
1380
1507
|
if (signal.aborted) throw unavailable();
|
|
1381
1508
|
return await send("", {
|
|
1382
1509
|
method: "POST",
|
|
@@ -1392,7 +1519,7 @@ var files = {
|
|
|
1392
1519
|
},
|
|
1393
1520
|
async enrich(input) {
|
|
1394
1521
|
let context2 = await resolveFilesContext();
|
|
1395
|
-
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();
|
|
1396
1523
|
let path = `${idPath(input.file)}/enrichments`;
|
|
1397
1524
|
if (typeof input.content == "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
|
|
1398
1525
|
throw new FileOperationError("request_too_large", 413);
|
|
@@ -1409,7 +1536,7 @@ var files = {
|
|
|
1409
1536
|
...input.mediaType === void 0 ? {} : { mediaType: input.mediaType },
|
|
1410
1537
|
...input.replace === void 0 ? {} : { replace: input.replace }
|
|
1411
1538
|
}, MAX_BYTES), header = encodeURIComponent(JSON.stringify(metadata));
|
|
1412
|
-
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw
|
|
1539
|
+
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid5();
|
|
1413
1540
|
let result2 = await send(path, { method: "POST", headers: {
|
|
1414
1541
|
"content-type": "application/octet-stream",
|
|
1415
1542
|
"x-oddington-enrichment": header
|
|
@@ -1445,8 +1572,8 @@ function parseConnectionLease(raw, now = Date.now()) {
|
|
|
1445
1572
|
}
|
|
1446
1573
|
|
|
1447
1574
|
var AirtableOperationError = class extends Error {
|
|
1448
|
-
constructor(
|
|
1449
|
-
super(
|
|
1575
|
+
constructor(message2, effect = "unapplied", receipts = []) {
|
|
1576
|
+
super(message2);
|
|
1450
1577
|
this.effect = effect;
|
|
1451
1578
|
this.receipts = receipts;
|
|
1452
1579
|
this.name = "AirtableOperationError";
|
|
@@ -1456,10 +1583,10 @@ var AirtableOperationError = class extends Error {
|
|
|
1456
1583
|
};
|
|
1457
1584
|
|
|
1458
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);
|
|
1459
|
-
function fail2(
|
|
1460
|
-
throw new AirtableOperationError(
|
|
1586
|
+
function fail2(message2) {
|
|
1587
|
+
throw new AirtableOperationError(message2);
|
|
1461
1588
|
}
|
|
1462
|
-
function
|
|
1589
|
+
function object3(v) {
|
|
1463
1590
|
return (!v || typeof v != "object" || Array.isArray(v) || ![null, Object.prototype].includes(Object.getPrototypeOf(v))) && fail2("Invalid Airtable data"), v;
|
|
1464
1591
|
}
|
|
1465
1592
|
function keys2(v, allowed, required = allowed) {
|
|
@@ -1468,8 +1595,8 @@ function keys2(v, allowed, required = allowed) {
|
|
|
1468
1595
|
function text2(v) {
|
|
1469
1596
|
return typeof v == "string" && v.length > 0 && v.length <= 1024;
|
|
1470
1597
|
}
|
|
1471
|
-
function
|
|
1472
|
-
let result2 =
|
|
1598
|
+
function fields4(v, nonempty = !1) {
|
|
1599
|
+
let result2 = object3(v);
|
|
1473
1600
|
(nonempty && !Object.keys(result2).length || Object.keys(result2).some((k) => !text2(k))) && fail2("Invalid Airtable fields");
|
|
1474
1601
|
try {
|
|
1475
1602
|
return serializable(result2);
|
|
@@ -1478,8 +1605,8 @@ function fields3(v, nonempty = !1) {
|
|
|
1478
1605
|
}
|
|
1479
1606
|
}
|
|
1480
1607
|
function record2(v) {
|
|
1481
|
-
let r =
|
|
1482
|
-
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) };
|
|
1483
1610
|
}
|
|
1484
1611
|
function equal(a, b) {
|
|
1485
1612
|
if (a === b) return !0;
|
|
@@ -1511,7 +1638,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1511
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");
|
|
1512
1639
|
let input;
|
|
1513
1640
|
try {
|
|
1514
|
-
input =
|
|
1641
|
+
input = object3(serializable(raw));
|
|
1515
1642
|
} catch {
|
|
1516
1643
|
return fail2("Invalid Airtable input");
|
|
1517
1644
|
}
|
|
@@ -1523,7 +1650,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1523
1650
|
operation: operation2.slice(8),
|
|
1524
1651
|
records: ids2.map((id3) => ({ id: id3 }))
|
|
1525
1652
|
});
|
|
1526
|
-
async function
|
|
1653
|
+
async function request2(path2, init2 = {}, write = !1) {
|
|
1527
1654
|
let response2;
|
|
1528
1655
|
try {
|
|
1529
1656
|
response2 = await (options.fetch ?? fetch)(`https://api.airtable.com/v0/${path2}`, {
|
|
@@ -1540,7 +1667,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1540
1667
|
}), new AirtableOperationError("Airtable request rejected", write && (response2.status >= 500 || response2.status === 408 || response2.status < 400) ? "uncertain" : "unapplied");
|
|
1541
1668
|
try {
|
|
1542
1669
|
if (!response2.headers.get("content-type")?.toLowerCase().includes("application/json")) throw new Error();
|
|
1543
|
-
let value =
|
|
1670
|
+
let value = object3(await response2.json()), safe = serializable(value);
|
|
1544
1671
|
if (Object.hasOwn(value, "error") || JSON.stringify(safe).includes(accessToken)) throw new Error();
|
|
1545
1672
|
return value;
|
|
1546
1673
|
} catch {
|
|
@@ -1551,13 +1678,13 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1551
1678
|
keys2(input, []);
|
|
1552
1679
|
let tables = [], seen = /* @__PURE__ */ new Set(), offset;
|
|
1553
1680
|
do {
|
|
1554
|
-
let query2 = new URLSearchParams(offset ? { offset } : {}), page = await
|
|
1681
|
+
let query2 = new URLSearchParams(offset ? { offset } : {}), page = await request2(`meta/bases/${baseId}/tables?${query2}`);
|
|
1555
1682
|
Array.isArray(page.tables) || fail2("Malformed Airtable tables");
|
|
1556
1683
|
for (let value of page.tables) {
|
|
1557
|
-
let t =
|
|
1684
|
+
let t = object3(value);
|
|
1558
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");
|
|
1559
1686
|
let metadata = t.fields.map((value2) => {
|
|
1560
|
-
let f =
|
|
1687
|
+
let f = object3(value2);
|
|
1561
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) } };
|
|
1562
1689
|
});
|
|
1563
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 });
|
|
@@ -1570,7 +1697,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1570
1697
|
let path = `${baseId}/${encodeURIComponent(input.table)}`;
|
|
1571
1698
|
if (operation2 === "records.get") {
|
|
1572
1699
|
keys2(input, ["table", "id"]), recordId(input.id) || fail2("Invalid Airtable record ID");
|
|
1573
|
-
let result3 = record2(await
|
|
1700
|
+
let result3 = record2(await request2(`${path}/${input.id}`));
|
|
1574
1701
|
return result3.id !== input.id && fail2("Malformed Airtable record"), result3;
|
|
1575
1702
|
}
|
|
1576
1703
|
if (operation2 === "records.list") {
|
|
@@ -1580,7 +1707,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1580
1707
|
let query2 = new URLSearchParams();
|
|
1581
1708
|
for (let field of input.fields ?? []) query2.append("fields[]", field);
|
|
1582
1709
|
offset && query2.set("offset", offset);
|
|
1583
|
-
let page = await
|
|
1710
|
+
let page = await request2(`${path}?${query2}`);
|
|
1584
1711
|
Array.isArray(page.records) || fail2("Malformed Airtable records");
|
|
1585
1712
|
for (let value of page.records) {
|
|
1586
1713
|
let r = record2(value);
|
|
@@ -1592,15 +1719,15 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1592
1719
|
}
|
|
1593
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");
|
|
1594
1721
|
let kind = operation2.slice(8), ids = /* @__PURE__ */ new Set(), records = input.records.map((value) => {
|
|
1595
|
-
let r =
|
|
1596
|
-
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) };
|
|
1597
1724
|
(!recordId(r.id) || ids.has(r.id)) && fail2("Invalid Airtable batch record ID"), ids.add(r.id);
|
|
1598
|
-
let set = kind === "update" ?
|
|
1599
|
-
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 } : {} };
|
|
1600
1727
|
});
|
|
1601
1728
|
for (let r of records) {
|
|
1602
1729
|
if (!("id" in r)) continue;
|
|
1603
|
-
let current2 = record2(await
|
|
1730
|
+
let current2 = record2(await request2(`${path}/${r.id}`));
|
|
1604
1731
|
current2.id !== r.id && fail2("Malformed Airtable record");
|
|
1605
1732
|
for (let [key, value] of Object.entries(r.expected))
|
|
1606
1733
|
(value === null ? Object.hasOwn(current2.fields, key) : !Object.hasOwn(current2.fields, key) || !equal(current2.fields[key], value)) && fail2("Airtable reviewed values are stale");
|
|
@@ -1608,14 +1735,14 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
|
|
|
1608
1735
|
await options.beforeMutation?.();
|
|
1609
1736
|
let query = new URLSearchParams();
|
|
1610
1737
|
if (kind === "delete") for (let id3 of ids) query.append("records[]", id3);
|
|
1611
|
-
let result2 = await
|
|
1738
|
+
let result2 = await request2(`${path}${kind === "delete" ? `?${query}` : ""}`, {
|
|
1612
1739
|
method: kind === "create" ? "POST" : kind === "update" ? "PATCH" : "DELETE",
|
|
1613
1740
|
...kind === "delete" ? {} : { body: JSON.stringify({ records: records.map((r) => "id" in r ? { id: r.id, fields: r.set } : r) }) }
|
|
1614
1741
|
}, !0), acknowledged = [], returned = [];
|
|
1615
1742
|
try {
|
|
1616
1743
|
if (!Array.isArray(result2.records)) throw new Error();
|
|
1617
1744
|
for (let value of result2.records) {
|
|
1618
|
-
let r =
|
|
1745
|
+
let r = object3(value);
|
|
1619
1746
|
if (!recordId(r.id) || acknowledged.includes(r.id) || kind !== "create" && !ids.has(r.id) || kind === "delete" && r.deleted !== !0) throw new Error();
|
|
1620
1747
|
acknowledged.push(r.id), kind !== "delete" && returned.push(record2(r));
|
|
1621
1748
|
}
|
|
@@ -1717,8 +1844,8 @@ var connections = /* @__PURE__ */ createConnections(async (name, operation2, inp
|
|
|
1717
1844
|
var LOCAL_ROUTINE_VALUE_BYTES = 256 * 1024;
|
|
1718
1845
|
|
|
1719
1846
|
var RECORD_WRITE_INPUT_LIMIT = 8 * 1024 * 1024, RoutineRecordWriteError = class extends Error {
|
|
1720
|
-
constructor(
|
|
1721
|
-
super(
|
|
1847
|
+
constructor(message2, effect) {
|
|
1848
|
+
super(message2);
|
|
1722
1849
|
this.effect = effect;
|
|
1723
1850
|
this.name = "RoutineRecordWriteError";
|
|
1724
1851
|
}
|
|
@@ -1769,10 +1896,10 @@ function validateRecordChange(value) {
|
|
|
1769
1896
|
return writes.length && validateRecordWrite({ repository: input.repository, records: writes }), deletes.length && validateRecordDelete({ repository: input.repository, records: deletes }), structuredClone(input);
|
|
1770
1897
|
}
|
|
1771
1898
|
function validateRoutineRecordWrite(value) {
|
|
1772
|
-
let
|
|
1773
|
-
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)
|
|
1774
1901
|
throw new InboxContractError("A stable routine request key is required");
|
|
1775
|
-
return { input: validateRecordChange(
|
|
1902
|
+
return { input: validateRecordChange(body.input), requestKey: body.requestKey };
|
|
1776
1903
|
}
|
|
1777
1904
|
function validCreatePath(value) {
|
|
1778
1905
|
return value === value.trim() && value.endsWith(".md") && !value.startsWith("/") && value.split("/").every((segment) => !!segment && ![".", ".."].includes(segment) && /^[a-zA-Z0-9_.-]+$/.test(segment));
|
|
@@ -1808,10 +1935,10 @@ var operations = {
|
|
|
1808
1935
|
function assert(value) {
|
|
1809
1936
|
if (!value) throw new Error("Invalid Inbox result");
|
|
1810
1937
|
}
|
|
1811
|
-
function
|
|
1938
|
+
function object4(value) {
|
|
1812
1939
|
return assert(value && typeof value == "object" && !Array.isArray(value) && [Object.prototype, null].includes(Object.getPrototypeOf(value)) && Reflect.ownKeys(value).every((key) => {
|
|
1813
|
-
let
|
|
1814
|
-
return !!
|
|
1940
|
+
let descriptor = typeof key == "string" ? Object.getOwnPropertyDescriptor(value, key) : void 0;
|
|
1941
|
+
return !!descriptor?.enumerable && "value" in descriptor;
|
|
1815
1942
|
})), value;
|
|
1816
1943
|
}
|
|
1817
1944
|
function keys3(value, allowed, required = allowed) {
|
|
@@ -1834,41 +1961,41 @@ function optionalDate(value) {
|
|
|
1834
1961
|
}
|
|
1835
1962
|
function array2(value) {
|
|
1836
1963
|
return assert(Array.isArray(value) && Object.getPrototypeOf(value) === Array.prototype && Reflect.ownKeys(value).length === value.length + 1 && value.every((_entry, index) => {
|
|
1837
|
-
let
|
|
1838
|
-
return !!
|
|
1964
|
+
let descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
1965
|
+
return !!descriptor?.enumerable && "value" in descriptor;
|
|
1839
1966
|
})), value;
|
|
1840
1967
|
}
|
|
1841
1968
|
function json2(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
1842
1969
|
if (value === null || typeof value == "boolean" || typeof value == "string" || typeof value == "number" && Number.isFinite(value)) return value;
|
|
1843
1970
|
assert(value && typeof value == "object" && !ancestors.has(value)), ancestors.add(value);
|
|
1844
1971
|
try {
|
|
1845
|
-
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)]));
|
|
1846
1973
|
} finally {
|
|
1847
1974
|
ancestors.delete(value);
|
|
1848
1975
|
}
|
|
1849
1976
|
}
|
|
1850
1977
|
function recordReference(value) {
|
|
1851
|
-
let record3 =
|
|
1978
|
+
let record3 = object4(value);
|
|
1852
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;
|
|
1853
1980
|
}
|
|
1854
1981
|
function responseDefinition(value) {
|
|
1855
|
-
let definition =
|
|
1982
|
+
let definition = object4(value);
|
|
1856
1983
|
keys3(definition, ["type", "source"]), assert(definition.type === "selection");
|
|
1857
|
-
let source =
|
|
1984
|
+
let source = object4(definition.source);
|
|
1858
1985
|
if (source.type === "authored") {
|
|
1859
1986
|
keys3(source, ["type", "options", "suggestions", "search"], ["type", "options"]);
|
|
1860
1987
|
let options = array2(source.options);
|
|
1861
1988
|
assert(options.length > 0);
|
|
1862
1989
|
let values = options.map((value2) => {
|
|
1863
|
-
let option =
|
|
1990
|
+
let option = object4(value2);
|
|
1864
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) {
|
|
1865
|
-
let note =
|
|
1992
|
+
let note = object4(option.note);
|
|
1866
1993
|
keys3(note, ["placeholder"]), assert(text3(note.placeholder));
|
|
1867
1994
|
}
|
|
1868
1995
|
return option.value;
|
|
1869
1996
|
});
|
|
1870
1997
|
if (assert(new Set(values).size === values.length), "search" in source || "suggestions" in source) {
|
|
1871
|
-
let search =
|
|
1998
|
+
let search = object4(source.search);
|
|
1872
1999
|
keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text3(search.triggerLabel) && text3(search.placeholder) && text3(search.emptyLabel));
|
|
1873
2000
|
let suggestions2 = array2(source.suggestions);
|
|
1874
2001
|
assert(suggestions2.length <= 8 && suggestions2.every((value2) => text3(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
|
|
@@ -1876,16 +2003,16 @@ function responseDefinition(value) {
|
|
|
1876
2003
|
return;
|
|
1877
2004
|
}
|
|
1878
2005
|
assert(source.type === "records"), keys3(source, ["type", "collection", "refPrefix", "where", "display", "suggestions"], ["type", "collection", "display"]);
|
|
1879
|
-
let collection =
|
|
2006
|
+
let collection = object4(source.collection);
|
|
1880
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));
|
|
1881
|
-
let where =
|
|
2008
|
+
let where = object4(source.where ?? {});
|
|
1882
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))));
|
|
1883
|
-
let display =
|
|
2010
|
+
let display = object4(source.display);
|
|
1884
2011
|
keys3(display, ["labelFields"]);
|
|
1885
2012
|
let labels = array2(display.labelFields);
|
|
1886
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)));
|
|
1887
2014
|
let suggestions = array2(source.suggestions ?? []), refs = suggestions.map((value2) => {
|
|
1888
|
-
let suggestion =
|
|
2015
|
+
let suggestion = object4(value2);
|
|
1889
2016
|
keys3(suggestion, ["record", "reason"], ["record"]);
|
|
1890
2017
|
let record3 = recordReference(suggestion.record);
|
|
1891
2018
|
return assert(record3.repository === collection.repository), "reason" in suggestion && assert(text3(suggestion.reason)), record3.ref;
|
|
@@ -1893,20 +2020,20 @@ function responseDefinition(value) {
|
|
|
1893
2020
|
assert(suggestions.length <= 8 && new Set(refs).size === refs.length);
|
|
1894
2021
|
}
|
|
1895
2022
|
function inboxFile(value) {
|
|
1896
|
-
let file2 =
|
|
2023
|
+
let file2 = object4(value);
|
|
1897
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));
|
|
1898
|
-
let details =
|
|
2025
|
+
let details = object4(file2.details);
|
|
1899
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)));
|
|
1900
2027
|
}
|
|
1901
|
-
function
|
|
2028
|
+
function fields5(value) {
|
|
1902
2029
|
let labels = array2(value).map((value2) => {
|
|
1903
|
-
let field =
|
|
2030
|
+
let field = object4(value2);
|
|
1904
2031
|
return keys3(field, ["label", "value"]), assert(text3(field.label) && text3(field.value)), field.label;
|
|
1905
2032
|
});
|
|
1906
2033
|
assert(new Set(labels).size === labels.length);
|
|
1907
2034
|
}
|
|
1908
2035
|
function block(value) {
|
|
1909
|
-
let entry =
|
|
2036
|
+
let entry = object4(value);
|
|
1910
2037
|
if (entry.kind === "rich-text") {
|
|
1911
2038
|
keys3(entry, ["kind", "markdown"]), assert(text3(entry.markdown));
|
|
1912
2039
|
return;
|
|
@@ -1922,30 +2049,30 @@ function block(value) {
|
|
|
1922
2049
|
["kind", "label", "initiallyExpanded", ...entry.kind === "record" ? ["record", "view"] : entry.kind === "records" ? ["records", "view"] : ["files"]],
|
|
1923
2050
|
["kind", "label", entry.kind === "record" ? "record" : entry.kind === "records" ? "records" : "files"]
|
|
1924
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") {
|
|
1925
|
-
let record3 =
|
|
1926
|
-
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);
|
|
1927
2054
|
return;
|
|
1928
2055
|
}
|
|
1929
2056
|
if (entry.kind === "records") {
|
|
1930
2057
|
let records = array2(entry.records), refs = records.map((value2) => {
|
|
1931
|
-
let record3 =
|
|
1932
|
-
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;
|
|
1933
2060
|
});
|
|
1934
2061
|
assert(records.length > 0 && new Set(refs).size === refs.length);
|
|
1935
2062
|
return;
|
|
1936
2063
|
}
|
|
1937
2064
|
let files3 = array2(entry.files);
|
|
1938
|
-
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);
|
|
1939
2066
|
}
|
|
1940
2067
|
function response(value) {
|
|
1941
|
-
let answer =
|
|
2068
|
+
let answer = object4(value);
|
|
1942
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;
|
|
1943
2070
|
}
|
|
1944
2071
|
function parseInboxRequest(value, questionListContext = "local") {
|
|
1945
2072
|
try {
|
|
1946
|
-
let envelope =
|
|
2073
|
+
let envelope = object4(value);
|
|
1947
2074
|
assert(Object.keys(envelope).sort().join(",") === "input,operation"), assert(typeof envelope.operation == "string" && Object.hasOwn(operations, envelope.operation));
|
|
1948
|
-
let operation2 = envelope.operation, input = { ...
|
|
2075
|
+
let operation2 = envelope.operation, input = { ...object4(envelope.input) }, required = operations[operation2];
|
|
1949
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)));
|
|
1950
2077
|
for (let key of ["itemId", "personId", "fileId"]) key in input && assert(id2(input[key]));
|
|
1951
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 };
|
|
@@ -1954,80 +2081,80 @@ function parseInboxRequest(value, questionListContext = "local") {
|
|
|
1954
2081
|
}
|
|
1955
2082
|
}
|
|
1956
2083
|
function parseInboxCurrent(value) {
|
|
1957
|
-
let current2 =
|
|
2084
|
+
let current2 = object4(value), workspace = object4(current2.workspace), viewer = object4(current2.viewer);
|
|
1958
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)), {
|
|
1959
2086
|
workspace: { id: workspace.id, slug: workspace.slug, name: workspace.name, locale: workspace.locale, timezone: workspace.timezone },
|
|
1960
2087
|
viewer: { id: viewer.id, name: viewer.name, email: viewer.email }
|
|
1961
2088
|
};
|
|
1962
2089
|
}
|
|
1963
2090
|
function parseInboxItem(value) {
|
|
1964
|
-
let item =
|
|
1965
|
-
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(
|
|
1966
|
-
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);
|
|
1967
2094
|
assert(text3(view.id) && text3(view.view) && text3(view.implementation)), json2(view.input);
|
|
1968
2095
|
}), array2(item.people).forEach((value2) => {
|
|
1969
|
-
let person =
|
|
2096
|
+
let person = object4(value2);
|
|
1970
2097
|
assert(id2(person.id) && text3(person.name));
|
|
1971
2098
|
}), array2(item.questions).forEach((value2) => {
|
|
1972
|
-
let question2 =
|
|
2099
|
+
let question2 = object4(value2);
|
|
1973
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) {
|
|
1974
|
-
let accepted =
|
|
2101
|
+
let accepted = object4(question2.acceptedResponse);
|
|
1975
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));
|
|
1976
2103
|
}
|
|
1977
2104
|
if (question2.execution !== null) {
|
|
1978
|
-
let execution =
|
|
2105
|
+
let execution = object4(question2.execution);
|
|
1979
2106
|
if (assert(id2(execution.id) && ["pending", "running", "completed", "failed"].includes(String(execution.state)) && integer(execution.attempt, 0)), "consequence" in execution) {
|
|
1980
|
-
let consequence =
|
|
2107
|
+
let consequence = object4(execution.consequence);
|
|
1981
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) => {
|
|
1982
|
-
let receipt =
|
|
2109
|
+
let receipt = object4(value3);
|
|
1983
2110
|
assert(text3(receipt.repository) && text3(receipt.commit) && text3(receipt.diff, !0));
|
|
1984
2111
|
});
|
|
1985
2112
|
}
|
|
1986
2113
|
}
|
|
1987
2114
|
}), array2(item.linkedAsks).forEach((value2) => {
|
|
1988
|
-
let linked =
|
|
2115
|
+
let linked = object4(value2);
|
|
1989
2116
|
if (assert(id2(linked.id)), linked.state === "unavailable") assert(typeof linked.done == "boolean");
|
|
1990
2117
|
else if (assert(["yours", "done", "open", "theirs"].includes(String(linked.state)) && text3(linked.title)), linked.state === "theirs") {
|
|
1991
|
-
let assignee =
|
|
2118
|
+
let assignee = object4(linked.assignee);
|
|
1992
2119
|
assert(id2(assignee.id) && text3(assignee.name));
|
|
1993
2120
|
}
|
|
1994
2121
|
}), array2(item.activity).forEach((value2) => {
|
|
1995
|
-
let
|
|
1996
|
-
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);
|
|
1997
2124
|
}), array2(item.work).forEach((value2) => {
|
|
1998
|
-
let work =
|
|
2125
|
+
let work = object4(value2);
|
|
1999
2126
|
assert(id2(work.id) && text3(work.questionId) && text3(work.reason) && optionalDate(work.settledAt));
|
|
2000
2127
|
}), item;
|
|
2001
2128
|
}
|
|
2002
2129
|
function parseAnswerableQuestion(value) {
|
|
2003
|
-
let entry =
|
|
2130
|
+
let entry = object4(json2(value));
|
|
2004
2131
|
keys3(entry, ["item", "origin", "question", "recordRefs"]);
|
|
2005
|
-
let item =
|
|
2132
|
+
let item = object4(entry.item);
|
|
2006
2133
|
keys3(item, ["id", "number", "revision", "title", "href"]), assert(id2(item.id) && integer(item.number) && integer(item.revision) && text3(item.title) && text3(item.href));
|
|
2007
2134
|
let link = new URL(item.href), slug = link.hostname.slice(0, -13);
|
|
2008
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}`);
|
|
2009
|
-
let origin =
|
|
2136
|
+
let origin = object4(entry.origin);
|
|
2010
2137
|
keys3(origin, ["routine"]), assert(text3(origin.routine) && origin.routine === origin.routine.trim());
|
|
2011
|
-
let question2 =
|
|
2138
|
+
let question2 = object4(entry.question);
|
|
2012
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);
|
|
2013
2140
|
let refs = array2(entry.recordRefs);
|
|
2014
2141
|
return assert(refs.every((ref) => text3(ref) && ref === ref.trim()) && new Set(refs).size === refs.length), entry;
|
|
2015
2142
|
}
|
|
2016
2143
|
function parseInboxAcceptance(value) {
|
|
2017
|
-
let accepted =
|
|
2144
|
+
let accepted = object4(value);
|
|
2018
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;
|
|
2019
2146
|
}
|
|
2020
2147
|
function parseInboxResult(operation2, value) {
|
|
2021
2148
|
if (operation2 === "current") return parseInboxCurrent(value);
|
|
2022
2149
|
if (operation2 === "questions.list") {
|
|
2023
|
-
let page =
|
|
2150
|
+
let page = object4(value);
|
|
2024
2151
|
keys3(page, ["questions", "nextBeforeNumber"]);
|
|
2025
2152
|
let questions = array2(page.questions).map(parseAnswerableQuestion);
|
|
2026
2153
|
return assert(page.nextBeforeNumber === null || integer(page.nextBeforeNumber)), { questions, nextBeforeNumber: page.nextBeforeNumber };
|
|
2027
2154
|
}
|
|
2028
2155
|
if (operation2 === "items.read") return parseInboxItem(value);
|
|
2029
2156
|
if (operation2 === "items.list") {
|
|
2030
|
-
let page =
|
|
2157
|
+
let page = object4(value), items = array2(page.items).map(parseInboxItem);
|
|
2031
2158
|
return assert(items.length <= 100 && (page.nextBeforeNumber === null || integer(page.nextBeforeNumber))), { items, nextBeforeNumber: page.nextBeforeNumber };
|
|
2032
2159
|
}
|
|
2033
2160
|
if (operation2 === "items.see") {
|
|
@@ -2035,30 +2162,30 @@ function parseInboxResult(operation2, value) {
|
|
|
2035
2162
|
return;
|
|
2036
2163
|
}
|
|
2037
2164
|
if (operation2 === "items.markDigestRead") {
|
|
2038
|
-
let read2 =
|
|
2165
|
+
let read2 = object4(value);
|
|
2039
2166
|
return assert(integer(read2.activityId) && date(read2.readAt)), read2;
|
|
2040
2167
|
}
|
|
2041
2168
|
if (operation2 === "items.rename" || operation2 === "items.setLifecycle") {
|
|
2042
|
-
let update =
|
|
2169
|
+
let update = object4(value), item = parseInboxItem(update.item);
|
|
2043
2170
|
return assert((update.activityId === null || integer(update.activityId)) && optionalDate(update.changedAt)), { ...update, item };
|
|
2044
2171
|
}
|
|
2045
2172
|
if (operation2 === "items.listRecipientCandidates") {
|
|
2046
2173
|
let candidates = array2(value);
|
|
2047
2174
|
return candidates.forEach((value2) => {
|
|
2048
|
-
let person =
|
|
2175
|
+
let person = object4(value2);
|
|
2049
2176
|
assert(id2(person.id) && text3(person.name) && text3(person.email));
|
|
2050
|
-
}), assert(new Set(candidates.map((value2) =>
|
|
2177
|
+
}), assert(new Set(candidates.map((value2) => object4(value2).id)).size === candidates.length), candidates;
|
|
2051
2178
|
}
|
|
2052
2179
|
if (operation2 === "items.addRecipient") {
|
|
2053
|
-
let addition =
|
|
2180
|
+
let addition = object4(value), item = parseInboxItem(addition.item);
|
|
2054
2181
|
return assert(id2(addition.addedPersonId) && item.people.some((person) => person.id === addition.addedPersonId)), { ...addition, item };
|
|
2055
2182
|
}
|
|
2056
2183
|
if (operation2 === "questions.answer") return parseInboxAcceptance(value);
|
|
2057
2184
|
if (operation2 === "questions.searchRecords") {
|
|
2058
|
-
let result2 =
|
|
2185
|
+
let result2 = object4(value);
|
|
2059
2186
|
assert(text3(result2.recordType) && integer(result2.eligibleCount, 0) && integer(result2.matchCount, 0) && Number(result2.matchCount) <= Number(result2.eligibleCount));
|
|
2060
2187
|
let labeled = (value2) => {
|
|
2061
|
-
let record3 =
|
|
2188
|
+
let record3 = object4(value2);
|
|
2062
2189
|
recordReference({ repository: record3.repository, ref: record3.ref }), assert(text3(record3.label)), "reason" in record3 && assert(text3(record3.reason));
|
|
2063
2190
|
};
|
|
2064
2191
|
return array2(result2.matches).forEach(labeled), array2(result2.suggestions).forEach(labeled), "selected" in result2 && labeled(result2.selected), result2;
|
|
@@ -2066,9 +2193,9 @@ function parseInboxResult(operation2, value) {
|
|
|
2066
2193
|
throw new Error("File content is not a JSON result");
|
|
2067
2194
|
}
|
|
2068
2195
|
|
|
2069
|
-
async function limitedBody(
|
|
2070
|
-
if (!
|
|
2071
|
-
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(() => {
|
|
2072
2199
|
expired = !0, reader.cancel().catch(() => {
|
|
2073
2200
|
});
|
|
2074
2201
|
}, timeoutMs), chunks = [], length = 0;
|
|
@@ -2213,7 +2340,7 @@ function appContext(origin, active2) {
|
|
|
2213
2340
|
}
|
|
2214
2341
|
}, cancel = () => {
|
|
2215
2342
|
controller.abort(), access.abort(), clearTimeout(expiry), clearTimeout(startup), clearTimeout(renewalTimer), clearInterval(monitor), globalThis.removeEventListener?.("storage", storageChanged);
|
|
2216
|
-
for (let
|
|
2343
|
+
for (let event of ["pageshow", "focus", "visibilitychange"]) globalThis.removeEventListener?.(event, wake);
|
|
2217
2344
|
}, invalidate = () => {
|
|
2218
2345
|
denied = !0, cancel();
|
|
2219
2346
|
try {
|
|
@@ -2226,7 +2353,7 @@ function appContext(origin, active2) {
|
|
|
2226
2353
|
} catch {
|
|
2227
2354
|
return !1;
|
|
2228
2355
|
}
|
|
2229
|
-
}, 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) => {
|
|
2230
2357
|
let value = JSON.parse(candidate ?? "null");
|
|
2231
2358
|
if (!validPair(value) || value.context.expiresAt > Date.now() + 6e5 || !sameSession(value.context)) throw new Error();
|
|
2232
2359
|
return value;
|
|
@@ -2261,7 +2388,7 @@ function appContext(origin, active2) {
|
|
|
2261
2388
|
if (response2.status >= 500) throw new AppRenewalUnavailable();
|
|
2262
2389
|
if (!response2.ok) throw new Error();
|
|
2263
2390
|
let value = await appResponse(response2, 4096, signal);
|
|
2264
|
-
if (!alive() || !
|
|
2391
|
+
if (!alive() || !bounded2(value)) throw new Error();
|
|
2265
2392
|
return value;
|
|
2266
2393
|
}
|
|
2267
2394
|
function install(value, candidate, raw) {
|
|
@@ -2333,7 +2460,7 @@ function appContext(origin, active2) {
|
|
|
2333
2460
|
return;
|
|
2334
2461
|
}
|
|
2335
2462
|
if (!response2.ok) throw new Error();
|
|
2336
|
-
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();
|
|
2337
2464
|
if (stored() !== previous) {
|
|
2338
2465
|
await synchronize(requestController.signal);
|
|
2339
2466
|
return;
|
|
@@ -2382,7 +2509,7 @@ function appContext(origin, active2) {
|
|
|
2382
2509
|
alive() && resolve().catch(() => {
|
|
2383
2510
|
});
|
|
2384
2511
|
};
|
|
2385
|
-
for (let
|
|
2512
|
+
for (let event of ["pageshow", "focus", "visibilitychange"]) globalThis.addEventListener?.(event, wake);
|
|
2386
2513
|
let dispose = () => {
|
|
2387
2514
|
disposed = !0, cancel();
|
|
2388
2515
|
};
|
|
@@ -2567,7 +2694,7 @@ async function send2(operation2, input) {
|
|
|
2567
2694
|
} finally {
|
|
2568
2695
|
reader?.releaseLock();
|
|
2569
2696
|
}
|
|
2570
|
-
},
|
|
2697
|
+
}, body = new ReadableStream({
|
|
2571
2698
|
async pull(controller) {
|
|
2572
2699
|
try {
|
|
2573
2700
|
check(), reader ??= source.getReader();
|
|
@@ -2585,7 +2712,7 @@ async function send2(operation2, input) {
|
|
|
2585
2712
|
},
|
|
2586
2713
|
cancel
|
|
2587
2714
|
}, { highWaterMark: 0 });
|
|
2588
|
-
return new Response(
|
|
2715
|
+
return new Response(body, { status: response2.status, headers: response2.headers });
|
|
2589
2716
|
}
|
|
2590
2717
|
let bytes = await limitedBody(response2, INBOX_RESULT_BYTES);
|
|
2591
2718
|
if (check(), !bytes) throw unavailable2();
|
|
@@ -2704,8 +2831,8 @@ function init({ auth: input }) {
|
|
|
2704
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);
|
|
2705
2832
|
} catch {
|
|
2706
2833
|
}
|
|
2707
|
-
let active2 = !0, revision = 0, person, token, binding = {},
|
|
2708
|
-
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();
|
|
2709
2836
|
if (!active2 || !endpoint || !workspace || globalThis.location.origin !== endpoint) throw new Error("Hosted Data context unavailable.");
|
|
2710
2837
|
let started = revision, { data: { session }, error } = await auth2.getSession();
|
|
2711
2838
|
if (!active2 || globalThis.location.origin !== endpoint || started !== revision || error || !session || person !== void 0 && person !== session.user.id)
|
|
@@ -2725,12 +2852,12 @@ function init({ auth: input }) {
|
|
|
2725
2852
|
binding
|
|
2726
2853
|
};
|
|
2727
2854
|
}), dispose = () => {
|
|
2728
|
-
active2 && (active2 = !1,
|
|
2855
|
+
active2 && (active2 = !1, local2?.dispose(), revision++, subscription?.unsubscribe(), stopDisposal?.(), uninstall(), installedDispose === dispose && (installedDispose = void 0));
|
|
2729
2856
|
};
|
|
2730
|
-
installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (subscription = auth2.onAuthStateChange((
|
|
2857
|
+
installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (subscription = auth2.onAuthStateChange((event, session) => {
|
|
2731
2858
|
let next = session?.user.id ?? null;
|
|
2732
|
-
(
|
|
2733
|
-
}).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());
|
|
2734
2861
|
}
|
|
2735
2862
|
var os = { init };
|
|
2736
2863
|
|
|
@@ -2780,19 +2907,19 @@ function createBrowserAuth(runtime) {
|
|
|
2780
2907
|
} catch {
|
|
2781
2908
|
}
|
|
2782
2909
|
}
|
|
2783
|
-
function notify(c,
|
|
2910
|
+
function notify(c, event) {
|
|
2784
2911
|
for (let listener of c.sessions)
|
|
2785
2912
|
try {
|
|
2786
|
-
listener(
|
|
2913
|
+
listener(event, event === "SIGNED_OUT" ? null : c.session);
|
|
2787
2914
|
} catch {
|
|
2788
2915
|
}
|
|
2789
2916
|
}
|
|
2790
2917
|
function expire(c) {
|
|
2791
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"));
|
|
2792
2919
|
}
|
|
2793
|
-
function accept(c,
|
|
2794
|
-
if (!c.active ||
|
|
2795
|
-
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);
|
|
2796
2923
|
replaced && c.revision++, c.timer && clearTimeout(c.timer);
|
|
2797
2924
|
let pending = c.state.pending;
|
|
2798
2925
|
if (!session) {
|
|
@@ -2805,7 +2932,7 @@ function createBrowserAuth(runtime) {
|
|
|
2805
2932
|
}
|
|
2806
2933
|
c.session = session;
|
|
2807
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 });
|
|
2808
|
-
publish(c, { status: "signed_in", account, ...pending ? { pending } : {} }), notify(c,
|
|
2935
|
+
publish(c, { status: "signed_in", account, ...pending ? { pending } : {} }), notify(c, event);
|
|
2809
2936
|
let checkExpiry = () => {
|
|
2810
2937
|
if (!c.active || !c.session) return;
|
|
2811
2938
|
let remaining = c.session.expires_at * 1e3 - Date.now();
|
|
@@ -2845,8 +2972,8 @@ function createBrowserAuth(runtime) {
|
|
|
2845
2972
|
c.provider.dispose();
|
|
2846
2973
|
return;
|
|
2847
2974
|
}
|
|
2848
|
-
let subscription = c.provider.onAuthStateChange((
|
|
2849
|
-
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);
|
|
2850
2977
|
}).data.subscription;
|
|
2851
2978
|
c.unsubscribe = () => subscription.unsubscribe();
|
|
2852
2979
|
let started = c.revision, { data: data3, error } = await c.provider.getSession();
|
|
@@ -3008,7 +3135,7 @@ function createBrowserAuth(runtime) {
|
|
|
3008
3135
|
if (!active2)
|
|
3009
3136
|
return callback("SIGNED_OUT", null), { data: { subscription: { unsubscribe() {
|
|
3010
3137
|
} } } };
|
|
3011
|
-
let listener = (
|
|
3138
|
+
let listener = (event, session) => callback(event, session);
|
|
3012
3139
|
return coordinator.sessions.add(listener), sessionObservers.add(listener), callback("INITIAL_SESSION", coordinator.session), { data: { subscription: { unsubscribe() {
|
|
3013
3140
|
coordinator.sessions.delete(listener), sessionObservers.delete(listener);
|
|
3014
3141
|
} } } };
|
|
@@ -3081,19 +3208,19 @@ async function provider(configuration, guard) {
|
|
|
3081
3208
|
}
|
|
3082
3209
|
},
|
|
3083
3210
|
fetch: Object.assign(async (input, init2) => {
|
|
3084
|
-
let revision = guard.revision(),
|
|
3085
|
-
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");
|
|
3086
3213
|
};
|
|
3087
|
-
|
|
3088
|
-
let response2 = await fetch(input, { ...init2, redirect: "error" }),
|
|
3089
|
-
(!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();
|
|
3090
3217
|
let result2 = new Response(
|
|
3091
|
-
[204, 205, 304].includes(response2.status) ? null :
|
|
3218
|
+
[204, 205, 304].includes(response2.status) ? null : body,
|
|
3092
3219
|
{ status: response2.status, statusText: response2.statusText, headers: response2.headers }
|
|
3093
3220
|
), json3 = result2.json.bind(result2);
|
|
3094
3221
|
return result2.json = async () => {
|
|
3095
3222
|
let value = await json3();
|
|
3096
|
-
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;
|
|
3097
3224
|
}, result2;
|
|
3098
3225
|
}, { preconnect: fetch.preconnect })
|
|
3099
3226
|
});
|
|
@@ -3102,15 +3229,15 @@ async function provider(configuration, guard) {
|
|
|
3102
3229
|
authorizationQueue = new Promise((resolve) => {
|
|
3103
3230
|
release = resolve;
|
|
3104
3231
|
}), await previous;
|
|
3105
|
-
let
|
|
3106
|
-
authorizationRequest =
|
|
3232
|
+
let request2 = { current: current2, rejected: !1 };
|
|
3233
|
+
authorizationRequest = request2;
|
|
3107
3234
|
try {
|
|
3108
3235
|
if (!current2()) throw new BrowserAuthError("stale");
|
|
3109
3236
|
let result2 = await (kind === "get" ? client.oauth.getAuthorizationDetails(id3) : kind === "approve" ? client.oauth.approveAuthorization(id3, { skipBrowserRedirect: !0 }) : client.oauth.denyAuthorization(id3, { skipBrowserRedirect: !0 }));
|
|
3110
|
-
if (
|
|
3237
|
+
if (request2.rejected || !current2()) throw new BrowserAuthError("stale");
|
|
3111
3238
|
return result2;
|
|
3112
3239
|
} catch (error) {
|
|
3113
|
-
throw
|
|
3240
|
+
throw request2.rejected || !current2() ? new BrowserAuthError("stale") : error;
|
|
3114
3241
|
} finally {
|
|
3115
3242
|
authorizationRequest = void 0, release();
|
|
3116
3243
|
}
|
|
@@ -3122,9 +3249,9 @@ async function provider(configuration, guard) {
|
|
|
3122
3249
|
deny: (id3, current2) => authorization("deny", id3, current2)
|
|
3123
3250
|
},
|
|
3124
3251
|
getSession: () => client.getSession(),
|
|
3125
|
-
onAuthStateChange: (callback) => client.onAuthStateChange((
|
|
3252
|
+
onAuthStateChange: (callback) => client.onAuthStateChange((event, session) => {
|
|
3126
3253
|
let revision = session ? provenance.get(session.access_token) : void 0;
|
|
3127
|
-
revision !== void 0 && !guard.current(revision) || (callback(
|
|
3254
|
+
revision !== void 0 && !guard.current(revision) || (callback(event, session), session && provenance.delete(session.access_token));
|
|
3128
3255
|
}),
|
|
3129
3256
|
signInWithOtp: (input) => client.signInWithOtp(input),
|
|
3130
3257
|
verifyOtp: (input) => client.verifyOtp(input),
|
|
@@ -3143,188 +3270,160 @@ async function provider(configuration, guard) {
|
|
|
3143
3270
|
}
|
|
3144
3271
|
var auth = /* @__PURE__ */ createBrowserAuth({ provider, failure: (reason) => new BrowserAuthError(reason) });
|
|
3145
3272
|
|
|
3146
|
-
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 {
|
|
3147
3274
|
constructor(reason) {
|
|
3148
3275
|
super(reason);
|
|
3149
3276
|
this.reason = reason;
|
|
3150
3277
|
this.name = "AppRoutineError";
|
|
3151
3278
|
}
|
|
3152
3279
|
reason;
|
|
3153
|
-
}
|
|
3154
|
-
function fail3(reason) {
|
|
3280
|
+
}, fail3 = (reason) => {
|
|
3155
3281
|
throw new AppRoutineError(reason);
|
|
3156
|
-
}
|
|
3157
|
-
function object4(value) {
|
|
3158
|
-
return !!value && typeof value == "object" && !Array.isArray(value);
|
|
3159
|
-
}
|
|
3160
|
-
function keys4(value, expected) {
|
|
3161
|
-
return Object.keys(value).sort().join(",") === expected;
|
|
3162
|
-
}
|
|
3282
|
+
};
|
|
3163
3283
|
function current(context2) {
|
|
3164
3284
|
(!context2.isCurrent() || context2.signal.aborted) && fail3("authority_unavailable");
|
|
3165
3285
|
}
|
|
3166
|
-
|
|
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);
|
|
3167
3297
|
try {
|
|
3168
|
-
let value = await appResponse(response2, maximum, context2.signal);
|
|
3169
|
-
|
|
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;
|
|
3170
3304
|
} catch (error) {
|
|
3171
|
-
if (current(context2), error instanceof
|
|
3172
|
-
|
|
3305
|
+
if (current(context2), error instanceof AppRoutineError) throw error;
|
|
3306
|
+
fail3("execution_unavailable");
|
|
3173
3307
|
}
|
|
3174
3308
|
}
|
|
3175
|
-
function
|
|
3176
|
-
|
|
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;
|
|
3177
3312
|
}
|
|
3178
|
-
function
|
|
3179
|
-
return
|
|
3313
|
+
function only(value, allowed) {
|
|
3314
|
+
return !!value && typeof value == "object" && !Array.isArray(value) && Object.keys(value).every((key) => allowed.split(",").includes(key));
|
|
3180
3315
|
}
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
if (
|
|
3199
|
-
|
|
3200
|
-
if (
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
context2.signal.addEventListener("abort", abort, { once: !0 });
|
|
3212
|
-
}), current(context2);
|
|
3213
|
-
}
|
|
3214
|
-
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);
|
|
3215
3346
|
return Object.freeze({
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
let
|
|
3219
|
-
for (;
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
response2 = await context2.requestRoutine(run.key, `runs/${run.runId}/events?after=${cursor}`);
|
|
3224
|
-
} catch {
|
|
3225
|
-
current(context2), await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
3226
|
-
continue;
|
|
3227
|
-
}
|
|
3228
|
-
if (response2.status >= 500) {
|
|
3229
|
-
await response2.body?.cancel(), await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
3230
|
-
continue;
|
|
3231
|
-
}
|
|
3232
|
-
let value;
|
|
3233
|
-
try {
|
|
3234
|
-
value = await body(context2, response2, 80 * 1024);
|
|
3235
|
-
} catch (error) {
|
|
3236
|
-
if (!(error instanceof AppResponseReadError)) throw error;
|
|
3237
|
-
await pause(context2, delay), delay = Math.min(delay * 2, 2e3);
|
|
3238
|
-
continue;
|
|
3239
|
-
}
|
|
3240
|
-
(!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");
|
|
3241
|
-
let delivery = [];
|
|
3242
|
-
for (let raw of value.events) {
|
|
3243
|
-
let publicEvent = event(raw, run, steps), encoded = JSON.stringify(raw), sequence = raw.sequence;
|
|
3244
|
-
if (sequence <= cursor) {
|
|
3245
|
-
seen[sequence - 1] !== encoded && fail3("execution_unavailable");
|
|
3246
|
-
continue;
|
|
3247
|
-
}
|
|
3248
|
-
(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);
|
|
3249
|
-
}
|
|
3250
|
-
(value.after !== cursor || value.terminal !== terminal) && fail3("execution_unavailable");
|
|
3251
|
-
for (let item of delivery)
|
|
3252
|
-
current(context2), yield item;
|
|
3253
|
-
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));
|
|
3254
3354
|
}
|
|
3255
3355
|
},
|
|
3256
|
-
async
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
fail3("execution_unavailable");
|
|
3264
|
-
}
|
|
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);
|
|
3265
3363
|
}
|
|
3266
3364
|
});
|
|
3267
3365
|
}
|
|
3268
|
-
async function
|
|
3269
|
-
let
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
let runs = value2.runs.map((run) => descriptor(run, key));
|
|
3277
|
-
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));
|
|
3278
|
-
}
|
|
3279
|
-
let available = await body(context2, await context2.requestAvailability(key), 16 * 1024);
|
|
3280
|
-
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");
|
|
3281
|
-
let steps = [...available.steps], encoded;
|
|
3282
|
-
try {
|
|
3283
|
-
encoded = JSON.stringify(input), (encoded === void 0 || new TextEncoder().encode(encoded).byteLength > 16 * 1024) && fail3("invalid_input");
|
|
3284
|
-
} catch {
|
|
3285
|
-
fail3("invalid_input");
|
|
3286
|
-
}
|
|
3287
|
-
let value = await body(context2, await context2.requestRoutine(key, "runs", {
|
|
3288
|
-
method: "POST",
|
|
3289
|
-
body: `{"input":${encoded}}`
|
|
3290
|
-
}), 16 * 1024);
|
|
3291
|
-
return handle(context2, descriptor(value, key), steps);
|
|
3292
|
-
} catch (error) {
|
|
3293
|
-
if (context2 && current(context2), error instanceof AppRoutineError) throw error;
|
|
3294
|
-
return fail3(context2 ? "execution_unavailable" : "authority_unavailable");
|
|
3295
|
-
}
|
|
3296
|
-
}
|
|
3297
|
-
|
|
3298
|
-
var authorityUnavailable = () => ({ available: !1, reason: "authority_unavailable" }), MAX_RESPONSE_BYTES = 16 * 1024;
|
|
3299
|
-
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
|
+
});
|
|
3300
3374
|
try {
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
if (context2.kind !== "local") return { available: !1, reason: "execution_unavailable" };
|
|
3304
|
-
let response2 = await context2.requestAvailability(key);
|
|
3305
|
-
if (!response2.ok || response2.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() !== "application/json")
|
|
3306
|
-
return authorityUnavailable();
|
|
3307
|
-
let value = await appResponse(response2, MAX_RESPONSE_BYTES, context2.signal);
|
|
3308
|
-
if (!context2.isCurrent() || !value || typeof value != "object" || Array.isArray(value)) return authorityUnavailable();
|
|
3309
|
-
let result2 = value;
|
|
3310
|
-
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;
|
|
3311
3377
|
} catch {
|
|
3312
|
-
return
|
|
3378
|
+
return unavailable3();
|
|
3313
3379
|
}
|
|
3314
3380
|
}
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
}
|
|
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
|
+
});
|
|
3328
3427
|
|
|
3329
3428
|
var LIMIT2 = 16 * 1024, context;
|
|
3330
3429
|
var appRun = {
|
|
@@ -3354,10 +3453,10 @@ function routineDataEnvelope(command) {
|
|
|
3354
3453
|
}
|
|
3355
3454
|
|
|
3356
3455
|
function routinePublicationClient2(options = {}) {
|
|
3357
|
-
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;
|
|
3358
3457
|
if (!workspace || !/^[a-z0-9][a-z0-9-]*$/.test(workspace) || capability !== void 0 && !/^[0-9a-f]{64}$/.test(capability))
|
|
3359
3458
|
throw new Error("A workspace and valid optional routine capability are required");
|
|
3360
|
-
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) => {
|
|
3361
3460
|
if (path === "/api/data") return fetch(`https://${workspace}.oddington.ai/api/data`, { ...init2, redirect: "error" });
|
|
3362
3461
|
let origin = `https://${workspace}.oddington.ai`, target = new URL(path, `${origin}/`);
|
|
3363
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")
|
|
@@ -3366,16 +3465,16 @@ function routinePublicationClient2(options = {}) {
|
|
|
3366
3465
|
} : async () => {
|
|
3367
3466
|
throw new Error("Member publication requires a host-supplied request");
|
|
3368
3467
|
});
|
|
3369
|
-
async function send3(operation2,
|
|
3370
|
-
if (
|
|
3371
|
-
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}`, {
|
|
3372
3471
|
method: "POST",
|
|
3373
3472
|
headers: {
|
|
3374
3473
|
"content-type": "application/json",
|
|
3375
3474
|
...headers,
|
|
3376
3475
|
...writing || reading ? { "x-oddington-workspace": workspace, "x-oddington-captured-records": "1" } : {}
|
|
3377
3476
|
},
|
|
3378
|
-
body: JSON.stringify(writing ? routineDataEnvelope(validateRoutineRecordWrite(
|
|
3477
|
+
body: JSON.stringify(writing ? routineDataEnvelope(validateRoutineRecordWrite(body)) : reading ? { operation: "records.select", request: validateRecordRead(body) } : body)
|
|
3379
3478
|
}), result2 = await response2.json();
|
|
3380
3479
|
if (!response2.ok && operation2 === "records/update")
|
|
3381
3480
|
throw new RoutineRecordWriteError(result2.error ?? "Could not confirm routine preparation", result2.effect ?? "uncertain");
|
|
@@ -3383,11 +3482,11 @@ function routinePublicationClient2(options = {}) {
|
|
|
3383
3482
|
return result2;
|
|
3384
3483
|
}
|
|
3385
3484
|
let transport = {
|
|
3386
|
-
async publish(
|
|
3387
|
-
return await send3("publish",
|
|
3485
|
+
async publish(body) {
|
|
3486
|
+
return await send3("publish", body);
|
|
3388
3487
|
},
|
|
3389
|
-
async resolve(
|
|
3390
|
-
await send3("resolve",
|
|
3488
|
+
async resolve(body) {
|
|
3489
|
+
await send3("resolve", body);
|
|
3391
3490
|
}
|
|
3392
3491
|
};
|
|
3393
3492
|
async function readRecords(input) {
|
|
@@ -3414,12 +3513,12 @@ function routinePublicationClient2(options = {}) {
|
|
|
3414
3513
|
files: {
|
|
3415
3514
|
async add(value) {
|
|
3416
3515
|
let input = validateFileAddOptions(value);
|
|
3417
|
-
if (
|
|
3516
|
+
if (local2) return validateInboxFile(await local2("files/add", input));
|
|
3418
3517
|
throw workingRoot ? new Error("Inbox file reads require a Node working root") : new Error("Inbox file reads require a working root");
|
|
3419
3518
|
}
|
|
3420
3519
|
},
|
|
3421
|
-
async check(
|
|
3422
|
-
await send3("check", { requestKey:
|
|
3520
|
+
async check(body) {
|
|
3521
|
+
await send3("check", { requestKey: body.requestKey, item: validatePublication(body.item) });
|
|
3423
3522
|
}
|
|
3424
3523
|
};
|
|
3425
3524
|
}
|