@oddington/sdk 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5985,9 +5985,9 @@ var init_errors = __esm(() => {
5985
5985
  }(Error);
5986
5986
  CorruptPageTreeError = function(_super) {
5987
5987
  __extends(CorruptPageTreeError2, _super);
5988
- function CorruptPageTreeError2(targetIndex, operation) {
5988
+ function CorruptPageTreeError2(targetIndex, operation2) {
5989
5989
  var _this = this;
5990
- var msg = "Failed to " + operation + " at targetIndex=" + targetIndex + " due to corrupt page tree: It is likely that one or more 'Count' entries are invalid";
5990
+ var msg = "Failed to " + operation2 + " at targetIndex=" + targetIndex + " due to corrupt page tree: It is likely that one or more 'Count' entries are invalid";
5991
5991
  _this = _super.call(this, msg) || this;
5992
5992
  return _this;
5993
5993
  }
@@ -21329,9 +21329,22 @@ function validateRecordDelete(value) {
21329
21329
  }
21330
21330
  function validateRecordChange(value) {
21331
21331
  const input = serializable(value);
21332
- if (Array.isArray(input?.records) && input.records.length && input.records.every((record) => !!record && typeof record === "object" && !Array.isArray(record) && !("set" in record) && !("fields" in record)))
21333
- return validateRecordDelete(input);
21334
- return validateRecordWrite(input);
21332
+ if (!input || Array.isArray(input) || typeof input !== "object" || Object.keys(input).sort().join(",") !== "records,repository" || !validRepositoryAlias(input.repository) || !Array.isArray(input.records) || !input.records.length || input.records.length > 1e4 || new Set(input.records.map((record) => record?.ref)).size !== input.records.length || new TextEncoder().encode(JSON.stringify(input)).byteLength > RECORD_WRITE_INPUT_LIMIT)
21333
+ throw new InboxContractError("Invalid record change batch");
21334
+ const writes = [], deletes = [];
21335
+ for (const record of input.records) {
21336
+ if (!record || typeof record !== "object" || Array.isArray(record))
21337
+ throw new InboxContractError("Invalid record change");
21338
+ if ("set" in record || "fields" in record)
21339
+ writes.push(record);
21340
+ else
21341
+ deletes.push(record);
21342
+ }
21343
+ if (writes.length)
21344
+ validateRecordWrite({ repository: input.repository, records: writes });
21345
+ if (deletes.length)
21346
+ validateRecordDelete({ repository: input.repository, records: deletes });
21347
+ return structuredClone(input);
21335
21348
  }
21336
21349
  function validateRoutineRecordWrite(value) {
21337
21350
  const body = serializable(value);
@@ -21685,15 +21698,60 @@ class DataOperationError extends Error {
21685
21698
  code;
21686
21699
  retryable;
21687
21700
  effect;
21688
- constructor(code, retryable = false, effect) {
21701
+ component;
21702
+ constructor(code, retryable = false, effect, component) {
21689
21703
  super(`Data operation failed: ${code}`);
21690
21704
  this.code = code;
21691
21705
  this.retryable = retryable;
21692
21706
  this.effect = effect;
21707
+ this.component = component;
21693
21708
  this.name = "DataOperationError";
21694
21709
  }
21695
21710
  }
21696
21711
 
21712
+ // ../../shared/data-search-input.ts
21713
+ var invalid = () => {
21714
+ throw new DataOperationError("invalid_query");
21715
+ };
21716
+ var scalarText = (value) => typeof value === "string" && !/[\u0000\uD800-\uDFFF]/u.test(value);
21717
+ function captureRecordsSearchInput(query, options) {
21718
+ if (!scalarText(query))
21719
+ return invalid();
21720
+ const length = [...query.trim()].length;
21721
+ if (length < 1 || length > 256)
21722
+ return invalid();
21723
+ if (options === undefined)
21724
+ return { query };
21725
+ if (!options || typeof options !== "object" || Array.isArray(options) || ![Object.prototype, null].includes(Object.getPrototypeOf(options)))
21726
+ return invalid();
21727
+ const descriptors = Object.getOwnPropertyDescriptors(options);
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();
21730
+ const captured = {};
21731
+ if (Object.hasOwn(descriptors, "collections")) {
21732
+ const supplied = descriptors.collections.value;
21733
+ if (!Array.isArray(supplied) || supplied.length < 1 || supplied.length > 16 || Reflect.ownKeys(supplied).length !== supplied.length + 1)
21734
+ return invalid();
21735
+ const collections = [];
21736
+ for (let index = 0;index < supplied.length; index++) {
21737
+ const descriptor = Object.getOwnPropertyDescriptor(supplied, String(index));
21738
+ if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value") || !scalarText(descriptor.value))
21739
+ return invalid();
21740
+ collections.push(descriptor.value);
21741
+ }
21742
+ if (new Set(collections).size !== collections.length)
21743
+ return invalid();
21744
+ captured.collections = collections;
21745
+ }
21746
+ if (Object.hasOwn(descriptors, "limit")) {
21747
+ const supplied = descriptors.limit.value;
21748
+ if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100)
21749
+ return invalid();
21750
+ captured.limit = supplied;
21751
+ }
21752
+ return { query, options: captured };
21753
+ }
21754
+
21697
21755
  // ../../shared/data-envelope.ts
21698
21756
  var DATA_REQUEST_LIMIT = 256 * 1024;
21699
21757
  var invalidChange = () => {
@@ -21727,14 +21785,20 @@ function captureValue(value, ancestors = new Set, depth = 0) {
21727
21785
  ancestors.delete(value);
21728
21786
  }
21729
21787
  }
21788
+ function captureDataDelete(record2) {
21789
+ const identity = mapping(record2);
21790
+ if (!validRecordRef(identity.$ref) || typeof identity.$version !== "string" || !identity.$version.length || identity.$version.length > 512)
21791
+ return invalidChange();
21792
+ return { ref: identity.$ref, expectedVersion: identity.$version };
21793
+ }
21730
21794
  function captureDataUpdate(record2, set) {
21731
- const identity = mapping(record2), fields3 = mapping(set);
21732
- if (!validRecordRef(identity.$ref) || typeof identity.$version !== "string" || !identity.$version.length || identity.$version.length > 512 || !Object.keys(fields3).length || Object.keys(fields3).some((key) => key.startsWith("$") || ["id", "type"].includes(key)))
21795
+ const identity = captureDataDelete(record2), fields3 = mapping(set);
21796
+ if (!Object.keys(fields3).length || Object.keys(fields3).some((key) => key.startsWith("$") || ["id", "type"].includes(key)))
21733
21797
  return invalidChange();
21734
- return { ref: identity.$ref, expectedVersion: identity.$version, set: captureValue(fields3) };
21798
+ return { ...identity, set: captureValue(fields3) };
21735
21799
  }
21736
- function captureDataUpdates(value) {
21737
- if (!Array.isArray(value) || !value.length || value.length > 1e4)
21800
+ function captureDataUpdates(value, allowEmpty = false) {
21801
+ if (!Array.isArray(value) || !allowEmpty && !value.length || value.length > 1e4)
21738
21802
  return invalidChange();
21739
21803
  const updates = value.map((item) => {
21740
21804
  const row = mapping(item);
@@ -21746,6 +21810,46 @@ function captureDataUpdates(value) {
21746
21810
  return invalidChange();
21747
21811
  return updates;
21748
21812
  }
21813
+ function captureDataCreate(value) {
21814
+ const row = mapping(value);
21815
+ if (!validRecordRef(row.$ref) || Object.keys(row).some((key) => key.startsWith("$") && !["$ref", "$filing"].includes(key)))
21816
+ return invalidChange();
21817
+ const { $ref: ref, $filing, ...fields3 } = row;
21818
+ let filing;
21819
+ if ($filing !== undefined) {
21820
+ const components = mapping($filing);
21821
+ 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)))
21822
+ return invalidChange();
21823
+ filing = { ...components };
21824
+ }
21825
+ return { ref, fields: captureValue(fields3), ...filing ? { filing } : {} };
21826
+ }
21827
+ function captureDataChanges(updatesValue, createsValue = [], deletesValue = []) {
21828
+ const updates = captureDataUpdates(updatesValue, true);
21829
+ if (!Array.isArray(createsValue) || createsValue.length > 1e4)
21830
+ return invalidChange();
21831
+ const creates = createsValue.map((item) => {
21832
+ const row = mapping(item);
21833
+ if (Object.keys(row).some((key) => !["ref", "fields", "filing"].includes(key)) || !Object.hasOwn(row, "ref") || !Object.hasOwn(row, "fields"))
21834
+ return invalidChange();
21835
+ const fields3 = mapping(row.fields);
21836
+ if (Object.keys(fields3).some((key) => key.startsWith("$")))
21837
+ return invalidChange();
21838
+ return captureDataCreate({ ...fields3, $ref: row.ref, ...Object.hasOwn(row, "filing") ? { $filing: row.filing } : {} });
21839
+ });
21840
+ if (!Array.isArray(deletesValue) || deletesValue.length > 1e4)
21841
+ return invalidChange();
21842
+ const deletes = deletesValue.map((item) => {
21843
+ const row = mapping(item);
21844
+ if (Object.keys(row).sort().join(",") !== "expectedVersion,ref")
21845
+ return invalidChange();
21846
+ return captureDataDelete({ $ref: row.ref, $version: row.expectedVersion });
21847
+ });
21848
+ const refs = [...updates, ...creates, ...deletes].map((item) => item.ref);
21849
+ if (!refs.length || refs.length > 1e4 || new Set(refs).size !== refs.length)
21850
+ return invalidChange();
21851
+ return { updates, creates, deletes };
21852
+ }
21749
21853
  function checkDataRequestSize(input) {
21750
21854
  if (new TextEncoder().encode(JSON.stringify(input)).byteLength > DATA_REQUEST_LIMIT)
21751
21855
  throw new DataOperationError("request_too_large", false, "unapplied");
@@ -21764,7 +21868,7 @@ function dataTransportError(status, value) {
21764
21868
  const row = error && typeof error === "object" ? error : undefined;
21765
21869
  const code = failures[status]?.find((allowed) => allowed === row?.code) ?? "unavailable";
21766
21870
  const effect = ["unapplied", "uncertain", "applied"].includes(String(row?.effect)) ? row.effect : undefined;
21767
- return new DataOperationError(code, ["capacity", "unavailable", "publication_pending"].includes(code), code === "conflict" ? "unapplied" : effect);
21871
+ return new DataOperationError(code, ["capacity", "unavailable", "publication_pending"].includes(code), code === "conflict" ? "unapplied" : effect, code === "invalid_change" && typeof row?.component === "string" && /^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/.test(row.component) ? row.component : undefined);
21768
21872
  }
21769
21873
 
21770
21874
  // ../../shared/files-contract.ts
@@ -21781,25 +21885,59 @@ class FileOperationError extends Error {
21781
21885
  }
21782
21886
  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}$/;
21783
21887
  function parseFileDescriptor(value) {
21784
- const invalid = () => {
21888
+ const invalid2 = () => {
21785
21889
  throw new FileOperationError("unavailable", 503, true);
21786
21890
  };
21787
21891
  if (!value || typeof value !== "object" || Array.isArray(value))
21788
- return invalid();
21892
+ return invalid2();
21789
21893
  const f = value;
21790
- 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 || typeof f.sha256 !== "string" || !/^[0-9a-f]{64}$/.test(f.sha256) || !f.enrichments || typeof f.enrichments !== "object" || Array.isArray(f.enrichments) || Object.keys(f.enrichments).length !== 0 || !f.details || typeof f.details !== "object" || Array.isArray(f.details))
21791
- return invalid();
21894
+ 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 > 16 * 1024 * 1024 || 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))
21895
+ return invalid2();
21792
21896
  const d = f.details;
21793
21897
  if (d.kind === "other") {
21794
21898
  if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream")
21795
- return invalid();
21899
+ return invalid2();
21796
21900
  } else if (d.kind === "csv") {
21797
21901
  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)
21798
- return invalid();
21902
+ return invalid2();
21799
21903
  } else
21800
- return invalid();
21904
+ return invalid2();
21905
+ for (const [name, descriptor] of Object.entries(f.enrichments)) {
21906
+ if (!safeEnrichmentName(name))
21907
+ return invalid2();
21908
+ parseEnrichmentDescriptor(descriptor);
21909
+ }
21910
+ if (new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024)
21911
+ return invalid2();
21801
21912
  return f;
21802
21913
  }
21914
+ function parseEnrichmentDescriptor(value) {
21915
+ const invalid2 = () => {
21916
+ throw new FileOperationError("unavailable", 503, true);
21917
+ };
21918
+ if (!value || typeof value !== "object" || Array.isArray(value))
21919
+ return invalid2();
21920
+ const d = value;
21921
+ 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))
21922
+ return invalid2();
21923
+ return d;
21924
+ }
21925
+ function safeEnrichmentName(value) {
21926
+ return safeFileName(value) && !/^original(?:\.|$)/i.test(value);
21927
+ }
21928
+ function parseFileEnrichMetadata(value, maxBytes) {
21929
+ const invalid2 = () => {
21930
+ throw new FileOperationError("invalid_input", 400);
21931
+ };
21932
+ if (!value || typeof value !== "object" || Array.isArray(value))
21933
+ return invalid2();
21934
+ const d = value;
21935
+ 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)))
21936
+ return invalid2();
21937
+ if (d.size > maxBytes)
21938
+ throw new FileOperationError("request_too_large", 413);
21939
+ return d;
21940
+ }
21803
21941
  function safeFileName(value) {
21804
21942
  return typeof value === "string" && value.length > 0 && value.length <= 255 && value === value.trim() && value !== "." && value !== ".." && !/[\u0000-\u001f\u007f-\u009f/\\:*?"<>|]/u.test(value) && !/[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/.test(value) && !/[. ]$/.test(value) && !/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(value);
21805
21943
  }
@@ -21807,42 +21945,47 @@ function safeFilePath(value) {
21807
21945
  return typeof value === "string" && value.length <= 1024 && value.split("/").every(safeFileName);
21808
21946
  }
21809
21947
  function parseFileCreateMetadata(value, maxBytes) {
21810
- const invalid = () => {
21948
+ const invalid2 = () => {
21811
21949
  throw new FileOperationError("invalid_input", 400);
21812
21950
  };
21813
21951
  if (!value || typeof value !== "object" || Array.isArray(value))
21814
- return invalid();
21952
+ return invalid2();
21815
21953
  const input = value;
21816
21954
  if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "size", "requestKey"].includes(key)))
21817
- return invalid();
21955
+ return invalid2();
21818
21956
  const path = input.path === undefined ? "Files" : input.path;
21819
21957
  if (!safeFileName(input.name) || !safeFilePath(path))
21820
- return invalid();
21821
- if (input.storage === "local" || input.storage === "both")
21822
- throw new FileOperationError("unsupported_context", 400);
21823
- if (input.storage !== undefined && input.storage !== "remote")
21824
- return invalid();
21958
+ return invalid2();
21959
+ if (input.storage !== undefined && input.storage !== "remote" && input.storage !== "local")
21960
+ return invalid2();
21825
21961
  if (!Number.isSafeInteger(input.size) || input.size < 0)
21826
- return invalid();
21962
+ return invalid2();
21827
21963
  if (input.size > maxBytes)
21828
21964
  throw new FileOperationError("request_too_large", 413);
21829
21965
  if (typeof input.requestKey !== "string" || input.requestKey.length < 1 || input.requestKey.length > 256 || input.requestKey !== input.requestKey.trim() || /[\u0000-\u001f\u007f]/.test(input.requestKey))
21830
- return invalid();
21966
+ return invalid2();
21831
21967
  let csv;
21832
21968
  if (input.csv !== undefined) {
21833
21969
  if (!input.csv || typeof input.csv !== "object" || Array.isArray(input.csv))
21834
- return invalid();
21970
+ return invalid2();
21835
21971
  const hints = input.csv;
21836
21972
  if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key)))
21837
- return invalid();
21973
+ return invalid2();
21838
21974
  const encoding = hints.encoding === undefined ? "utf-8" : hints.encoding;
21839
21975
  const delimiter = hints.delimiter === undefined ? "," : hints.delimiter;
21840
21976
  const headerRow = hints.headerRow === undefined ? 1 : hints.headerRow;
21841
21977
  if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", "\t"].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5)
21842
- return invalid();
21978
+ return invalid2();
21843
21979
  csv = { encoding, delimiter, headerRow };
21844
21980
  }
21845
- return { name: input.name, path, storage: "remote", ...csv ? { csv } : {}, size: input.size, requestKey: input.requestKey };
21981
+ return {
21982
+ name: input.name,
21983
+ path,
21984
+ ...input.storage ? { storage: input.storage } : {},
21985
+ ...csv ? { csv } : {},
21986
+ size: input.size,
21987
+ requestKey: input.requestKey
21988
+ };
21846
21989
  }
21847
21990
 
21848
21991
  // ../../shared/os-origin.ts
@@ -21856,6 +21999,21 @@ function oddingtonOrigin(environment = process.env) {
21856
21999
  }
21857
22000
 
21858
22001
  // src/routine-local-transport.ts
22002
+ function privateRoutineRequest(environment = typeof process === "undefined" ? {} : process.env) {
22003
+ const prepared = ["ODDINGTON_ROUTINE_LOCAL", "ODDINGTON_ROUTINE_LOCAL_SOCKET", "ODDINGTON_ROUTINE_LOCAL_TOKEN"].some((key) => environment[key] !== undefined);
22004
+ const managed = ["ODDINGTON_FILES_SOCKET", "ODDINGTON_FILES_TOKEN"].some((key) => environment[key] !== undefined);
22005
+ if (!prepared && !managed)
22006
+ return;
22007
+ const socket = prepared ? environment.ODDINGTON_ROUTINE_LOCAL_SOCKET : environment.ODDINGTON_FILES_SOCKET;
22008
+ const token = prepared ? environment.ODDINGTON_ROUTINE_LOCAL_TOKEN : environment.ODDINGTON_FILES_TOKEN;
22009
+ const request = localRoutineRequest(prepared ? environment : {
22010
+ ODDINGTON_ROUTINE_LOCAL: "1",
22011
+ ODDINGTON_ROUTINE_LOCAL_SOCKET: socket,
22012
+ ODDINGTON_ROUTINE_LOCAL_TOKEN: token
22013
+ });
22014
+ const isCurrent = () => prepared ? environment.ODDINGTON_ROUTINE_LOCAL === "1" && environment.ODDINGTON_ROUTINE_LOCAL_SOCKET === socket && environment.ODDINGTON_ROUTINE_LOCAL_TOKEN === token : environment.ODDINGTON_FILES_SOCKET === socket && environment.ODDINGTON_FILES_TOKEN === token;
22015
+ return { request, isCurrent, identity: `private:${socket}` };
22016
+ }
21859
22017
  function localRoutineRequest(environment = typeof process === "undefined" ? {} : process.env) {
21860
22018
  const {
21861
22019
  ODDINGTON_ROUTINE_LOCAL: mode,
@@ -21865,11 +22023,11 @@ function localRoutineRequest(environment = typeof process === "undefined" ? {} :
21865
22023
  if (mode === undefined && socket === undefined && token === undefined)
21866
22024
  return;
21867
22025
  if (mode !== "1" || !socket || !token || !/^[0-9a-f]{64}$/.test(token))
21868
- throw new Error("Local preparation transport unavailable; nothing can publish");
22026
+ throw new Error("Preparation transport unavailable; nothing can publish");
21869
22027
  const tcp = /^tcp:\/\/127\.0\.0\.1:([1-9][0-9]{0,4})$/.exec(socket);
21870
22028
  const endpoint = tcp && tcp[0] === socket && Number(tcp[1]) <= 65535 ? { hostname: "127.0.0.1", port: Number(tcp[1]) } : socket.startsWith("/") && !socket.startsWith("//") && !socket.includes("\x00") ? { socketPath: socket } : undefined;
21871
22029
  if (!endpoint)
21872
- throw new Error("Local preparation transport unavailable; nothing can publish");
22030
+ throw new Error("Preparation transport unavailable; nothing can publish");
21873
22031
  return async (operation, input) => {
21874
22032
  const { request } = await import("node:http");
21875
22033
  return await new Promise((resolve, reject) => {
@@ -21880,7 +22038,7 @@ function localRoutineRequest(environment = typeof process === "undefined" ? {} :
21880
22038
  headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
21881
22039
  timeout: 120000
21882
22040
  }, (response) => {
21883
- const chunks = [];
22041
+ const bytes = Buffer.alloc(33554432);
21884
22042
  let size = 0;
21885
22043
  response.on("data", (chunk) => {
21886
22044
  size += chunk.length;
@@ -21888,17 +22046,37 @@ function localRoutineRequest(environment = typeof process === "undefined" ? {} :
21888
22046
  response.destroy();
21889
22047
  reject(new Error("Local result exceeds supported size"));
21890
22048
  } else
21891
- chunks.push(chunk);
22049
+ bytes.set(chunk, size - chunk.length);
21892
22050
  });
21893
22051
  response.on("error", reject);
21894
22052
  response.on("end", () => {
21895
22053
  try {
21896
- const result = JSON.parse(Buffer.concat(chunks).toString());
22054
+ const result = JSON.parse(bytes.subarray(0, size).toString());
21897
22055
  if (response.statusCode !== 200) {
22056
+ if (operation === "files/request") {
22057
+ const error = result.error;
22058
+ const status = response.statusCode ?? 503;
22059
+ const codes = [
22060
+ "invalid_input",
22061
+ "unsupported_context",
22062
+ "unauthenticated",
22063
+ "access_denied",
22064
+ "request_too_large",
22065
+ "conflict",
22066
+ "local_only",
22067
+ "integrity",
22068
+ "unavailable",
22069
+ "capacity",
22070
+ "method_not_allowed"
22071
+ ];
22072
+ if (error?.code && codes.includes(error.code))
22073
+ throw new FileOperationError(error.code, status, error.code === "capacity" || error.code === "unavailable");
22074
+ throw new FileOperationError("unavailable", 503, true);
22075
+ }
21898
22076
  if (operation === "data/query") {
21899
22077
  throw dataTransportError(response.statusCode ?? 0, result);
21900
22078
  }
21901
- throw new Error(typeof result.error === "string" ? result.error : "Local preparation failed");
22079
+ throw new Error(typeof result.error === "string" ? result.error : "Preparation failed");
21902
22080
  }
21903
22081
  resolve(result);
21904
22082
  } catch (error) {
@@ -21906,8 +22084,8 @@ function localRoutineRequest(environment = typeof process === "undefined" ? {} :
21906
22084
  }
21907
22085
  });
21908
22086
  });
21909
- call.on("error", () => reject(new Error("Local preparation transport unavailable; nothing was published")));
21910
- call.on("timeout", () => call.destroy(new Error("Local preparation timed out")));
22087
+ call.on("error", () => reject(new Error("Preparation transport unavailable; nothing was published")));
22088
+ call.on("timeout", () => call.destroy(new Error("Preparation timed out")));
21911
22089
  call.end(JSON.stringify(input));
21912
22090
  });
21913
22091
  };
@@ -21927,6 +22105,9 @@ async function resolveDataContext() {
21927
22105
  const local = localRoutineRequest();
21928
22106
  if (local)
21929
22107
  return { local };
22108
+ const managed = privateRoutineRequest();
22109
+ if (managed)
22110
+ return { local: managed.request };
21930
22111
  const host = memberContext;
21931
22112
  if (host !== undefined) {
21932
22113
  const context = await host();
@@ -21945,8 +22126,14 @@ async function resolveDataContext() {
21945
22126
  async function resolveFilesContext() {
21946
22127
  try {
21947
22128
  const environment = typeof process === "undefined" ? {} : process.env;
21948
- if (["ODDINGTON_ROUTINE_LOCAL", "ODDINGTON_ROUTINE_LOCAL_SOCKET", "ODDINGTON_ROUTINE_LOCAL_TOKEN"].some((key) => environment[key] !== undefined))
21949
- throw new Error;
22129
+ const local = privateRoutineRequest(environment);
22130
+ if (local)
22131
+ return {
22132
+ url: local.identity,
22133
+ headers: {},
22134
+ isCurrent: local.isCurrent,
22135
+ local: local.request
22136
+ };
21950
22137
  const host = memberContext;
21951
22138
  if (host) {
21952
22139
  const context = await host();
@@ -21954,13 +22141,14 @@ async function resolveFilesContext() {
21954
22141
  throw new Error;
21955
22142
  return {
21956
22143
  ...filesContext(context.workspace, context.endpoint, { authorization: `Bearer ${context.accessToken}` }),
21957
- isCurrent: context.isCurrent
22144
+ isCurrent: context.isCurrent,
22145
+ local: undefined
21958
22146
  };
21959
22147
  }
21960
22148
  if (!/^[0-9a-f]{64}$/.test(environment.ODDINGTON_ROUTINE_RUN ?? ""))
21961
22149
  throw new Error;
21962
22150
  const workspace = environment.ODDINGTON_ROUTINE_WORKSPACE;
21963
- return filesContext(workspace, `https://${workspace}.oddington.ai`, { "x-oddington-run": environment.ODDINGTON_ROUTINE_RUN });
22151
+ return { ...filesContext(workspace, `https://${workspace}.oddington.ai`, { "x-oddington-run": environment.ODDINGTON_ROUTINE_RUN }), local: undefined };
21964
22152
  } catch {
21965
22153
  throw new FileOperationError("unsupported_context", 400);
21966
22154
  }
@@ -22011,36 +22199,82 @@ var data = {
22011
22199
  list: () => send({ operation: "collections.list" }),
22012
22200
  schema: (name) => send({ operation: "collections.schema", name })
22013
22201
  },
22014
- records: { select: (query) => send({ operation: "records.select", query }) },
22202
+ records: {
22203
+ select: (query) => send({ operation: "records.select", query }),
22204
+ search: (query, options) => {
22205
+ try {
22206
+ return send({ operation: "records.search", ...captureRecordsSearchInput(query, options) });
22207
+ } catch (error) {
22208
+ return Promise.reject(error);
22209
+ }
22210
+ }
22211
+ },
22015
22212
  changes() {
22016
- let updates = [], publicationId;
22213
+ let updates = [], creates = [], deletes = [], publicationId;
22017
22214
  let pending, confirmed;
22018
22215
  const snapshot = () => {
22019
- const captured = captureDataUpdates(updates);
22216
+ const captured = captureDataChanges(updates, creates, deletes);
22217
+ const input = {
22218
+ updates: captured.updates,
22219
+ ...captured.creates.length ? { creates: captured.creates } : {},
22220
+ ...captured.deletes.length ? { deletes: captured.deletes } : {}
22221
+ };
22020
22222
  checkDataRequestSize({
22021
22223
  repository,
22022
22224
  operation: "changes.publish",
22023
- updates: captured,
22225
+ ...input,
22024
22226
  publicationId: publicationId ?? "00000000-0000-4000-8000-000000000000"
22025
22227
  });
22026
- return captured;
22228
+ return input;
22027
22229
  };
22028
22230
  return {
22231
+ create(record2) {
22232
+ if (publicationId)
22233
+ throw new DataOperationError("invalid_change", false, "unapplied");
22234
+ const next = [...creates, captureDataCreate(record2)];
22235
+ captureDataChanges(updates, next, deletes);
22236
+ checkDataRequestSize({
22237
+ repository,
22238
+ operation: "changes.publish",
22239
+ updates,
22240
+ creates: next,
22241
+ ...deletes.length ? { deletes } : {},
22242
+ publicationId: "00000000-0000-4000-8000-000000000000"
22243
+ });
22244
+ creates = next;
22245
+ },
22029
22246
  update(record2, set) {
22030
22247
  if (publicationId)
22031
22248
  throw new DataOperationError("invalid_change", false, "unapplied");
22032
22249
  const next = [...updates, captureDataUpdate(record2, set)];
22033
- captureDataUpdates(next);
22250
+ captureDataChanges(next, creates, deletes);
22034
22251
  checkDataRequestSize({
22035
22252
  repository,
22036
22253
  operation: "changes.publish",
22037
22254
  updates: next,
22255
+ ...creates.length ? { creates } : {},
22256
+ ...deletes.length ? { deletes } : {},
22038
22257
  publicationId: "00000000-0000-4000-8000-000000000000"
22039
22258
  });
22040
22259
  updates = next;
22041
22260
  },
22261
+ delete(record2) {
22262
+ if (publicationId)
22263
+ throw new DataOperationError("invalid_change", false, "unapplied");
22264
+ const next = [...deletes, captureDataDelete(record2)];
22265
+ captureDataChanges(updates, creates, next);
22266
+ checkDataRequestSize({
22267
+ repository,
22268
+ operation: "changes.publish",
22269
+ updates,
22270
+ deletes: next,
22271
+ ...creates.length ? { creates } : {},
22272
+ publicationId: "00000000-0000-4000-8000-000000000000"
22273
+ });
22274
+ deletes = next;
22275
+ },
22042
22276
  async validate() {
22043
- await send({ operation: "changes.validate", updates: snapshot() });
22277
+ await send({ operation: "changes.validate", ...snapshot() });
22044
22278
  },
22045
22279
  publish() {
22046
22280
  if (confirmed)
@@ -22053,12 +22287,12 @@ var data = {
22053
22287
  return Promise.reject(error);
22054
22288
  }
22055
22289
  publicationId ??= crypto.randomUUID();
22056
- pending = send({ operation: "changes.publish", updates: captured, publicationId }).then((result) => {
22290
+ pending = send({ operation: "changes.publish", ...captured, publicationId }).then((result) => {
22057
22291
  confirmed = structuredClone(result);
22058
22292
  return result;
22059
22293
  }).catch((error) => {
22060
22294
  if (error instanceof DataOperationError)
22061
- throw new DataOperationError(error.code, error.retryable, error.effect ?? (["unavailable", "publication_pending"].includes(error.code) ? "uncertain" : "unapplied"));
22295
+ throw new DataOperationError(error.code, error.retryable, error.effect ?? (["unavailable", "publication_pending"].includes(error.code) ? "uncertain" : "unapplied"), error.component);
22062
22296
  throw new DataOperationError("unavailable", true, "uncertain");
22063
22297
  }).finally(() => {
22064
22298
  pending = undefined;
@@ -22079,14 +22313,14 @@ var TIMEOUT_MS = 30000;
22079
22313
  var MAX_ACTIVE = 4;
22080
22314
  var ATTEMPTS = 2;
22081
22315
  var active = 0;
22082
- var invalid = () => new FileOperationError("invalid_input", 400);
22316
+ var invalid2 = () => new FileOperationError("invalid_input", 400);
22083
22317
  var unavailable = () => new FileOperationError("unavailable", 503, true);
22084
22318
  var failures = {
22085
22319
  400: ["invalid_input", "unsupported_context"],
22086
22320
  401: ["unauthenticated"],
22087
22321
  403: ["access_denied"],
22088
22322
  405: ["method_not_allowed"],
22089
- 409: ["conflict"],
22323
+ 409: ["conflict", "local_only"],
22090
22324
  413: ["request_too_large"],
22091
22325
  429: ["capacity"],
22092
22326
  503: ["integrity", "unavailable"]
@@ -22103,7 +22337,7 @@ async function boundedBytes(stream, limit) {
22103
22337
  if (done)
22104
22338
  break;
22105
22339
  if (!(value instanceof Uint8Array))
22106
- throw invalid();
22340
+ throw invalid2();
22107
22341
  size += value.byteLength;
22108
22342
  if (size > limit)
22109
22343
  throw new FileOperationError("request_too_large", 413);
@@ -22143,8 +22377,76 @@ async function result(response) {
22143
22377
  throw unavailable();
22144
22378
  }
22145
22379
  }
22380
+ async function hostedContent(url, init, parent) {
22381
+ const delivery = new AbortController;
22382
+ const abort = () => delivery.abort(parent.reason);
22383
+ parent.addEventListener("abort", abort, { once: true });
22384
+ if (parent.aborted)
22385
+ abort();
22386
+ const detach = () => parent.removeEventListener("abort", abort);
22387
+ try {
22388
+ const response = await fetch(url, { ...init, signal: delivery.signal });
22389
+ if (delivery.signal.aborted) {
22390
+ response.body?.cancel().catch(() => {});
22391
+ throw unavailable();
22392
+ }
22393
+ if (!response.body) {
22394
+ detach();
22395
+ return response;
22396
+ }
22397
+ const source = response.body;
22398
+ let reader;
22399
+ let settled = false;
22400
+ const cancel = async (reason) => {
22401
+ if (settled)
22402
+ return;
22403
+ settled = true;
22404
+ detach();
22405
+ delivery.abort(reason);
22406
+ try {
22407
+ await (reader ? reader.cancel(reason) : source.cancel(reason));
22408
+ } catch (error) {
22409
+ if (error !== delivery.signal.reason && !(error instanceof Error && error.name === "AbortError"))
22410
+ throw error;
22411
+ } finally {
22412
+ reader?.releaseLock();
22413
+ }
22414
+ };
22415
+ const body = new ReadableStream({
22416
+ async pull(controller) {
22417
+ try {
22418
+ reader ??= source.getReader();
22419
+ const { done, value } = await reader.read();
22420
+ if (settled)
22421
+ return;
22422
+ if (done) {
22423
+ settled = true;
22424
+ detach();
22425
+ reader.releaseLock();
22426
+ controller.close();
22427
+ } else
22428
+ controller.enqueue(value);
22429
+ } catch (error) {
22430
+ if (settled)
22431
+ return;
22432
+ controller.error(error);
22433
+ await cancel(error).catch(() => {});
22434
+ }
22435
+ },
22436
+ cancel
22437
+ }, { highWaterMark: 0 });
22438
+ const wrapped = new Response(body, { status: response.status, statusText: response.statusText, headers: response.headers });
22439
+ for (const key of ["url", "redirected", "type"])
22440
+ Object.defineProperty(wrapped, key, { value: response[key] });
22441
+ return wrapped;
22442
+ } catch (error) {
22443
+ detach();
22444
+ delivery.abort(error);
22445
+ throw error;
22446
+ }
22447
+ }
22146
22448
  async function send(suffix, init, descriptor, initial, parent) {
22147
- const original = initial ?? await resolveFilesContext();
22449
+ const original = initial;
22148
22450
  const checkCurrent = () => {
22149
22451
  if (parent?.aborted)
22150
22452
  throw unavailable();
@@ -22153,37 +22455,75 @@ async function send(suffix, init, descriptor, initial, parent) {
22153
22455
  };
22154
22456
  for (let attempt = 0;attempt < ATTEMPTS; attempt++) {
22155
22457
  checkCurrent();
22156
- const context = attempt === 0 && !initial ? original : await resolveFilesContext();
22458
+ const context = await resolveFilesContext();
22157
22459
  checkCurrent();
22158
22460
  if (context.url !== original.url)
22159
22461
  throw new FileOperationError("unsupported_context", 400);
22160
22462
  try {
22161
- return await timed(async (signal) => {
22162
- const response = await fetch(`${context.url}${suffix}`, {
22163
- ...init,
22164
- signal,
22165
- headers: { ...context.headers, ...init.headers },
22166
- redirect: "error",
22167
- cache: "no-store"
22168
- });
22463
+ return await (async () => {
22464
+ const response = context.local ? await (async () => {
22465
+ const body = init.body instanceof ArrayBuffer ? new Uint8Array(init.body) : undefined;
22466
+ let binary = "";
22467
+ if (body)
22468
+ for (let offset = 0;offset < body.length; offset += 8192)
22469
+ binary += String.fromCharCode(...body.subarray(offset, offset + 8192));
22470
+ const value2 = await context.local("files/request", {
22471
+ suffix,
22472
+ method: init.method,
22473
+ headers: Object.fromEntries(new Headers(init.headers)),
22474
+ ...body ? { bytes: btoa(binary) } : {}
22475
+ });
22476
+ if (value2.bytes !== undefined) {
22477
+ if (value2.bytes.length > Math.ceil(MAX_BYTES / 3) * 4)
22478
+ throw unavailable();
22479
+ const data2 = atob(value2.bytes);
22480
+ return new Response(Uint8Array.from(data2, (c) => c.charCodeAt(0)), { status: value2.status, headers: value2.headers });
22481
+ }
22482
+ return Response.json(value2.json, { status: value2.status, headers: value2.headers });
22483
+ })() : await (async () => {
22484
+ const url = `${context.url}${suffix}`;
22485
+ const request = {
22486
+ ...init,
22487
+ signal: parent,
22488
+ headers: { ...context.headers, ...init.headers },
22489
+ redirect: "error",
22490
+ cache: "no-store"
22491
+ };
22492
+ return descriptor ? fetch(url, request) : hostedContent(url, request, parent);
22493
+ })();
22169
22494
  if (!response.ok) {
22170
- const value = await result(response);
22171
- const error = value && typeof value === "object" && "error" in value ? value.error : undefined;
22495
+ const value2 = await result(response);
22496
+ const error = value2 && typeof value2 === "object" && "error" in value2 ? value2.error : undefined;
22172
22497
  const received = error && typeof error === "object" && "code" in error ? error.code : undefined;
22173
22498
  const code = failures[response.status]?.find((code2) => code2 === received);
22174
22499
  throw code ? new FileOperationError(code, response.status, code === "capacity" || code === "unavailable") : unavailable();
22175
22500
  }
22176
- if (response.status !== 200)
22501
+ if (response.status !== 200) {
22502
+ response.body?.cancel().catch(() => {});
22177
22503
  throw unavailable();
22178
- checkCurrent();
22504
+ }
22505
+ try {
22506
+ checkCurrent();
22507
+ } catch (error) {
22508
+ response.body?.cancel().catch(() => {});
22509
+ throw error;
22510
+ }
22179
22511
  if (!descriptor)
22180
22512
  return response;
22181
- const file = parseFileDescriptor(await result(response));
22182
- if (file.size > MAX_BYTES)
22183
- throw unavailable();
22513
+ const value = await result(response);
22514
+ let parsed;
22515
+ if (descriptor === "enrichment") {
22516
+ if (!value || typeof value !== "object" || Array.isArray(value))
22517
+ throw unavailable();
22518
+ const { name, ...metadata } = value;
22519
+ if (!safeEnrichmentName(name))
22520
+ throw unavailable();
22521
+ parsed = { name, ...parseEnrichmentDescriptor(metadata) };
22522
+ } else
22523
+ parsed = parseFileDescriptor(value);
22184
22524
  checkCurrent();
22185
- return file;
22186
- }, parent);
22525
+ return parsed;
22526
+ })();
22187
22527
  } catch (error) {
22188
22528
  const failure = error instanceof FileOperationError ? error : unavailable();
22189
22529
  if (!failure.retryable || attempt + 1 === ATTEMPTS)
@@ -22194,22 +22534,92 @@ async function send(suffix, init, descriptor, initial, parent) {
22194
22534
  }
22195
22535
  function idPath(id2) {
22196
22536
  if (typeof id2 !== "string" || !FILE_ID_PATTERN.test(id2))
22197
- throw invalid();
22537
+ throw invalid2();
22198
22538
  return `/${id2}`;
22199
22539
  }
22540
+ async function operation(work, initial, parent) {
22541
+ const context = initial ?? await resolveFilesContext();
22542
+ if (active >= MAX_ACTIVE)
22543
+ throw new FileOperationError("capacity", 429, true);
22544
+ active++;
22545
+ return timed(async (signal) => {
22546
+ try {
22547
+ return await work(context, signal);
22548
+ } finally {
22549
+ active--;
22550
+ }
22551
+ }, parent).catch((error) => {
22552
+ throw error instanceof FileOperationError ? error : unavailable();
22553
+ });
22554
+ }
22555
+ function contentPath(id2, name) {
22556
+ const path = idPath(id2);
22557
+ if (name === undefined)
22558
+ return `${path}/content`;
22559
+ if (!safeEnrichmentName(name))
22560
+ throw invalid2();
22561
+ return `${path}/enrichments/${encodeURIComponent(name)}/content`;
22562
+ }
22563
+ async function read(id2, names) {
22564
+ const context = await resolveFilesContext();
22565
+ idPath(id2);
22566
+ if (names === undefined || typeof names === "string") {
22567
+ const path = contentPath(id2, names);
22568
+ return operation((context2, signal) => send(path, { method: "GET" }, false, context2, signal), context);
22569
+ }
22570
+ if (!Array.isArray(names))
22571
+ throw invalid2();
22572
+ const distinct = [];
22573
+ const seen = new Set;
22574
+ for (const name of names) {
22575
+ if (typeof name !== "string" || !safeEnrichmentName(name))
22576
+ throw invalid2();
22577
+ if (seen.has(name))
22578
+ continue;
22579
+ if (seen.size === 16)
22580
+ throw invalid2();
22581
+ seen.add(name);
22582
+ distinct.push(name);
22583
+ }
22584
+ const paths = distinct.map((name) => contentPath(id2, name));
22585
+ return timed(async (parent) => {
22586
+ const responses = {};
22587
+ try {
22588
+ for (let i = 0;i < paths.length; i++) {
22589
+ const response = await operation((context2, signal) => send(paths[i], { method: "GET" }, false, context2, signal), context, parent);
22590
+ Object.defineProperty(responses, distinct[i], { value: response, enumerable: true });
22591
+ }
22592
+ if (!context.isCurrent())
22593
+ throw new FileOperationError("unsupported_context", 400);
22594
+ return responses;
22595
+ } catch (error) {
22596
+ for (const response of Object.values(responses))
22597
+ response.body?.cancel().catch(() => {});
22598
+ throw error;
22599
+ }
22600
+ });
22601
+ }
22200
22602
  var files = {
22603
+ async upload(id2) {
22604
+ return operation(async (context, signal) => {
22605
+ const file = await send(`${idPath(id2)}/upload`, { method: "POST" }, true, context, signal);
22606
+ if (file.id !== id2)
22607
+ throw unavailable();
22608
+ return file;
22609
+ });
22610
+ },
22201
22611
  async create(input, options) {
22202
22612
  const context = await resolveFilesContext();
22203
22613
  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")))
22204
- throw invalid();
22614
+ throw invalid2();
22205
22615
  const blob = input.file instanceof Blob;
22206
22616
  const array2 = input.file instanceof Uint8Array;
22207
22617
  const stream = input.file instanceof ReadableStream;
22208
22618
  if (!blob && !array2 && !stream)
22209
- throw invalid();
22619
+ throw invalid2();
22210
22620
  const intrinsic = blob ? input.file.size : array2 ? input.file.byteLength : undefined;
22211
22621
  if (intrinsic !== undefined && input.size !== undefined && input.size !== intrinsic)
22212
- throw invalid();
22622
+ throw invalid2();
22213
22623
  let name = input.name;
22214
22624
  if (name === undefined && blob && "name" in input.file && typeof input.file.name === "string") {
22215
22625
  name = typeof globalThis.File !== "undefined" && input.file instanceof globalThis.File ? input.file.name : input.file.name.split(/[\\/]/).at(-1);
@@ -22222,9 +22632,11 @@ var files = {
22222
22632
  csv: input.csv,
22223
22633
  requestKey: options?.requestKey === undefined ? crypto.randomUUID() : options.requestKey
22224
22634
  }, MAX_BYTES);
22635
+ if (!context.local && metadata.storage === "local")
22636
+ throw new FileOperationError("unsupported_context", 400);
22225
22637
  const header = encodeURIComponent(JSON.stringify(metadata));
22226
22638
  if (new TextEncoder().encode(header).byteLength > METADATA_BYTES)
22227
- throw invalid();
22639
+ throw invalid2();
22228
22640
  if (active >= MAX_ACTIVE)
22229
22641
  throw new FileOperationError("capacity", 429, true);
22230
22642
  active++;
@@ -22232,7 +22644,7 @@ var files = {
22232
22644
  try {
22233
22645
  const bytes = array2 ? input.file.slice() : await boundedBytes(blob ? input.file.stream() : input.file, metadata.size);
22234
22646
  if (bytes.byteLength !== metadata.size)
22235
- throw invalid();
22647
+ throw invalid2();
22236
22648
  if (signal.aborted)
22237
22649
  throw unavailable();
22238
22650
  return await send("", {
@@ -22247,12 +22659,45 @@ var files = {
22247
22659
  throw error instanceof FileOperationError ? error : unavailable();
22248
22660
  });
22249
22661
  },
22662
+ async enrich(input) {
22663
+ const context = await resolveFilesContext();
22664
+ 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))
22665
+ throw invalid2();
22666
+ const path = `${idPath(input.file)}/enrichments`;
22667
+ if (typeof input.content === "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
22668
+ throw new FileOperationError("request_too_large", 413);
22669
+ return operation(async (context2, signal) => {
22670
+ let bytes;
22671
+ if (typeof input.content === "string") {
22672
+ const buffer = new Uint8Array(Math.min(MAX_BYTES, input.content.length * 3));
22673
+ const encoded = new TextEncoder().encodeInto(input.content, buffer);
22674
+ if (encoded.read !== input.content.length)
22675
+ throw new FileOperationError("request_too_large", 413);
22676
+ bytes = buffer.slice(0, encoded.written);
22677
+ } else
22678
+ bytes = input.content.slice();
22679
+ const metadata = parseFileEnrichMetadata({
22680
+ name: input.name,
22681
+ size: bytes.byteLength,
22682
+ ...input.mediaType === undefined ? {} : { mediaType: input.mediaType },
22683
+ ...input.replace === undefined ? {} : { replace: input.replace }
22684
+ }, MAX_BYTES);
22685
+ const header = encodeURIComponent(JSON.stringify(metadata));
22686
+ if (new TextEncoder().encode(header).byteLength > METADATA_BYTES)
22687
+ throw invalid2();
22688
+ const result2 = await send(path, { method: "POST", headers: {
22689
+ "content-type": "application/octet-stream",
22690
+ "x-oddington-enrichment": header
22691
+ }, body: bytes.buffer }, "enrichment", context2, signal);
22692
+ if (result2.name !== metadata.name)
22693
+ throw unavailable();
22694
+ return result2;
22695
+ }, context);
22696
+ },
22250
22697
  async get(id2) {
22251
- return send(idPath(id2), { method: "GET" }, true);
22698
+ return operation((context, signal) => send(idPath(id2), { method: "GET" }, true, context, signal));
22252
22699
  },
22253
- async read(id2) {
22254
- return send(`${idPath(id2)}/content`, { method: "GET" }, false);
22255
- }
22700
+ read
22256
22701
  };
22257
22702
  // src/os.ts
22258
22703
  var installedDispose;
@@ -22336,16 +22781,16 @@ function routinePublicationClient(options = {}) {
22336
22781
  } : async () => {
22337
22782
  throw new Error("Member publication requires a host-supplied request");
22338
22783
  });
22339
- async function send2(operation, body) {
22784
+ async function send2(operation2, body) {
22340
22785
  if (local)
22341
- return await local(operation, body);
22342
- const response = await request(`/api/cli/workspaces/${workspace}/inbox/${operation}`, {
22786
+ return await local(operation2, body);
22787
+ const response = await request(`/api/cli/workspaces/${workspace}/inbox/${operation2}`, {
22343
22788
  method: "POST",
22344
22789
  headers: { "content-type": "application/json", ...headers },
22345
22790
  body: JSON.stringify(body)
22346
22791
  });
22347
22792
  const result2 = await response.json();
22348
- if (!response.ok && operation === "records/update")
22793
+ if (!response.ok && operation2 === "records/update")
22349
22794
  throw new RoutineRecordWriteError(result2.error ?? "Could not confirm routine preparation", result2.effect ?? "uncertain");
22350
22795
  if (!response.ok)
22351
22796
  throw new Error(result2.error ?? "Could not confirm routine publication");