@oddington/sdk 0.1.5 → 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/README.md CHANGED
@@ -140,8 +140,41 @@ Each graph selection sends one request and returns only selected canonical
140
140
  values, expanded forward links and exact opaque public versions. Cursors
141
141
  continue the exact retained artifact and collection selection, even after
142
142
  replacement; repeat its options and links while omitting unrelated collections.
143
- No automatic retry, separate version fetch, search or history operation is
144
- included. Collection schemas omit Markdown storage hints.
143
+ There is no automatic retry or separate version fetch. History is not included.
144
+ Collection schemas omit Markdown storage hints.
145
+
146
+ Use bounded plain-text lookup to find full Records and guards:
147
+
148
+ ```ts
149
+ const found = await general.records.search('acme overdue', {
150
+ collections: ['invoices'], limit: 20,
151
+ });
152
+ const searchedVersion = found.$meta.version;
153
+ for (const { collection, record } of found.matches) {
154
+ console.log(collection, record.$ref, record.$version);
155
+ }
156
+ ```
157
+
158
+ Search sends one request. The trimmed query has 1–256 Unicode code points;
159
+ case-insensitive whitespace-separated terms match stable refs and structured
160
+ scalar values, including link refs and array values. Every term must match;
161
+ field names and Markdown bodies are excluded. Omitted options search all
162
+ accessible collections with a limit of 20. Supplied collections contain 1–16
163
+ distinct accessible names; the integer limit is 1–100. Invalid queries or
164
+ unsupported options fail with `invalid_query`. There is no cursor, count,
165
+ projection, highlighting, embedding or historical version option.
166
+
167
+ Matches have deterministic order and complete canonical Records. Empty matches
168
+ succeed with the exact searched version. Members search latest published data;
169
+ routines search their captured version, advancing only through their own
170
+ publication. Immediate `os routine run` uses hosted search. During
171
+ `os routine prepare`, search uses the same committed local Index as select,
172
+ ignores dirty/untracked files and advances only to that run's exact proposed
173
+ version after its own Changes publication. Validation does not advance reads;
174
+ another publisher does not move the captured view. Search Records can supply
175
+ guards for subsequent Changes. Missing or incomplete search data, including
176
+ retained versions without it, fails retryably with `unavailable` without an
177
+ alternate read path.
145
178
 
146
179
  `where` combines field conditions with AND. Alongside exact scalar/null equality
147
180
  and `$in`, declared one-valued `integer`, `number` and `date` fields accept
package/dist/index.js CHANGED
@@ -21709,6 +21709,49 @@ class DataOperationError extends Error {
21709
21709
  }
21710
21710
  }
21711
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
+
21712
21755
  // ../../shared/data-envelope.ts
21713
21756
  var DATA_REQUEST_LIMIT = 256 * 1024;
21714
21757
  var invalidChange = () => {
@@ -21842,55 +21885,55 @@ class FileOperationError extends Error {
21842
21885
  }
21843
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}$/;
21844
21887
  function parseFileDescriptor(value) {
21845
- const invalid = () => {
21888
+ const invalid2 = () => {
21846
21889
  throw new FileOperationError("unavailable", 503, true);
21847
21890
  };
21848
21891
  if (!value || typeof value !== "object" || Array.isArray(value))
21849
- return invalid();
21892
+ return invalid2();
21850
21893
  const f = value;
21851
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))
21852
- return invalid();
21895
+ return invalid2();
21853
21896
  const d = f.details;
21854
21897
  if (d.kind === "other") {
21855
21898
  if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream")
21856
- return invalid();
21899
+ return invalid2();
21857
21900
  } else if (d.kind === "csv") {
21858
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)
21859
- return invalid();
21902
+ return invalid2();
21860
21903
  } else
21861
- return invalid();
21904
+ return invalid2();
21862
21905
  for (const [name, descriptor] of Object.entries(f.enrichments)) {
21863
21906
  if (!safeEnrichmentName(name))
21864
- return invalid();
21907
+ return invalid2();
21865
21908
  parseEnrichmentDescriptor(descriptor);
21866
21909
  }
21867
21910
  if (new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024)
21868
- return invalid();
21911
+ return invalid2();
21869
21912
  return f;
21870
21913
  }
21871
21914
  function parseEnrichmentDescriptor(value) {
21872
- const invalid = () => {
21915
+ const invalid2 = () => {
21873
21916
  throw new FileOperationError("unavailable", 503, true);
21874
21917
  };
21875
21918
  if (!value || typeof value !== "object" || Array.isArray(value))
21876
- return invalid();
21919
+ return invalid2();
21877
21920
  const d = value;
21878
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))
21879
- return invalid();
21922
+ return invalid2();
21880
21923
  return d;
21881
21924
  }
21882
21925
  function safeEnrichmentName(value) {
21883
21926
  return safeFileName(value) && !/^original(?:\.|$)/i.test(value);
21884
21927
  }
21885
21928
  function parseFileEnrichMetadata(value, maxBytes) {
21886
- const invalid = () => {
21929
+ const invalid2 = () => {
21887
21930
  throw new FileOperationError("invalid_input", 400);
21888
21931
  };
21889
21932
  if (!value || typeof value !== "object" || Array.isArray(value))
21890
- return invalid();
21933
+ return invalid2();
21891
21934
  const d = value;
21892
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)))
21893
- return invalid();
21936
+ return invalid2();
21894
21937
  if (d.size > maxBytes)
21895
21938
  throw new FileOperationError("request_too_large", 413);
21896
21939
  return d;
@@ -21902,37 +21945,37 @@ function safeFilePath(value) {
21902
21945
  return typeof value === "string" && value.length <= 1024 && value.split("/").every(safeFileName);
21903
21946
  }
21904
21947
  function parseFileCreateMetadata(value, maxBytes) {
21905
- const invalid = () => {
21948
+ const invalid2 = () => {
21906
21949
  throw new FileOperationError("invalid_input", 400);
21907
21950
  };
21908
21951
  if (!value || typeof value !== "object" || Array.isArray(value))
21909
- return invalid();
21952
+ return invalid2();
21910
21953
  const input = value;
21911
21954
  if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "size", "requestKey"].includes(key)))
21912
- return invalid();
21955
+ return invalid2();
21913
21956
  const path = input.path === undefined ? "Files" : input.path;
21914
21957
  if (!safeFileName(input.name) || !safeFilePath(path))
21915
- return invalid();
21958
+ return invalid2();
21916
21959
  if (input.storage !== undefined && input.storage !== "remote" && input.storage !== "local")
21917
- return invalid();
21960
+ return invalid2();
21918
21961
  if (!Number.isSafeInteger(input.size) || input.size < 0)
21919
- return invalid();
21962
+ return invalid2();
21920
21963
  if (input.size > maxBytes)
21921
21964
  throw new FileOperationError("request_too_large", 413);
21922
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))
21923
- return invalid();
21966
+ return invalid2();
21924
21967
  let csv;
21925
21968
  if (input.csv !== undefined) {
21926
21969
  if (!input.csv || typeof input.csv !== "object" || Array.isArray(input.csv))
21927
- return invalid();
21970
+ return invalid2();
21928
21971
  const hints = input.csv;
21929
21972
  if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key)))
21930
- return invalid();
21973
+ return invalid2();
21931
21974
  const encoding = hints.encoding === undefined ? "utf-8" : hints.encoding;
21932
21975
  const delimiter = hints.delimiter === undefined ? "," : hints.delimiter;
21933
21976
  const headerRow = hints.headerRow === undefined ? 1 : hints.headerRow;
21934
21977
  if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", "\t"].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5)
21935
- return invalid();
21978
+ return invalid2();
21936
21979
  csv = { encoding, delimiter, headerRow };
21937
21980
  }
21938
21981
  return {
@@ -22156,7 +22199,16 @@ var data = {
22156
22199
  list: () => send({ operation: "collections.list" }),
22157
22200
  schema: (name) => send({ operation: "collections.schema", name })
22158
22201
  },
22159
- 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
+ },
22160
22212
  changes() {
22161
22213
  let updates = [], creates = [], deletes = [], publicationId;
22162
22214
  let pending, confirmed;
@@ -22261,7 +22313,7 @@ var TIMEOUT_MS = 30000;
22261
22313
  var MAX_ACTIVE = 4;
22262
22314
  var ATTEMPTS = 2;
22263
22315
  var active = 0;
22264
- var invalid = () => new FileOperationError("invalid_input", 400);
22316
+ var invalid2 = () => new FileOperationError("invalid_input", 400);
22265
22317
  var unavailable = () => new FileOperationError("unavailable", 503, true);
22266
22318
  var failures = {
22267
22319
  400: ["invalid_input", "unsupported_context"],
@@ -22285,7 +22337,7 @@ async function boundedBytes(stream, limit) {
22285
22337
  if (done)
22286
22338
  break;
22287
22339
  if (!(value instanceof Uint8Array))
22288
- throw invalid();
22340
+ throw invalid2();
22289
22341
  size += value.byteLength;
22290
22342
  if (size > limit)
22291
22343
  throw new FileOperationError("request_too_large", 413);
@@ -22325,6 +22377,74 @@ async function result(response) {
22325
22377
  throw unavailable();
22326
22378
  }
22327
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
+ }
22328
22448
  async function send(suffix, init, descriptor, initial, parent) {
22329
22449
  const original = initial;
22330
22450
  const checkCurrent = () => {
@@ -22360,13 +22480,17 @@ async function send(suffix, init, descriptor, initial, parent) {
22360
22480
  return new Response(Uint8Array.from(data2, (c) => c.charCodeAt(0)), { status: value2.status, headers: value2.headers });
22361
22481
  }
22362
22482
  return Response.json(value2.json, { status: value2.status, headers: value2.headers });
22363
- })() : await fetch(`${context.url}${suffix}`, {
22364
- ...init,
22365
- signal: parent,
22366
- headers: { ...context.headers, ...init.headers },
22367
- redirect: "error",
22368
- cache: "no-store"
22369
- });
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
+ })();
22370
22494
  if (!response.ok) {
22371
22495
  const value2 = await result(response);
22372
22496
  const error = value2 && typeof value2 === "object" && "error" in value2 ? value2.error : undefined;
@@ -22410,7 +22534,7 @@ async function send(suffix, init, descriptor, initial, parent) {
22410
22534
  }
22411
22535
  function idPath(id2) {
22412
22536
  if (typeof id2 !== "string" || !FILE_ID_PATTERN.test(id2))
22413
- throw invalid();
22537
+ throw invalid2();
22414
22538
  return `/${id2}`;
22415
22539
  }
22416
22540
  async function operation(work, initial, parent) {
@@ -22433,7 +22557,7 @@ function contentPath(id2, name) {
22433
22557
  if (name === undefined)
22434
22558
  return `${path}/content`;
22435
22559
  if (!safeEnrichmentName(name))
22436
- throw invalid();
22560
+ throw invalid2();
22437
22561
  return `${path}/enrichments/${encodeURIComponent(name)}/content`;
22438
22562
  }
22439
22563
  async function read(id2, names) {
@@ -22444,16 +22568,16 @@ async function read(id2, names) {
22444
22568
  return operation((context2, signal) => send(path, { method: "GET" }, false, context2, signal), context);
22445
22569
  }
22446
22570
  if (!Array.isArray(names))
22447
- throw invalid();
22571
+ throw invalid2();
22448
22572
  const distinct = [];
22449
22573
  const seen = new Set;
22450
22574
  for (const name of names) {
22451
22575
  if (typeof name !== "string" || !safeEnrichmentName(name))
22452
- throw invalid();
22576
+ throw invalid2();
22453
22577
  if (seen.has(name))
22454
22578
  continue;
22455
22579
  if (seen.size === 16)
22456
- throw invalid();
22580
+ throw invalid2();
22457
22581
  seen.add(name);
22458
22582
  distinct.push(name);
22459
22583
  }
@@ -22487,15 +22611,15 @@ var files = {
22487
22611
  async create(input, options) {
22488
22612
  const context = await resolveFilesContext();
22489
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")))
22490
- throw invalid();
22614
+ throw invalid2();
22491
22615
  const blob = input.file instanceof Blob;
22492
22616
  const array2 = input.file instanceof Uint8Array;
22493
22617
  const stream = input.file instanceof ReadableStream;
22494
22618
  if (!blob && !array2 && !stream)
22495
- throw invalid();
22619
+ throw invalid2();
22496
22620
  const intrinsic = blob ? input.file.size : array2 ? input.file.byteLength : undefined;
22497
22621
  if (intrinsic !== undefined && input.size !== undefined && input.size !== intrinsic)
22498
- throw invalid();
22622
+ throw invalid2();
22499
22623
  let name = input.name;
22500
22624
  if (name === undefined && blob && "name" in input.file && typeof input.file.name === "string") {
22501
22625
  name = typeof globalThis.File !== "undefined" && input.file instanceof globalThis.File ? input.file.name : input.file.name.split(/[\\/]/).at(-1);
@@ -22512,7 +22636,7 @@ var files = {
22512
22636
  throw new FileOperationError("unsupported_context", 400);
22513
22637
  const header = encodeURIComponent(JSON.stringify(metadata));
22514
22638
  if (new TextEncoder().encode(header).byteLength > METADATA_BYTES)
22515
- throw invalid();
22639
+ throw invalid2();
22516
22640
  if (active >= MAX_ACTIVE)
22517
22641
  throw new FileOperationError("capacity", 429, true);
22518
22642
  active++;
@@ -22520,7 +22644,7 @@ var files = {
22520
22644
  try {
22521
22645
  const bytes = array2 ? input.file.slice() : await boundedBytes(blob ? input.file.stream() : input.file, metadata.size);
22522
22646
  if (bytes.byteLength !== metadata.size)
22523
- throw invalid();
22647
+ throw invalid2();
22524
22648
  if (signal.aborted)
22525
22649
  throw unavailable();
22526
22650
  return await send("", {
@@ -22538,7 +22662,7 @@ var files = {
22538
22662
  async enrich(input) {
22539
22663
  const context = await resolveFilesContext();
22540
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))
22541
- throw invalid();
22665
+ throw invalid2();
22542
22666
  const path = `${idPath(input.file)}/enrichments`;
22543
22667
  if (typeof input.content === "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
22544
22668
  throw new FileOperationError("request_too_large", 413);
@@ -22560,7 +22684,7 @@ var files = {
22560
22684
  }, MAX_BYTES);
22561
22685
  const header = encodeURIComponent(JSON.stringify(metadata));
22562
22686
  if (new TextEncoder().encode(header).byteLength > METADATA_BYTES)
22563
- throw invalid();
22687
+ throw invalid2();
22564
22688
  const result2 = await send(path, { method: "POST", headers: {
22565
22689
  "content-type": "application/octet-stream",
22566
22690
  "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, 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, 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
  };
@@ -107,6 +107,19 @@ export type RecordsResult = {
107
107
  [collection: string]: SelectedRecord[] | SelectionMetadata;
108
108
  };
109
109
  export type RecordIdentity = Pick<SelectedRecord, '$ref' | '$version'>;
110
+ export type RecordsSearchOptions = {
111
+ collections?: string[];
112
+ limit?: number;
113
+ };
114
+ export type RecordsSearchResult = {
115
+ $meta: {
116
+ version: string;
117
+ };
118
+ matches: Array<{
119
+ collection: string;
120
+ record: SelectedRecord;
121
+ }>;
122
+ };
110
123
  export type RecordUpdateSet = Record<string, DataValue>;
111
124
  export type RecordCreation = {
112
125
  $ref: string;
@@ -135,6 +148,7 @@ export interface DataRepository {
135
148
  };
136
149
  records: {
137
150
  select(query: RecordsQuery): Promise<RecordsResult>;
151
+ search(query: string, options?: RecordsSearchOptions): Promise<RecordsSearchResult>;
138
152
  };
139
153
  changes(): DataChangeSet;
140
154
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oddington/sdk",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Oddington routine and response-handler SDK",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",