@oddington/sdk 0.1.9 → 0.1.10
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 +29 -1
- package/dist/browser.js +92 -59
- package/dist/index.js +115 -69
- package/dist/types/packages/sdk/src/public.d.ts +1 -1
- package/dist/types/shared/data-contract.d.ts +26 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -299,9 +299,37 @@ Each graph selection sends one request and returns only selected canonical
|
|
|
299
299
|
values, expanded forward links and exact opaque public versions. Cursors
|
|
300
300
|
continue the exact retained artifact and collection selection, even after
|
|
301
301
|
replacement; repeat its options and links while omitting unrelated collections.
|
|
302
|
-
There is no automatic retry or separate version fetch.
|
|
302
|
+
There is no automatic retry or separate version fetch.
|
|
303
303
|
Collection schemas omit Markdown storage hints.
|
|
304
304
|
|
|
305
|
+
Read published History through the same inert repository handle:
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
const versions = await general.history.list({ limit: 50 });
|
|
309
|
+
const older = versions.length
|
|
310
|
+
? await general.history.list({ before: versions.at(-1)!.version }) : [];
|
|
311
|
+
const close = await general.history.at('2026-10-09T16:30:00Z');
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
List returns an entry array in descending published sequence, with an exclusive
|
|
315
|
+
visible `before` and a default limit of 50 (integer 1–100). Cutoff accepts a real
|
|
316
|
+
RFC 3339 instant with an explicit offset and returns the greatest visible sequence
|
|
317
|
+
published at or before it, or null. Entries contain exactly `version`, `publishedAt`,
|
|
318
|
+
`author`, `authoredAt`, `committer`, `committedAt`, `message`, `created`, `updated`,
|
|
319
|
+
and `deleted`. Git identities and complete messages are repository facts; changed
|
|
320
|
+
refs are lexical. Versions are opaque published identities, never Git expressions.
|
|
321
|
+
Each operation captures input before resolving authority and makes one request.
|
|
322
|
+
Incomplete selected metadata fails the whole result retryably with `unavailable`;
|
|
323
|
+
current Records remain independent. Hosted routines retain their captured ceiling
|
|
324
|
+
until their own authoritative publication advances it. History is served through
|
|
325
|
+
the member/run Data transport. Local apps and local routines use the same calls;
|
|
326
|
+
their OS parent may acquire one bounded page or cutoff result, retain it against
|
|
327
|
+
the exact repository target and published ceiling, and serve an identical warm
|
|
328
|
+
request without another hosted call. Authority loss, expiry, target replacement
|
|
329
|
+
or published-version replacement invalidates that retained result. Prepared local
|
|
330
|
+
changes do not appear in published History.
|
|
331
|
+
Historical Record selection and `history.changes` are not exposed by this slice.
|
|
332
|
+
|
|
305
333
|
Use bounded plain-text lookup to find full Records and guards:
|
|
306
334
|
|
|
307
335
|
```ts
|
package/dist/browser.js
CHANGED
|
@@ -717,31 +717,65 @@ var DataOperationError = class extends Error {
|
|
|
717
717
|
|
|
718
718
|
var invalid = () => {
|
|
719
719
|
throw new DataOperationError("invalid_query");
|
|
720
|
-
},
|
|
720
|
+
}, historyText = (value) => typeof value == "string" && !/[\u0000\uD800-\uDFFF]/u.test(value);
|
|
721
|
+
function historyVersion(value) {
|
|
722
|
+
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);
|
|
723
|
+
}
|
|
724
|
+
function historyProperties(value) {
|
|
725
|
+
if (!value || typeof value != "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) return invalid();
|
|
726
|
+
let descriptors = Object.getOwnPropertyDescriptors(value);
|
|
727
|
+
return Reflect.ownKeys(value).some((key) => typeof key != "string" || !descriptors[key]?.enumerable || !Object.hasOwn(descriptors[key], "value")) ? invalid() : descriptors;
|
|
728
|
+
}
|
|
729
|
+
function captureHistoryListOptions(value) {
|
|
730
|
+
if (value === void 0) return {};
|
|
731
|
+
let descriptors = historyProperties(value), result2 = {};
|
|
732
|
+
if (Object.keys(descriptors).some((key) => !["limit", "before"].includes(key))) return invalid();
|
|
733
|
+
if (Object.hasOwn(descriptors, "limit")) {
|
|
734
|
+
let limit = descriptors.limit.value;
|
|
735
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100) return invalid();
|
|
736
|
+
result2.limit = limit;
|
|
737
|
+
}
|
|
738
|
+
if (Object.hasOwn(descriptors, "before")) {
|
|
739
|
+
let before = descriptors.before.value;
|
|
740
|
+
if (!historyVersion(before)) return invalid();
|
|
741
|
+
result2.before = before;
|
|
742
|
+
}
|
|
743
|
+
return result2;
|
|
744
|
+
}
|
|
745
|
+
function captureHistoryInstant(value) {
|
|
746
|
+
if (!historyText(value) || value.length > 1024) return invalid();
|
|
747
|
+
let match = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.\d+)?([Zz]|([+-])(\d{2}):(\d{2}))$/.exec(value);
|
|
748
|
+
if (!match) return invalid();
|
|
749
|
+
let [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number), days = new Date(Date.UTC(year, month, 0));
|
|
750
|
+
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 ? invalid() : value;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
var invalid2 = () => {
|
|
754
|
+
throw new DataOperationError("invalid_query");
|
|
755
|
+
};
|
|
721
756
|
function captureRecordsSearchInput(query, options) {
|
|
722
|
-
if (!
|
|
757
|
+
if (!historyText(query)) return invalid2();
|
|
723
758
|
let length = [...query.trim()].length;
|
|
724
|
-
if (length < 1 || length > 256) return
|
|
759
|
+
if (length < 1 || length > 256) return invalid2();
|
|
725
760
|
if (options === void 0) return { query };
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
if (Reflect.ownKeys(options).some((key) => typeof key != "string" || !["collections", "limit"].includes(key) || !descriptors[key]?.enumerable || !Object.hasOwn(descriptors[key], "value"))) return invalid();
|
|
761
|
+
let descriptors = historyProperties(options);
|
|
762
|
+
if (Object.keys(descriptors).some((key) => !["collections", "limit"].includes(key))) return invalid2();
|
|
729
763
|
let captured = {};
|
|
730
764
|
if (Object.hasOwn(descriptors, "collections")) {
|
|
731
765
|
let supplied = descriptors.collections.value;
|
|
732
|
-
if (!Array.isArray(supplied) || supplied.length < 1 || supplied.length > 16 || Reflect.ownKeys(supplied).length !== supplied.length + 1) return
|
|
766
|
+
if (!Array.isArray(supplied) || supplied.length < 1 || supplied.length > 16 || Reflect.ownKeys(supplied).length !== supplied.length + 1) return invalid2();
|
|
733
767
|
let collections = [];
|
|
734
768
|
for (let index = 0; index < supplied.length; index++) {
|
|
735
769
|
let descriptor2 = Object.getOwnPropertyDescriptor(supplied, String(index));
|
|
736
|
-
if (!descriptor2?.enumerable || !Object.hasOwn(descriptor2, "value") || !
|
|
770
|
+
if (!descriptor2?.enumerable || !Object.hasOwn(descriptor2, "value") || !historyText(descriptor2.value)) return invalid2();
|
|
737
771
|
collections.push(descriptor2.value);
|
|
738
772
|
}
|
|
739
|
-
if (new Set(collections).size !== collections.length) return
|
|
773
|
+
if (new Set(collections).size !== collections.length) return invalid2();
|
|
740
774
|
captured.collections = collections;
|
|
741
775
|
}
|
|
742
776
|
if (Object.hasOwn(descriptors, "limit")) {
|
|
743
777
|
let supplied = descriptors.limit.value;
|
|
744
|
-
if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100) return
|
|
778
|
+
if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100) return invalid2();
|
|
745
779
|
captured.limit = supplied;
|
|
746
780
|
}
|
|
747
781
|
return { query, options: captured };
|
|
@@ -842,42 +876,42 @@ var FileOperationError = class extends Error {
|
|
|
842
876
|
retryable;
|
|
843
877
|
}, 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;
|
|
844
878
|
function parseFileDescriptor(value) {
|
|
845
|
-
let
|
|
879
|
+
let invalid4 = () => {
|
|
846
880
|
throw new FileOperationError("unavailable", 503, !0);
|
|
847
881
|
};
|
|
848
|
-
if (!value || typeof value != "object" || Array.isArray(value)) return
|
|
882
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return invalid4();
|
|
849
883
|
let f = value;
|
|
850
|
-
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
|
|
884
|
+
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 invalid4();
|
|
851
885
|
let d = f.details;
|
|
852
886
|
if (d.kind === "other") {
|
|
853
|
-
if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream") return
|
|
887
|
+
if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream") return invalid4();
|
|
854
888
|
} else if (d.kind === "csv") {
|
|
855
|
-
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
|
|
856
|
-
} else return
|
|
889
|
+
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 invalid4();
|
|
890
|
+
} else return invalid4();
|
|
857
891
|
for (let [name, descriptor2] of Object.entries(f.enrichments)) {
|
|
858
|
-
if (!safeEnrichmentName(name)) return
|
|
892
|
+
if (!safeEnrichmentName(name)) return invalid4();
|
|
859
893
|
parseEnrichmentDescriptor(descriptor2);
|
|
860
894
|
}
|
|
861
|
-
return new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024 ?
|
|
895
|
+
return new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024 ? invalid4() : f;
|
|
862
896
|
}
|
|
863
897
|
function parseEnrichmentDescriptor(value) {
|
|
864
|
-
let
|
|
898
|
+
let invalid4 = () => {
|
|
865
899
|
throw new FileOperationError("unavailable", 503, !0);
|
|
866
900
|
};
|
|
867
|
-
if (!value || typeof value != "object" || Array.isArray(value)) return
|
|
901
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return invalid4();
|
|
868
902
|
let d = value;
|
|
869
|
-
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) ?
|
|
903
|
+
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) ? invalid4() : d;
|
|
870
904
|
}
|
|
871
905
|
function safeEnrichmentName(value) {
|
|
872
906
|
return safeFileName(value) && !/^original(?:\.|$)/i.test(value);
|
|
873
907
|
}
|
|
874
908
|
function parseFileEnrichMetadata(value, maxBytes) {
|
|
875
|
-
let
|
|
909
|
+
let invalid4 = () => {
|
|
876
910
|
throw new FileOperationError("invalid_input", 400);
|
|
877
911
|
};
|
|
878
|
-
if (!value || typeof value != "object" || Array.isArray(value)) return
|
|
912
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return invalid4();
|
|
879
913
|
let d = value;
|
|
880
|
-
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
|
|
914
|
+
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 invalid4();
|
|
881
915
|
if (d.size > maxBytes) throw new FileOperationError("request_too_large", 413);
|
|
882
916
|
return d;
|
|
883
917
|
}
|
|
@@ -888,23 +922,23 @@ function safeFilePath(value) {
|
|
|
888
922
|
return typeof value == "string" && value.length <= 1024 && value.split("/").every(safeFileName);
|
|
889
923
|
}
|
|
890
924
|
function parseFileCreateMetadata(value, maxBytes) {
|
|
891
|
-
let
|
|
925
|
+
let invalid4 = () => {
|
|
892
926
|
throw new FileOperationError("invalid_input", 400);
|
|
893
927
|
};
|
|
894
|
-
if (!value || typeof value != "object" || Array.isArray(value)) return
|
|
928
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return invalid4();
|
|
895
929
|
let input = value;
|
|
896
|
-
if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "size", "requestKey"].includes(key))) return
|
|
930
|
+
if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "size", "requestKey"].includes(key))) return invalid4();
|
|
897
931
|
let path = input.path === void 0 ? "Files" : input.path;
|
|
898
|
-
if (!safeFileName(input.name) || !safeFilePath(path) || input.storage !== void 0 && input.storage !== "remote" && input.storage !== "local" || !Number.isSafeInteger(input.size) || input.size < 0) return
|
|
932
|
+
if (!safeFileName(input.name) || !safeFilePath(path) || input.storage !== void 0 && input.storage !== "remote" && input.storage !== "local" || !Number.isSafeInteger(input.size) || input.size < 0) return invalid4();
|
|
899
933
|
if (input.size > maxBytes) throw new FileOperationError("request_too_large", 413);
|
|
900
|
-
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
|
|
934
|
+
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 invalid4();
|
|
901
935
|
let csv;
|
|
902
936
|
if (input.csv !== void 0) {
|
|
903
|
-
if (!input.csv || typeof input.csv != "object" || Array.isArray(input.csv)) return
|
|
937
|
+
if (!input.csv || typeof input.csv != "object" || Array.isArray(input.csv)) return invalid4();
|
|
904
938
|
let hints = input.csv;
|
|
905
|
-
if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key))) return
|
|
939
|
+
if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key))) return invalid4();
|
|
906
940
|
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;
|
|
907
|
-
if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", " "].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5) return
|
|
941
|
+
if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", " "].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5) return invalid4();
|
|
908
942
|
csv = { encoding, delimiter, headerRow };
|
|
909
943
|
}
|
|
910
944
|
return {
|
|
@@ -992,13 +1026,14 @@ var data = {
|
|
|
992
1026
|
async function send2(input) {
|
|
993
1027
|
let context2 = await resolveDataContext();
|
|
994
1028
|
try {
|
|
995
|
-
|
|
1029
|
+
let envelope = { repository, ...input };
|
|
1030
|
+
if (checkDataRequestSize(envelope), "local" in context2) return await context2.local("data/query", envelope);
|
|
996
1031
|
let response = await fetch(context2.url, {
|
|
997
1032
|
method: "POST",
|
|
998
1033
|
redirect: "error",
|
|
999
1034
|
cache: "no-store",
|
|
1000
1035
|
headers: { "content-type": "application/json", ...context2.headers },
|
|
1001
|
-
body: JSON.stringify(
|
|
1036
|
+
body: JSON.stringify(envelope)
|
|
1002
1037
|
}), result2 = await response.json();
|
|
1003
1038
|
if (!response.ok)
|
|
1004
1039
|
throw dataTransportError(response.status, result2);
|
|
@@ -1014,13 +1049,11 @@ var data = {
|
|
|
1014
1049
|
},
|
|
1015
1050
|
records: {
|
|
1016
1051
|
select: (query) => send2({ operation: "records.select", query }),
|
|
1017
|
-
search: (query, options) => {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1052
|
+
search: async (query, options) => send2({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
|
|
1053
|
+
},
|
|
1054
|
+
history: {
|
|
1055
|
+
list: async (options) => send2({ operation: "history.list", options: captureHistoryListOptions(options) }),
|
|
1056
|
+
at: async (instant) => send2({ operation: "history.at", instant: captureHistoryInstant(instant) })
|
|
1024
1057
|
},
|
|
1025
1058
|
changes() {
|
|
1026
1059
|
let updates = [], creates = [], deletes = [], publicationId, pending, confirmed, snapshot = () => {
|
|
@@ -1104,7 +1137,7 @@ var data = {
|
|
|
1104
1137
|
}
|
|
1105
1138
|
};
|
|
1106
1139
|
|
|
1107
|
-
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,
|
|
1140
|
+
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, invalid3 = () => new FileOperationError("invalid_input", 400), unavailable = () => new FileOperationError("unavailable", 503, !0), failures = {
|
|
1108
1141
|
400: ["invalid_input", "unsupported_context"],
|
|
1109
1142
|
401: ["unauthenticated"],
|
|
1110
1143
|
403: ["access_denied"],
|
|
@@ -1121,7 +1154,7 @@ async function boundedBytes(stream, limit) {
|
|
|
1121
1154
|
for (; ; ) {
|
|
1122
1155
|
let { done, value } = await reader.read();
|
|
1123
1156
|
if (done) break;
|
|
1124
|
-
if (!(value instanceof Uint8Array)) throw
|
|
1157
|
+
if (!(value instanceof Uint8Array)) throw invalid3();
|
|
1125
1158
|
if (size += value.byteLength, size > limit) throw new FileOperationError("request_too_large", 413);
|
|
1126
1159
|
bytes.set(value, size - value.byteLength);
|
|
1127
1160
|
}
|
|
@@ -1249,7 +1282,7 @@ async function send(suffix, init2, descriptor2, initial, parent) {
|
|
|
1249
1282
|
throw unavailable();
|
|
1250
1283
|
}
|
|
1251
1284
|
function idPath(id2) {
|
|
1252
|
-
if (typeof id2 != "string" || !FILE_ID_PATTERN.test(id2)) throw
|
|
1285
|
+
if (typeof id2 != "string" || !FILE_ID_PATTERN.test(id2)) throw invalid3();
|
|
1253
1286
|
return `/${id2}`;
|
|
1254
1287
|
}
|
|
1255
1288
|
async function multipartCreate(input, metadata, exchange, release = () => {
|
|
@@ -1292,18 +1325,18 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1292
1325
|
if (!chunk || offset === chunk.byteLength) {
|
|
1293
1326
|
chunk = void 0, offset = 0;
|
|
1294
1327
|
let value2 = await next();
|
|
1295
|
-
if (value2.done || !(value2.value instanceof Uint8Array) || (chunk = value2.value, chunk.byteLength > metadata.size - sent - filled)) throw
|
|
1328
|
+
if (value2.done || !(value2.value instanceof Uint8Array) || (chunk = value2.value, chunk.byteLength > metadata.size - sent - filled)) throw invalid3();
|
|
1296
1329
|
}
|
|
1297
1330
|
let take = Math.min(length - filled, chunk.byteLength - offset);
|
|
1298
1331
|
part.set(chunk.subarray(offset, offset + take), filled), filled += take, offset += take, offset === chunk.byteLength && (chunk = void 0, offset = 0);
|
|
1299
1332
|
}
|
|
1300
1333
|
}
|
|
1301
|
-
if (part.byteLength !== length) throw
|
|
1334
|
+
if (part.byteLength !== length) throw invalid3();
|
|
1302
1335
|
if (reader && sent + length === metadata.size)
|
|
1303
1336
|
for (lastProgress = Date.now(); ; ) {
|
|
1304
1337
|
let value2 = await next();
|
|
1305
1338
|
if (value2.done) break;
|
|
1306
|
-
if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw
|
|
1339
|
+
if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw invalid3();
|
|
1307
1340
|
}
|
|
1308
1341
|
let value = await request((signal) => exchange(`${route}/part`, {
|
|
1309
1342
|
method: "POST",
|
|
@@ -1317,7 +1350,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
1317
1350
|
}
|
|
1318
1351
|
if (upload) for (let name of Object.keys(upload.file.enrichments)) {
|
|
1319
1352
|
let bytes = await request(() => upload.enrichment(name));
|
|
1320
|
-
if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw
|
|
1353
|
+
if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw invalid3();
|
|
1321
1354
|
await request((signal) => exchange(`${route}/enrichments/${encodeURIComponent(name)}`, {
|
|
1322
1355
|
method: "POST",
|
|
1323
1356
|
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket },
|
|
@@ -1361,7 +1394,7 @@ async function operation(work, initial, parent) {
|
|
|
1361
1394
|
function contentPath(id2, name) {
|
|
1362
1395
|
let path = idPath(id2);
|
|
1363
1396
|
if (name === void 0) return `${path}/content`;
|
|
1364
|
-
if (!safeEnrichmentName(name)) throw
|
|
1397
|
+
if (!safeEnrichmentName(name)) throw invalid3();
|
|
1365
1398
|
return `${path}/enrichments/${encodeURIComponent(name)}/content`;
|
|
1366
1399
|
}
|
|
1367
1400
|
async function read(id2, names) {
|
|
@@ -1370,12 +1403,12 @@ async function read(id2, names) {
|
|
|
1370
1403
|
let path = contentPath(id2, names);
|
|
1371
1404
|
return operation((context3, signal) => send(path, { method: "GET" }, !1, context3, signal), context2);
|
|
1372
1405
|
}
|
|
1373
|
-
if (!Array.isArray(names)) throw
|
|
1406
|
+
if (!Array.isArray(names)) throw invalid3();
|
|
1374
1407
|
let distinct = [], seen = /* @__PURE__ */ new Set();
|
|
1375
1408
|
for (let name of names) {
|
|
1376
|
-
if (typeof name != "string" || !safeEnrichmentName(name)) throw
|
|
1409
|
+
if (typeof name != "string" || !safeEnrichmentName(name)) throw invalid3();
|
|
1377
1410
|
if (!seen.has(name)) {
|
|
1378
|
-
if (seen.size === 16) throw
|
|
1411
|
+
if (seen.size === 16) throw invalid3();
|
|
1379
1412
|
seen.add(name), distinct.push(name);
|
|
1380
1413
|
}
|
|
1381
1414
|
}
|
|
@@ -1407,11 +1440,11 @@ var files = {
|
|
|
1407
1440
|
async create(input, options) {
|
|
1408
1441
|
let context2 = await resolveFilesContext();
|
|
1409
1442
|
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")))
|
|
1410
|
-
throw
|
|
1443
|
+
throw invalid3();
|
|
1411
1444
|
let blob = input.file instanceof Blob, array2 = input.file instanceof Uint8Array, stream = input.file instanceof ReadableStream;
|
|
1412
|
-
if (!blob && !array2 && !stream) throw
|
|
1445
|
+
if (!blob && !array2 && !stream) throw invalid3();
|
|
1413
1446
|
let intrinsic = blob ? input.file.size : array2 ? input.file.byteLength : void 0;
|
|
1414
|
-
if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw
|
|
1447
|
+
if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw invalid3();
|
|
1415
1448
|
let name = input.name;
|
|
1416
1449
|
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));
|
|
1417
1450
|
let metadata = parseFileCreateMetadata({
|
|
@@ -1424,7 +1457,7 @@ var files = {
|
|
|
1424
1457
|
}, FILE_ORIGINAL_MAX_BYTES);
|
|
1425
1458
|
if (!context2.local && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
|
|
1426
1459
|
let header = encodeURIComponent(JSON.stringify(metadata));
|
|
1427
|
-
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw
|
|
1460
|
+
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid3();
|
|
1428
1461
|
if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
|
|
1429
1462
|
if (active++, context2.localFiles && metadata.size > MAX_BYTES) {
|
|
1430
1463
|
let controller = new AbortController(), file = input.file, offset = 0, body2 = file instanceof ReadableStream ? file : file instanceof Blob ? file.stream() : new ReadableStream({
|
|
@@ -1452,7 +1485,7 @@ var files = {
|
|
|
1452
1485
|
blob ? input.file.stream() : input.file,
|
|
1453
1486
|
metadata.size
|
|
1454
1487
|
);
|
|
1455
|
-
if (bytes.byteLength !== metadata.size) throw
|
|
1488
|
+
if (bytes.byteLength !== metadata.size) throw invalid3();
|
|
1456
1489
|
if (signal.aborted) throw unavailable();
|
|
1457
1490
|
return await send("", {
|
|
1458
1491
|
method: "POST",
|
|
@@ -1468,7 +1501,7 @@ var files = {
|
|
|
1468
1501
|
},
|
|
1469
1502
|
async enrich(input) {
|
|
1470
1503
|
let context2 = await resolveFilesContext();
|
|
1471
|
-
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
|
|
1504
|
+
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 invalid3();
|
|
1472
1505
|
let path = `${idPath(input.file)}/enrichments`;
|
|
1473
1506
|
if (typeof input.content == "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
|
|
1474
1507
|
throw new FileOperationError("request_too_large", 413);
|
|
@@ -1485,7 +1518,7 @@ var files = {
|
|
|
1485
1518
|
...input.mediaType === void 0 ? {} : { mediaType: input.mediaType },
|
|
1486
1519
|
...input.replace === void 0 ? {} : { replace: input.replace }
|
|
1487
1520
|
}, MAX_BYTES), header = encodeURIComponent(JSON.stringify(metadata));
|
|
1488
|
-
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw
|
|
1521
|
+
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid3();
|
|
1489
1522
|
let result2 = await send(path, { method: "POST", headers: {
|
|
1490
1523
|
"content-type": "application/octet-stream",
|
|
1491
1524
|
"x-oddington-enrichment": header
|
package/dist/index.js
CHANGED
|
@@ -21709,44 +21709,91 @@ class DataOperationError extends Error {
|
|
|
21709
21709
|
}
|
|
21710
21710
|
}
|
|
21711
21711
|
|
|
21712
|
-
// ../../shared/data-
|
|
21712
|
+
// ../../shared/data-history-input.ts
|
|
21713
21713
|
var invalid = () => {
|
|
21714
21714
|
throw new DataOperationError("invalid_query");
|
|
21715
21715
|
};
|
|
21716
|
-
var
|
|
21717
|
-
function
|
|
21718
|
-
|
|
21716
|
+
var historyText = (value) => typeof value === "string" && !/[\u0000\uD800-\uDFFF]/u.test(value);
|
|
21717
|
+
function historyVersion(value) {
|
|
21718
|
+
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);
|
|
21719
|
+
}
|
|
21720
|
+
function historyProperties(value) {
|
|
21721
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
|
|
21722
|
+
return invalid();
|
|
21723
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
21724
|
+
if (Reflect.ownKeys(value).some((key) => typeof key !== "string" || !descriptors[key]?.enumerable || !Object.hasOwn(descriptors[key], "value")))
|
|
21725
|
+
return invalid();
|
|
21726
|
+
return descriptors;
|
|
21727
|
+
}
|
|
21728
|
+
function captureHistoryListOptions(value) {
|
|
21729
|
+
if (value === undefined)
|
|
21730
|
+
return {};
|
|
21731
|
+
const descriptors = historyProperties(value), result = {};
|
|
21732
|
+
if (Object.keys(descriptors).some((key) => !["limit", "before"].includes(key)))
|
|
21733
|
+
return invalid();
|
|
21734
|
+
if (Object.hasOwn(descriptors, "limit")) {
|
|
21735
|
+
const limit = descriptors.limit.value;
|
|
21736
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
21737
|
+
return invalid();
|
|
21738
|
+
result.limit = limit;
|
|
21739
|
+
}
|
|
21740
|
+
if (Object.hasOwn(descriptors, "before")) {
|
|
21741
|
+
const before = descriptors.before.value;
|
|
21742
|
+
if (!historyVersion(before))
|
|
21743
|
+
return invalid();
|
|
21744
|
+
result.before = before;
|
|
21745
|
+
}
|
|
21746
|
+
return result;
|
|
21747
|
+
}
|
|
21748
|
+
function captureHistoryInstant(value) {
|
|
21749
|
+
if (!historyText(value) || value.length > 1024)
|
|
21719
21750
|
return invalid();
|
|
21751
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.\d+)?([Zz]|([+-])(\d{2}):(\d{2}))$/.exec(value);
|
|
21752
|
+
if (!match)
|
|
21753
|
+
return invalid();
|
|
21754
|
+
const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number);
|
|
21755
|
+
const days = new Date(Date.UTC(year, month, 0));
|
|
21756
|
+
days.setUTCFullYear(year);
|
|
21757
|
+
if (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)
|
|
21758
|
+
return invalid();
|
|
21759
|
+
return value;
|
|
21760
|
+
}
|
|
21761
|
+
|
|
21762
|
+
// ../../shared/data-search-input.ts
|
|
21763
|
+
var invalid2 = () => {
|
|
21764
|
+
throw new DataOperationError("invalid_query");
|
|
21765
|
+
};
|
|
21766
|
+
function captureRecordsSearchInput(query, options) {
|
|
21767
|
+
if (!historyText(query))
|
|
21768
|
+
return invalid2();
|
|
21720
21769
|
const length = [...query.trim()].length;
|
|
21721
21770
|
if (length < 1 || length > 256)
|
|
21722
|
-
return
|
|
21771
|
+
return invalid2();
|
|
21723
21772
|
if (options === undefined)
|
|
21724
21773
|
return { query };
|
|
21725
|
-
|
|
21726
|
-
|
|
21727
|
-
|
|
21728
|
-
if (Reflect.ownKeys(options).some((key) => typeof key !== "string" || !["collections", "limit"].includes(key) || !descriptors[key]?.enumerable || !Object.hasOwn(descriptors[key], "value")))
|
|
21729
|
-
return invalid();
|
|
21774
|
+
const descriptors = historyProperties(options);
|
|
21775
|
+
if (Object.keys(descriptors).some((key) => !["collections", "limit"].includes(key)))
|
|
21776
|
+
return invalid2();
|
|
21730
21777
|
const captured = {};
|
|
21731
21778
|
if (Object.hasOwn(descriptors, "collections")) {
|
|
21732
21779
|
const supplied = descriptors.collections.value;
|
|
21733
21780
|
if (!Array.isArray(supplied) || supplied.length < 1 || supplied.length > 16 || Reflect.ownKeys(supplied).length !== supplied.length + 1)
|
|
21734
|
-
return
|
|
21781
|
+
return invalid2();
|
|
21735
21782
|
const collections = [];
|
|
21736
21783
|
for (let index = 0;index < supplied.length; index++) {
|
|
21737
21784
|
const descriptor = Object.getOwnPropertyDescriptor(supplied, String(index));
|
|
21738
|
-
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value") || !
|
|
21739
|
-
return
|
|
21785
|
+
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value") || !historyText(descriptor.value))
|
|
21786
|
+
return invalid2();
|
|
21740
21787
|
collections.push(descriptor.value);
|
|
21741
21788
|
}
|
|
21742
21789
|
if (new Set(collections).size !== collections.length)
|
|
21743
|
-
return
|
|
21790
|
+
return invalid2();
|
|
21744
21791
|
captured.collections = collections;
|
|
21745
21792
|
}
|
|
21746
21793
|
if (Object.hasOwn(descriptors, "limit")) {
|
|
21747
21794
|
const supplied = descriptors.limit.value;
|
|
21748
21795
|
if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100)
|
|
21749
|
-
return
|
|
21796
|
+
return invalid2();
|
|
21750
21797
|
captured.limit = supplied;
|
|
21751
21798
|
}
|
|
21752
21799
|
return { query, options: captured };
|
|
@@ -21886,55 +21933,55 @@ class FileOperationError extends Error {
|
|
|
21886
21933
|
var 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}$/;
|
|
21887
21934
|
var FILE_ORIGINAL_MAX_BYTES = 5 * 1024 ** 3;
|
|
21888
21935
|
function parseFileDescriptor(value) {
|
|
21889
|
-
const
|
|
21936
|
+
const invalid3 = () => {
|
|
21890
21937
|
throw new FileOperationError("unavailable", 503, true);
|
|
21891
21938
|
};
|
|
21892
21939
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
21893
|
-
return
|
|
21940
|
+
return invalid3();
|
|
21894
21941
|
const f = value;
|
|
21895
21942
|
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))
|
|
21896
|
-
return
|
|
21943
|
+
return invalid3();
|
|
21897
21944
|
const d = f.details;
|
|
21898
21945
|
if (d.kind === "other") {
|
|
21899
21946
|
if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream")
|
|
21900
|
-
return
|
|
21947
|
+
return invalid3();
|
|
21901
21948
|
} else if (d.kind === "csv") {
|
|
21902
21949
|
if (Object.keys(d).sort().join(",") !== "dataRows,delimiter,encoding,headerRow,kind" || f.mediaType !== "text/csv" || !["utf-8", "windows-1252"].includes(d.encoding) || ![",", ";", "\t"].includes(d.delimiter) || !Number.isSafeInteger(d.headerRow) || d.headerRow < 1 || !Number.isSafeInteger(d.dataRows) || d.dataRows < 0)
|
|
21903
|
-
return
|
|
21950
|
+
return invalid3();
|
|
21904
21951
|
} else
|
|
21905
|
-
return
|
|
21952
|
+
return invalid3();
|
|
21906
21953
|
for (const [name, descriptor] of Object.entries(f.enrichments)) {
|
|
21907
21954
|
if (!safeEnrichmentName(name))
|
|
21908
|
-
return
|
|
21955
|
+
return invalid3();
|
|
21909
21956
|
parseEnrichmentDescriptor(descriptor);
|
|
21910
21957
|
}
|
|
21911
21958
|
if (new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024)
|
|
21912
|
-
return
|
|
21959
|
+
return invalid3();
|
|
21913
21960
|
return f;
|
|
21914
21961
|
}
|
|
21915
21962
|
function parseEnrichmentDescriptor(value) {
|
|
21916
|
-
const
|
|
21963
|
+
const invalid3 = () => {
|
|
21917
21964
|
throw new FileOperationError("unavailable", 503, true);
|
|
21918
21965
|
};
|
|
21919
21966
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
21920
|
-
return
|
|
21967
|
+
return invalid3();
|
|
21921
21968
|
const d = value;
|
|
21922
21969
|
if (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))
|
|
21923
|
-
return
|
|
21970
|
+
return invalid3();
|
|
21924
21971
|
return d;
|
|
21925
21972
|
}
|
|
21926
21973
|
function safeEnrichmentName(value) {
|
|
21927
21974
|
return safeFileName(value) && !/^original(?:\.|$)/i.test(value);
|
|
21928
21975
|
}
|
|
21929
21976
|
function parseFileEnrichMetadata(value, maxBytes) {
|
|
21930
|
-
const
|
|
21977
|
+
const invalid3 = () => {
|
|
21931
21978
|
throw new FileOperationError("invalid_input", 400);
|
|
21932
21979
|
};
|
|
21933
21980
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
21934
|
-
return
|
|
21981
|
+
return invalid3();
|
|
21935
21982
|
const d = value;
|
|
21936
21983
|
if (Object.keys(d).some((key) => !["name", "size", "mediaType", "replace"].includes(key)) || !safeEnrichmentName(d.name) || !Number.isSafeInteger(d.size) || d.size < 0 || d.mediaType !== undefined && (typeof d.mediaType !== "string" || d.mediaType.length > 255 || /[\u0000-\u001f\u007f]/.test(d.mediaType)) || d.replace !== undefined && (typeof d.replace !== "string" || !/^[0-9a-f]{64}$/.test(d.replace)))
|
|
21937
|
-
return
|
|
21984
|
+
return invalid3();
|
|
21938
21985
|
if (d.size > maxBytes)
|
|
21939
21986
|
throw new FileOperationError("request_too_large", 413);
|
|
21940
21987
|
return d;
|
|
@@ -21946,37 +21993,37 @@ function safeFilePath(value) {
|
|
|
21946
21993
|
return typeof value === "string" && value.length <= 1024 && value.split("/").every(safeFileName);
|
|
21947
21994
|
}
|
|
21948
21995
|
function parseFileCreateMetadata(value, maxBytes) {
|
|
21949
|
-
const
|
|
21996
|
+
const invalid3 = () => {
|
|
21950
21997
|
throw new FileOperationError("invalid_input", 400);
|
|
21951
21998
|
};
|
|
21952
21999
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
21953
|
-
return
|
|
22000
|
+
return invalid3();
|
|
21954
22001
|
const input = value;
|
|
21955
22002
|
if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "size", "requestKey"].includes(key)))
|
|
21956
|
-
return
|
|
22003
|
+
return invalid3();
|
|
21957
22004
|
const path = input.path === undefined ? "Files" : input.path;
|
|
21958
22005
|
if (!safeFileName(input.name) || !safeFilePath(path))
|
|
21959
|
-
return
|
|
22006
|
+
return invalid3();
|
|
21960
22007
|
if (input.storage !== undefined && input.storage !== "remote" && input.storage !== "local")
|
|
21961
|
-
return
|
|
22008
|
+
return invalid3();
|
|
21962
22009
|
if (!Number.isSafeInteger(input.size) || input.size < 0)
|
|
21963
|
-
return
|
|
22010
|
+
return invalid3();
|
|
21964
22011
|
if (input.size > maxBytes)
|
|
21965
22012
|
throw new FileOperationError("request_too_large", 413);
|
|
21966
22013
|
if (typeof input.requestKey !== "string" || input.requestKey.length < 1 || input.requestKey.length > 256 || input.requestKey !== input.requestKey.trim() || /[\u0000-\u001f\u007f]/.test(input.requestKey))
|
|
21967
|
-
return
|
|
22014
|
+
return invalid3();
|
|
21968
22015
|
let csv;
|
|
21969
22016
|
if (input.csv !== undefined) {
|
|
21970
22017
|
if (!input.csv || typeof input.csv !== "object" || Array.isArray(input.csv))
|
|
21971
|
-
return
|
|
22018
|
+
return invalid3();
|
|
21972
22019
|
const hints = input.csv;
|
|
21973
22020
|
if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key)))
|
|
21974
|
-
return
|
|
22021
|
+
return invalid3();
|
|
21975
22022
|
const encoding = hints.encoding === undefined ? "utf-8" : hints.encoding;
|
|
21976
22023
|
const delimiter = hints.delimiter === undefined ? "," : hints.delimiter;
|
|
21977
22024
|
const headerRow = hints.headerRow === undefined ? 1 : hints.headerRow;
|
|
21978
22025
|
if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", "\t"].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5)
|
|
21979
|
-
return
|
|
22026
|
+
return invalid3();
|
|
21980
22027
|
csv = { encoding, delimiter, headerRow };
|
|
21981
22028
|
}
|
|
21982
22029
|
return {
|
|
@@ -22432,15 +22479,16 @@ var data = {
|
|
|
22432
22479
|
async function send(input) {
|
|
22433
22480
|
const context = await resolveDataContext();
|
|
22434
22481
|
try {
|
|
22435
|
-
|
|
22482
|
+
const envelope = { repository, ...input };
|
|
22483
|
+
checkDataRequestSize(envelope);
|
|
22436
22484
|
if ("local" in context)
|
|
22437
|
-
return await context.local("data/query",
|
|
22485
|
+
return await context.local("data/query", envelope);
|
|
22438
22486
|
const response = await fetch(context.url, {
|
|
22439
22487
|
method: "POST",
|
|
22440
22488
|
redirect: "error",
|
|
22441
22489
|
cache: "no-store",
|
|
22442
22490
|
headers: { "content-type": "application/json", ...context.headers },
|
|
22443
|
-
body: JSON.stringify(
|
|
22491
|
+
body: JSON.stringify(envelope)
|
|
22444
22492
|
});
|
|
22445
22493
|
const result = await response.json();
|
|
22446
22494
|
if (!response.ok) {
|
|
@@ -22460,13 +22508,11 @@ var data = {
|
|
|
22460
22508
|
},
|
|
22461
22509
|
records: {
|
|
22462
22510
|
select: (query) => send({ operation: "records.select", query }),
|
|
22463
|
-
search: (query, options) => {
|
|
22464
|
-
|
|
22465
|
-
|
|
22466
|
-
|
|
22467
|
-
|
|
22468
|
-
}
|
|
22469
|
-
}
|
|
22511
|
+
search: async (query, options) => send({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
|
|
22512
|
+
},
|
|
22513
|
+
history: {
|
|
22514
|
+
list: async (options) => send({ operation: "history.list", options: captureHistoryListOptions(options) }),
|
|
22515
|
+
at: async (instant) => send({ operation: "history.at", instant: captureHistoryInstant(instant) })
|
|
22470
22516
|
},
|
|
22471
22517
|
changes() {
|
|
22472
22518
|
let updates = [], creates = [], deletes = [], publicationId;
|
|
@@ -22574,7 +22620,7 @@ var TIMEOUT_MS = 30000;
|
|
|
22574
22620
|
var MAX_ACTIVE = 4;
|
|
22575
22621
|
var ATTEMPTS = 2;
|
|
22576
22622
|
var active = 0;
|
|
22577
|
-
var
|
|
22623
|
+
var invalid3 = () => new FileOperationError("invalid_input", 400);
|
|
22578
22624
|
var unavailable = () => new FileOperationError("unavailable", 503, true);
|
|
22579
22625
|
var failures = {
|
|
22580
22626
|
400: ["invalid_input", "unsupported_context"],
|
|
@@ -22598,7 +22644,7 @@ async function boundedBytes(stream, limit) {
|
|
|
22598
22644
|
if (done)
|
|
22599
22645
|
break;
|
|
22600
22646
|
if (!(value instanceof Uint8Array))
|
|
22601
|
-
throw
|
|
22647
|
+
throw invalid3();
|
|
22602
22648
|
size += value.byteLength;
|
|
22603
22649
|
if (size > limit)
|
|
22604
22650
|
throw new FileOperationError("request_too_large", 413);
|
|
@@ -22780,7 +22826,7 @@ async function send(suffix, init, descriptor, initial, parent) {
|
|
|
22780
22826
|
}
|
|
22781
22827
|
function idPath(id2) {
|
|
22782
22828
|
if (typeof id2 !== "string" || !FILE_ID_PATTERN.test(id2))
|
|
22783
|
-
throw
|
|
22829
|
+
throw invalid3();
|
|
22784
22830
|
return `/${id2}`;
|
|
22785
22831
|
}
|
|
22786
22832
|
async function multipartCreate(input, metadata, exchange, release = () => {
|
|
@@ -22844,12 +22890,12 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
22844
22890
|
offset = 0;
|
|
22845
22891
|
const value2 = await next();
|
|
22846
22892
|
if (value2.done)
|
|
22847
|
-
throw
|
|
22893
|
+
throw invalid3();
|
|
22848
22894
|
if (!(value2.value instanceof Uint8Array))
|
|
22849
|
-
throw
|
|
22895
|
+
throw invalid3();
|
|
22850
22896
|
chunk = value2.value;
|
|
22851
22897
|
if (chunk.byteLength > metadata.size - sent - filled)
|
|
22852
|
-
throw
|
|
22898
|
+
throw invalid3();
|
|
22853
22899
|
}
|
|
22854
22900
|
const take = Math.min(length - filled, chunk.byteLength - offset);
|
|
22855
22901
|
part.set(chunk.subarray(offset, offset + take), filled);
|
|
@@ -22862,7 +22908,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
22862
22908
|
}
|
|
22863
22909
|
}
|
|
22864
22910
|
if (part.byteLength !== length)
|
|
22865
|
-
throw
|
|
22911
|
+
throw invalid3();
|
|
22866
22912
|
if (reader && sent + length === metadata.size) {
|
|
22867
22913
|
lastProgress = Date.now();
|
|
22868
22914
|
for (;; ) {
|
|
@@ -22870,7 +22916,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
22870
22916
|
if (value2.done)
|
|
22871
22917
|
break;
|
|
22872
22918
|
if (!(value2.value instanceof Uint8Array) || value2.value.byteLength)
|
|
22873
|
-
throw
|
|
22919
|
+
throw invalid3();
|
|
22874
22920
|
}
|
|
22875
22921
|
}
|
|
22876
22922
|
const value = await request((signal) => exchange(`${route}/part`, {
|
|
@@ -22890,7 +22936,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
22890
22936
|
for (const name of Object.keys(upload.file.enrichments)) {
|
|
22891
22937
|
const bytes = await request(() => upload.enrichment(name));
|
|
22892
22938
|
if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES)
|
|
22893
|
-
throw
|
|
22939
|
+
throw invalid3();
|
|
22894
22940
|
await request((signal) => exchange(`${route}/enrichments/${encodeURIComponent(name)}`, {
|
|
22895
22941
|
method: "POST",
|
|
22896
22942
|
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket },
|
|
@@ -22944,7 +22990,7 @@ function contentPath(id2, name) {
|
|
|
22944
22990
|
if (name === undefined)
|
|
22945
22991
|
return `${path}/content`;
|
|
22946
22992
|
if (!safeEnrichmentName(name))
|
|
22947
|
-
throw
|
|
22993
|
+
throw invalid3();
|
|
22948
22994
|
return `${path}/enrichments/${encodeURIComponent(name)}/content`;
|
|
22949
22995
|
}
|
|
22950
22996
|
async function read(id2, names) {
|
|
@@ -22955,16 +23001,16 @@ async function read(id2, names) {
|
|
|
22955
23001
|
return operation((context2, signal) => send(path, { method: "GET" }, false, context2, signal), context);
|
|
22956
23002
|
}
|
|
22957
23003
|
if (!Array.isArray(names))
|
|
22958
|
-
throw
|
|
23004
|
+
throw invalid3();
|
|
22959
23005
|
const distinct = [];
|
|
22960
23006
|
const seen = new Set;
|
|
22961
23007
|
for (const name of names) {
|
|
22962
23008
|
if (typeof name !== "string" || !safeEnrichmentName(name))
|
|
22963
|
-
throw
|
|
23009
|
+
throw invalid3();
|
|
22964
23010
|
if (seen.has(name))
|
|
22965
23011
|
continue;
|
|
22966
23012
|
if (seen.size === 16)
|
|
22967
|
-
throw
|
|
23013
|
+
throw invalid3();
|
|
22968
23014
|
seen.add(name);
|
|
22969
23015
|
distinct.push(name);
|
|
22970
23016
|
}
|
|
@@ -22998,15 +23044,15 @@ var files = {
|
|
|
22998
23044
|
async create(input, options) {
|
|
22999
23045
|
const context = await resolveFilesContext();
|
|
23000
23046
|
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "size", "path", "name", "storage", "csv"].includes(key)) || options !== undefined && (!options || typeof options !== "object" || Array.isArray(options) || Object.keys(options).some((key) => key !== "requestKey")))
|
|
23001
|
-
throw
|
|
23047
|
+
throw invalid3();
|
|
23002
23048
|
const blob = input.file instanceof Blob;
|
|
23003
23049
|
const array2 = input.file instanceof Uint8Array;
|
|
23004
23050
|
const stream = input.file instanceof ReadableStream;
|
|
23005
23051
|
if (!blob && !array2 && !stream)
|
|
23006
|
-
throw
|
|
23052
|
+
throw invalid3();
|
|
23007
23053
|
const intrinsic = blob ? input.file.size : array2 ? input.file.byteLength : undefined;
|
|
23008
23054
|
if (intrinsic !== undefined && input.size !== undefined && input.size !== intrinsic)
|
|
23009
|
-
throw
|
|
23055
|
+
throw invalid3();
|
|
23010
23056
|
let name = input.name;
|
|
23011
23057
|
if (name === undefined && blob && "name" in input.file && typeof input.file.name === "string") {
|
|
23012
23058
|
name = typeof globalThis.File !== "undefined" && input.file instanceof globalThis.File ? input.file.name : input.file.name.split(/[\\/]/).at(-1);
|
|
@@ -23023,7 +23069,7 @@ var files = {
|
|
|
23023
23069
|
throw new FileOperationError("unsupported_context", 400);
|
|
23024
23070
|
const header = encodeURIComponent(JSON.stringify(metadata));
|
|
23025
23071
|
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES)
|
|
23026
|
-
throw
|
|
23072
|
+
throw invalid3();
|
|
23027
23073
|
if (active >= MAX_ACTIVE)
|
|
23028
23074
|
throw new FileOperationError("capacity", 429, true);
|
|
23029
23075
|
active++;
|
|
@@ -23057,7 +23103,7 @@ var files = {
|
|
|
23057
23103
|
try {
|
|
23058
23104
|
const bytes = array2 ? input.file.slice() : await boundedBytes(blob ? input.file.stream() : input.file, metadata.size);
|
|
23059
23105
|
if (bytes.byteLength !== metadata.size)
|
|
23060
|
-
throw
|
|
23106
|
+
throw invalid3();
|
|
23061
23107
|
if (signal.aborted)
|
|
23062
23108
|
throw unavailable();
|
|
23063
23109
|
return await send("", {
|
|
@@ -23075,7 +23121,7 @@ var files = {
|
|
|
23075
23121
|
async enrich(input) {
|
|
23076
23122
|
const context = await resolveFilesContext();
|
|
23077
23123
|
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))
|
|
23078
|
-
throw
|
|
23124
|
+
throw invalid3();
|
|
23079
23125
|
const path = `${idPath(input.file)}/enrichments`;
|
|
23080
23126
|
if (typeof input.content === "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
|
|
23081
23127
|
throw new FileOperationError("request_too_large", 413);
|
|
@@ -23097,7 +23143,7 @@ var files = {
|
|
|
23097
23143
|
}, MAX_BYTES);
|
|
23098
23144
|
const header = encodeURIComponent(JSON.stringify(metadata));
|
|
23099
23145
|
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES)
|
|
23100
|
-
throw
|
|
23146
|
+
throw invalid3();
|
|
23101
23147
|
const result2 = await send(path, { method: "POST", headers: {
|
|
23102
23148
|
"content-type": "application/octet-stream",
|
|
23103
23149
|
"x-oddington-enrichment": header
|
|
@@ -13,7 +13,7 @@ export { AirtableOperationError } from '../../../shared/airtable-contract.js';
|
|
|
13
13
|
export type { AirtableField, AirtableTable, AirtableRecord, AirtableListInput, AirtableGetInput, AirtableCreateInput, AirtableUpdateInput, AirtableDeleteInput, AirtableReceipt, AirtableWriteResult, AirtableClient, Connections } from '../../../shared/airtable-contract.js';
|
|
14
14
|
export declare const connections: import('../../../shared/airtable-contract.js').Connections;
|
|
15
15
|
export { DataOperationError } from '../../../shared/data-contract.js';
|
|
16
|
-
export type { DataRepository, DataErrorCode, PublicValueDefinition, PublicField, CollectionSummary, CollectionSchema, QueryScalar, SelectionOptions, RecordSelection, RecordsQuery, DataValue, SelectedRecord, SelectionMetadata, RecordsResult, RecordsSearchOptions, RecordsSearchResult, RecordIdentity, RecordCreation, RecordUpdateSet, DataPublication, DataChangeSet, DataEffect } from '../../../shared/data-contract.js';
|
|
16
|
+
export type { DataRepository, DataErrorCode, PublicValueDefinition, PublicField, CollectionSummary, CollectionSchema, QueryScalar, SelectionOptions, RecordSelection, RecordsQuery, DataValue, SelectedRecord, SelectionMetadata, RecordsResult, RecordsSearchOptions, RecordsSearchResult, HistoryListOptions, HistoryEntry, RecordIdentity, RecordCreation, RecordUpdateSet, DataPublication, DataChangeSet, DataEffect } from '../../../shared/data-contract.js';
|
|
17
17
|
export declare const data: {
|
|
18
18
|
repository(name: string): import('../../../shared/data-contract.js').DataRepository;
|
|
19
19
|
};
|
|
@@ -134,6 +134,28 @@ export type DataPublication = {
|
|
|
134
134
|
updated: RecordIdentity[];
|
|
135
135
|
deleted: RecordIdentity[];
|
|
136
136
|
};
|
|
137
|
+
export type HistoryListOptions = {
|
|
138
|
+
limit?: number;
|
|
139
|
+
before?: string;
|
|
140
|
+
};
|
|
141
|
+
export type HistoryEntry = {
|
|
142
|
+
version: string;
|
|
143
|
+
publishedAt: string;
|
|
144
|
+
author: {
|
|
145
|
+
name: string;
|
|
146
|
+
email: string;
|
|
147
|
+
};
|
|
148
|
+
authoredAt: string;
|
|
149
|
+
committer: {
|
|
150
|
+
name: string;
|
|
151
|
+
email: string;
|
|
152
|
+
};
|
|
153
|
+
committedAt: string;
|
|
154
|
+
message: string;
|
|
155
|
+
created: string[];
|
|
156
|
+
updated: string[];
|
|
157
|
+
deleted: string[];
|
|
158
|
+
};
|
|
137
159
|
export interface DataChangeSet {
|
|
138
160
|
create(record: RecordCreation): void;
|
|
139
161
|
update(record: RecordIdentity, set: RecordUpdateSet): void;
|
|
@@ -150,6 +172,10 @@ export interface DataRepository {
|
|
|
150
172
|
select(query: RecordsQuery): Promise<RecordsResult>;
|
|
151
173
|
search(query: string, options?: RecordsSearchOptions): Promise<RecordsSearchResult>;
|
|
152
174
|
};
|
|
175
|
+
history: {
|
|
176
|
+
list(options?: HistoryListOptions): Promise<HistoryEntry[]>;
|
|
177
|
+
at(instant: string): Promise<HistoryEntry | null>;
|
|
178
|
+
};
|
|
153
179
|
changes(): DataChangeSet;
|
|
154
180
|
}
|
|
155
181
|
export type DataErrorCode = 'context_unavailable' | 'unauthenticated' | 'access_denied' | 'invalid_query' | 'request_too_large' | 'capacity' | 'unavailable' | 'invalid_change' | 'conflict' | 'publication_pending';
|