@oddington/sdk 0.1.32 → 0.1.34
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 +32 -0
- package/dist/browser.js +151 -88
- package/dist/index.js +3 -3
- package/dist/types/packages/sdk/src/data-schema-types.d.ts +3 -1
- package/dist/types/packages/sdk/src/public.d.ts +2 -0
- package/dist/types/packages/sdk/src/source.d.ts +57 -0
- package/dist/types/shared/data-contract.d.ts +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -452,6 +452,38 @@ is read independently with fresh authority; there is no cross-name revision snap
|
|
|
452
452
|
Names cannot contain separators or use the reserved `original` basename with
|
|
453
453
|
or without an extension. Enrichments share their parent File's access and retention.
|
|
454
454
|
|
|
455
|
+
Compose retained Files and ordinary Data changes with the pure `source` helpers:
|
|
456
|
+
|
|
457
|
+
```ts
|
|
458
|
+
import { data, files, source } from '@oddington/sdk';
|
|
459
|
+
|
|
460
|
+
const file = await files.create({ file: statementCsv, name: 'October statement.csv',
|
|
461
|
+
path: 'Statements', storage: 'remote' });
|
|
462
|
+
const statement = source.file({ $ref: '_sources/statement_october', file,
|
|
463
|
+
locations: [source.location.os(file)] });
|
|
464
|
+
const changes = data.repository('general').changes();
|
|
465
|
+
changes.create({ ...statement, added: '2026-10-20' });
|
|
466
|
+
changes.create({ $ref: 'transactions/one',
|
|
467
|
+
sources: [source.csv.row(statement.$ref, parsedTransaction.recordPosition)] });
|
|
468
|
+
await changes.publish();
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
The caller's CSV parser supplies `recordPosition` from the retained statement:
|
|
472
|
+
positions count CSV records from 1, including the header when present. Expanded
|
|
473
|
+
Source occurrences expose `sourceRecord.$fragment` (for example `row=41`),
|
|
474
|
+
while their `$ref` remains the base Record ref. Exact Source reads and unexpanded
|
|
475
|
+
links retain their ordinary Data shapes.
|
|
476
|
+
|
|
477
|
+
`source.location.gmail({ connection, message, attachment, url? })` and
|
|
478
|
+
`source.location.dropbox({ connection, file, revision?, path?, url? })` build flat
|
|
479
|
+
Locations from successful provider responses. Use
|
|
480
|
+
`source.locations.merge(existingLocations, incomingLocations)` in an ordinary
|
|
481
|
+
guarded Data update. Known objects match by OS File ID, Gmail connection/message/
|
|
482
|
+
attachment, or Dropbox connection/File ID; newer Locations replace old path,
|
|
483
|
+
revision and URL facts. Distinct objects and custom provider values remain.
|
|
484
|
+
Helpers need no initialization and perform no I/O, choose no ref, and add no
|
|
485
|
+
changes. File retention and Data validation/publication remain explicit.
|
|
486
|
+
|
|
455
487
|
Read a named repository through the authenticated host context:
|
|
456
488
|
|
|
457
489
|
```ts
|
package/dist/browser.js
CHANGED
|
@@ -140,8 +140,8 @@ function serializable(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
|
140
140
|
try {
|
|
141
141
|
if (Array.isArray(value))
|
|
142
142
|
return array(value, "JSON array"), value.map((entry) => serializable(entry, ancestors));
|
|
143
|
-
let
|
|
144
|
-
return keys(
|
|
143
|
+
let source2 = object(value, "JSON input");
|
|
144
|
+
return keys(source2, Object.keys(source2), "JSON input"), Object.fromEntries(Object.entries(source2).map(([key, entry]) => [key, serializable(entry, ancestors)]));
|
|
145
145
|
} finally {
|
|
146
146
|
ancestors.delete(value);
|
|
147
147
|
}
|
|
@@ -235,9 +235,9 @@ function selection(value) {
|
|
|
235
235
|
return keys(input, ["source"], "selection"), validateResponseDefinition({ type: "selection", source: input.source });
|
|
236
236
|
}
|
|
237
237
|
function validateAuthoredSource(value) {
|
|
238
|
-
let
|
|
239
|
-
keys(
|
|
240
|
-
let options = array(
|
|
238
|
+
let source2 = object(value, "response definition");
|
|
239
|
+
keys(source2, ["type", "options", "suggestions", "search"], "response definition"), source2.type !== "authored" && fail("Expected authored options");
|
|
240
|
+
let options = array(source2.options, "options").map((entry) => {
|
|
241
241
|
let option = object(entry, "choice");
|
|
242
242
|
keys(option, ["value", "label", "description", "note"], "choice");
|
|
243
243
|
let note;
|
|
@@ -252,14 +252,14 @@ function validateAuthoredSource(value) {
|
|
|
252
252
|
...note ? { note } : {}
|
|
253
253
|
};
|
|
254
254
|
});
|
|
255
|
-
if (options.length || fail("Choices require at least one option"), new Set(options.map((option) => option.value)).size !== options.length && fail("Duplicate choice value"), Object.hasOwn(
|
|
256
|
-
let labels = object(
|
|
255
|
+
if (options.length || fail("Choices require at least one option"), new Set(options.map((option) => option.value)).size !== options.length && fail("Duplicate choice value"), Object.hasOwn(source2, "search") || Object.hasOwn(source2, "suggestions")) {
|
|
256
|
+
let labels = object(source2.search, "choice search");
|
|
257
257
|
keys(labels, ["triggerLabel", "placeholder", "emptyLabel"], "choice search");
|
|
258
258
|
let search = {
|
|
259
259
|
triggerLabel: text(labels.triggerLabel, "search trigger label"),
|
|
260
260
|
placeholder: text(labels.placeholder, "search placeholder"),
|
|
261
261
|
emptyLabel: text(labels.emptyLabel, "search empty label")
|
|
262
|
-
}, suggestions = array(
|
|
262
|
+
}, suggestions = array(source2.suggestions, "suggestions").map((value2) => id(value2, "suggestion value"));
|
|
263
263
|
return (suggestions.length > 8 || new Set(suggestions).size !== suggestions.length || suggestions.some((value2) => !options.some((option) => option.value === value2))) && fail("Search permits at most eight unique published suggestions"), { type: "authored", options, suggestions, search };
|
|
264
264
|
}
|
|
265
265
|
return options.length > 9 && fail("Choices require one to nine options"), { type: "authored", options };
|
|
@@ -271,22 +271,22 @@ function validateRecordReference(value) {
|
|
|
271
271
|
return (!/^[a-z0-9][a-z0-9._/-]{0,127}$/.test(repository) || /\.\.|\/\//.test(repository) || ref.length > 512 || !/^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)+$/.test(ref)) && fail("Invalid Record identity"), { repository, ref };
|
|
272
272
|
}
|
|
273
273
|
function validateRecordSource(value) {
|
|
274
|
-
let
|
|
275
|
-
keys(
|
|
276
|
-
let collection = object(
|
|
274
|
+
let source2 = object(value, "Record selection");
|
|
275
|
+
keys(source2, ["type", "collection", "refPrefix", "where", "display", "suggestions"], "Record selection"), source2.type !== "records" && fail("Expected Record options");
|
|
276
|
+
let collection = object(source2.collection, "collection");
|
|
277
277
|
keys(collection, ["repository", "name"], "collection");
|
|
278
278
|
let repository = validateRecordReference({ repository: collection.repository, ref: "records/example" }).repository, name2 = id(collection.name, "collection name");
|
|
279
279
|
/^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(name2) || fail("Invalid collection name");
|
|
280
|
-
let refPrefix =
|
|
280
|
+
let refPrefix = source2.refPrefix === void 0 ? void 0 : id(source2.refPrefix, "Record reference prefix");
|
|
281
281
|
refPrefix !== void 0 && (!refPrefix.endsWith("/") || refPrefix.length > 512 || !/^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)*\/$/.test(refPrefix)) && fail("Invalid Record reference prefix");
|
|
282
|
-
let where = object(
|
|
282
|
+
let where = object(source2.where ?? {}, "Record filter"), fieldName = (name3) => /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name3) && !["constructor", "prototype"].includes(name3);
|
|
283
283
|
for (let [name3, value2] of Object.entries(where))
|
|
284
284
|
(!fieldName(name3) || !(value2 === null || ["string", "number", "boolean"].includes(typeof value2)) || typeof value2 == "number" && !Number.isFinite(value2)) && fail("Record filters require scalar equality");
|
|
285
|
-
let display = object(
|
|
285
|
+
let display = object(source2.display, "Record display");
|
|
286
286
|
keys(display, ["labelFields"], "Record display");
|
|
287
287
|
let labelFields = distinctIds(display.labelFields, "label fields");
|
|
288
288
|
(labelFields.length > 2 || labelFields.some((name3) => !fieldName(name3))) && fail("Select one or two scalar label fields");
|
|
289
|
-
let suggestions = array(
|
|
289
|
+
let suggestions = array(source2.suggestions ?? [], "suggestions").map((value2) => {
|
|
290
290
|
let entry = object(value2, "suggestion");
|
|
291
291
|
keys(entry, ["record", "reason"], "suggestion");
|
|
292
292
|
let record4 = validateRecordReference(entry.record);
|
|
@@ -304,61 +304,61 @@ function validateRecordSource(value) {
|
|
|
304
304
|
function validateResponseDefinition(value) {
|
|
305
305
|
let definition = object(value, "response definition");
|
|
306
306
|
keys(definition, ["type", "source"], "response definition"), definition.type !== "selection" && fail("Expected a selection definition");
|
|
307
|
-
let
|
|
308
|
-
switch (
|
|
307
|
+
let source2 = object(definition.source, "option source");
|
|
308
|
+
switch (source2.type) {
|
|
309
309
|
case "authored":
|
|
310
|
-
return { type: "selection", source: validateAuthoredSource(
|
|
310
|
+
return { type: "selection", source: validateAuthoredSource(source2) };
|
|
311
311
|
case "records":
|
|
312
|
-
return { type: "selection", source: validateRecordSource(
|
|
312
|
+
return { type: "selection", source: validateRecordSource(source2) };
|
|
313
313
|
default:
|
|
314
314
|
return fail("Unsupported option source");
|
|
315
315
|
}
|
|
316
316
|
}
|
|
317
317
|
function handlerReference(value) {
|
|
318
|
-
let
|
|
319
|
-
return keys(
|
|
318
|
+
let source2 = object(value, "handler reference");
|
|
319
|
+
return keys(source2, ["id", "input"], "handler reference"), { id: id(source2.id, "handler ID"), input: serializable(source2.input) };
|
|
320
320
|
}
|
|
321
321
|
function defineHandler(value) {
|
|
322
|
-
let
|
|
323
|
-
keys(
|
|
322
|
+
let source2 = object(value, "handler");
|
|
323
|
+
keys(source2, ["id", "results", "run"], "handler");
|
|
324
324
|
let stable = (value2) => typeof value2 == "string" && /^[a-zA-Z0-9][a-zA-Z0-9_./-]{0,127}$/.test(value2);
|
|
325
|
-
stable(
|
|
326
|
-
let results =
|
|
327
|
-
return results && (results.length > 64 || results.some((result2) => !stable(result2))) && fail("Handler results must be stable IDs"), typeof
|
|
325
|
+
stable(source2.id) || fail("Handler ID must be stable");
|
|
326
|
+
let results = source2.results === void 0 ? void 0 : distinctIds(source2.results, "handler results", !1);
|
|
327
|
+
return results && (results.length > 64 || results.some((result2) => !stable(result2))) && fail("Handler results must be stable IDs"), typeof source2.run != "function" && fail("Handler requires a run function"), Object.freeze({ id: value.id, ...results === void 0 ? {} : { results: Object.freeze(results.sort()) }, run: value.run });
|
|
328
328
|
}
|
|
329
329
|
function respond(handler, input) {
|
|
330
330
|
return defineHandler(handler), handlerReference({ id: handler.id, input });
|
|
331
331
|
}
|
|
332
332
|
function question(value) {
|
|
333
|
-
let
|
|
334
|
-
keys(
|
|
335
|
-
let to = personReference(
|
|
333
|
+
let source2 = object(value, "question");
|
|
334
|
+
keys(source2, ["id", "to", "allowedResponders", "prompt", "instructions", "response", "handler"], "question");
|
|
335
|
+
let to = personReference(source2.to, "question assignee"), allowedResponders = source2.allowedResponders === void 0 ? [to] : distinctPeople(source2.allowedResponders, "allowed responders");
|
|
336
336
|
return allowedResponders.includes(to) || fail("Allowed responders must include the assignee"), {
|
|
337
|
-
id: id(
|
|
337
|
+
id: id(source2.id, "question ID"),
|
|
338
338
|
to,
|
|
339
339
|
allowedResponders,
|
|
340
|
-
prompt: text(
|
|
341
|
-
...
|
|
342
|
-
response: validateResponseDefinition(
|
|
343
|
-
...Object.hasOwn(
|
|
340
|
+
prompt: text(source2.prompt, "question prompt"),
|
|
341
|
+
...source2.instructions === void 0 ? {} : { instructions: text(source2.instructions, "instructions") },
|
|
342
|
+
response: validateResponseDefinition(source2.response),
|
|
343
|
+
...Object.hasOwn(source2, "handler") ? { handler: handlerReference(source2.handler) } : {}
|
|
344
344
|
};
|
|
345
345
|
}
|
|
346
|
-
function presentation(
|
|
347
|
-
let views =
|
|
346
|
+
function presentation(source2) {
|
|
347
|
+
let views = source2.views === void 0 ? [] : array(source2.views, "views").map((entry) => {
|
|
348
348
|
let view = object(entry, "view");
|
|
349
349
|
return keys(view, ["id", "view", "input"], "view"), { id: id(view.id, "view ID"), view: id(view.view, "view name"), input: serializable(view.input) };
|
|
350
350
|
});
|
|
351
351
|
new Set(views.map((view) => view.id)).size !== views.length && fail("Duplicate view ID");
|
|
352
|
-
let body =
|
|
352
|
+
let body = source2.body === void 0 ? [] : array(source2.body, "body").map(validateBlock);
|
|
353
353
|
for (let block2 of body) {
|
|
354
354
|
let targets = block2.kind === "record" ? [block2.view] : block2.kind === "records" ? [block2.view, ...block2.records.map((record4) => record4.view)] : [];
|
|
355
355
|
for (let target of targets) target !== void 0 && !views.some((view) => view.id === target) && fail(`Unknown Block View target: ${target}`);
|
|
356
356
|
}
|
|
357
|
-
return { title: text(
|
|
357
|
+
return { title: text(source2.title, "title"), description: text(source2.description, "description"), views, body };
|
|
358
358
|
}
|
|
359
359
|
function validatePublication(value) {
|
|
360
|
-
let
|
|
361
|
-
|
|
360
|
+
let source2 = object(value, "publication");
|
|
361
|
+
source2.kind !== "ask" && source2.kind !== "digest" && fail("Publication requires an explicit kind"), keys(source2, [
|
|
362
362
|
"kind",
|
|
363
363
|
"title",
|
|
364
364
|
"description",
|
|
@@ -366,25 +366,25 @@ function validatePublication(value) {
|
|
|
366
366
|
"views",
|
|
367
367
|
"body",
|
|
368
368
|
"notifyImmediately",
|
|
369
|
-
...
|
|
370
|
-
], "publication"),
|
|
371
|
-
let itemPresentation = { ...presentation(
|
|
372
|
-
if (new Set(linkedAsks).size !== linkedAsks.length && fail("Ask belongs to more than one problem"),
|
|
369
|
+
...source2.kind === "ask" ? ["questions", "tags", "recordRefs"] : []
|
|
370
|
+
], "publication"), source2.notifyImmediately !== void 0 && typeof source2.notifyImmediately != "boolean" && fail("notifyImmediately must be a boolean");
|
|
371
|
+
let itemPresentation = { ...presentation(source2), ...source2.notifyImmediately === void 0 ? {} : { notifyImmediately: source2.notifyImmediately } }, linkedAsks = (itemPresentation.body ?? []).flatMap((block2) => block2.kind === "asks" ? block2.asks : []);
|
|
372
|
+
if (new Set(linkedAsks).size !== linkedAsks.length && fail("Ask belongs to more than one problem"), source2.kind === "digest") return {
|
|
373
373
|
kind: "digest",
|
|
374
374
|
...itemPresentation,
|
|
375
|
-
recipients: distinctPeople(
|
|
375
|
+
recipients: distinctPeople(source2.recipients, "digest recipients")
|
|
376
376
|
};
|
|
377
377
|
itemPresentation.body?.some((block2) => block2.kind === "asks") && fail("Asks Blocks belong to Digests");
|
|
378
|
-
let questions = array(
|
|
378
|
+
let questions = array(source2.questions === void 0 ? [] : source2.questions, "questions").map((value2) => question(value2));
|
|
379
379
|
new Set(questions.map((entry) => entry.id)).size !== questions.length && fail("Duplicate question ID");
|
|
380
|
-
let extra =
|
|
380
|
+
let extra = source2.recipients === void 0 ? [] : distinctPeople(source2.recipients, "recipients", !1);
|
|
381
381
|
!questions.length && !extra.length && fail("Ask requires at least one recipient");
|
|
382
|
-
let tags = array(
|
|
382
|
+
let tags = array(source2.tags === void 0 ? [] : source2.tags, "Ask tags").map((value2) => {
|
|
383
383
|
let tag = text(value2, "Ask tag");
|
|
384
384
|
return new TextEncoder().encode(tag).byteLength > 64 && fail("Ask tag exceeds 64 UTF-8 bytes"), tag;
|
|
385
385
|
});
|
|
386
386
|
(tags.length > 32 || new Set(tags).size !== tags.length) && fail("Ask tags exceed bounds or contain duplicates");
|
|
387
|
-
let recordRefs = array(
|
|
387
|
+
let recordRefs = array(source2.recordRefs === void 0 ? [] : source2.recordRefs, "Ask Record references").map((value2) => {
|
|
388
388
|
let row = object(value2, "Ask Record reference");
|
|
389
389
|
keys(row, ["repository", "id"], "Ask Record reference");
|
|
390
390
|
let { repository, ref } = validateRecordReference({ repository: row.repository, ref: row.id });
|
|
@@ -400,25 +400,25 @@ function validatePublication(value) {
|
|
|
400
400
|
};
|
|
401
401
|
}
|
|
402
402
|
function continueAsk(value) {
|
|
403
|
-
let
|
|
404
|
-
return keys(
|
|
403
|
+
let source2 = object(value, "continueAsk");
|
|
404
|
+
return keys(source2, [], "continueAsk"), { type: "continue" };
|
|
405
405
|
}
|
|
406
406
|
function resolution(value) {
|
|
407
|
-
let
|
|
408
|
-
return keys(
|
|
409
|
-
evidence: array(
|
|
407
|
+
let source2 = object(value, "resolution");
|
|
408
|
+
return keys(source2, ["outcome", "evidence"], "resolution"), { outcome: text(source2.outcome, "outcome"), ...source2.evidence === void 0 ? {} : {
|
|
409
|
+
evidence: array(source2.evidence, "evidence").map((entry) => serializable(entry))
|
|
410
410
|
} };
|
|
411
411
|
}
|
|
412
412
|
function resolveAsk(value) {
|
|
413
413
|
return { type: "resolve", ...resolution(value) };
|
|
414
414
|
}
|
|
415
415
|
function validateResolution(value) {
|
|
416
|
-
let
|
|
417
|
-
return keys(
|
|
418
|
-
expectedRevision:
|
|
416
|
+
let source2 = object(value, "published resolution");
|
|
417
|
+
return keys(source2, ["expectedRevision", "outcome", "evidence"], "published resolution"), (!Number.isSafeInteger(source2.expectedRevision) || source2.expectedRevision < 1) && fail("Expected revision must be a positive integer"), {
|
|
418
|
+
expectedRevision: source2.expectedRevision,
|
|
419
419
|
...resolution({
|
|
420
|
-
outcome:
|
|
421
|
-
...
|
|
420
|
+
outcome: source2.outcome,
|
|
421
|
+
...source2.evidence === void 0 ? {} : { evidence: source2.evidence }
|
|
422
422
|
})
|
|
423
423
|
};
|
|
424
424
|
}
|
|
@@ -429,20 +429,20 @@ function publicationRequestKey(value) {
|
|
|
429
429
|
function createInboxPublisher(transport) {
|
|
430
430
|
return {
|
|
431
431
|
async publishAsk(value, options) {
|
|
432
|
-
let
|
|
433
|
-
keys(
|
|
432
|
+
let source2 = object(value, "ask");
|
|
433
|
+
keys(source2, ["title", "description", "recipients", "views", "body", "questions", "notifyImmediately", "tags", "recordRefs"], "ask");
|
|
434
434
|
let result2 = await transport.publish({
|
|
435
435
|
requestKey: publicationRequestKey(options),
|
|
436
|
-
item: validatePublication({ ...
|
|
436
|
+
item: validatePublication({ ...source2, kind: "ask" })
|
|
437
437
|
});
|
|
438
438
|
return id(result2.id, "published ask ID"), (!("revision" in result2) || !Number.isSafeInteger(result2.revision) || result2.revision !== 1) && fail("Initial ask publication must return revision 1"), { id: result2.id, revision: result2.revision };
|
|
439
439
|
},
|
|
440
440
|
async publishDigest(value, options) {
|
|
441
|
-
let
|
|
442
|
-
keys(
|
|
441
|
+
let source2 = object(value, "digest");
|
|
442
|
+
keys(source2, ["title", "description", "recipients", "views", "body", "notifyImmediately"], "digest");
|
|
443
443
|
let result2 = await transport.publish({
|
|
444
444
|
requestKey: publicationRequestKey(options),
|
|
445
|
-
item: validatePublication({ ...
|
|
445
|
+
item: validatePublication({ ...source2, kind: "digest" })
|
|
446
446
|
});
|
|
447
447
|
return { id: id(result2.id, "published digest ID") };
|
|
448
448
|
},
|
|
@@ -1406,11 +1406,11 @@ async function hostedContent(url, init2, parent, upstream = fetch, check = async
|
|
|
1406
1406
|
}
|
|
1407
1407
|
if (!response2.body)
|
|
1408
1408
|
return detach(), response2;
|
|
1409
|
-
let
|
|
1409
|
+
let source2 = response2.body, reader, settled = !1, output, cancel = async (reason) => {
|
|
1410
1410
|
if (!settled) {
|
|
1411
1411
|
settled = !0, detach(), delivery.signal.removeEventListener("abort", stop), delivery.abort(reason);
|
|
1412
1412
|
try {
|
|
1413
|
-
await (reader ? reader.cancel(reason) :
|
|
1413
|
+
await (reader ? reader.cancel(reason) : source2.cancel(reason));
|
|
1414
1414
|
} catch (error) {
|
|
1415
1415
|
if (error !== delivery.signal.reason && !(error instanceof Error && error.name === "AbortError")) throw error;
|
|
1416
1416
|
} finally {
|
|
@@ -1429,7 +1429,7 @@ async function hostedContent(url, init2, parent, upstream = fetch, check = async
|
|
|
1429
1429
|
async pull(controller) {
|
|
1430
1430
|
try {
|
|
1431
1431
|
if (await check(), settled) return;
|
|
1432
|
-
reader ??=
|
|
1432
|
+
reader ??= source2.getReader();
|
|
1433
1433
|
let { done, value } = await reader.read();
|
|
1434
1434
|
if (await check(), settled) return;
|
|
1435
1435
|
done ? (settled = !0, detach(), delivery.signal.removeEventListener("abort", stop), reader.releaseLock(), controller.close()) : controller.enqueue(value);
|
|
@@ -2192,6 +2192,68 @@ function validCreatePath(value) {
|
|
|
2192
2192
|
return value === value.trim() && value.endsWith(".md") && !value.startsWith("/") && value.split("/").every((segment) => !!segment && ![".", ".."].includes(segment) && /^[a-zA-Z0-9_.-]+$/.test(segment));
|
|
2193
2193
|
}
|
|
2194
2194
|
|
|
2195
|
+
function locationIdentity(location) {
|
|
2196
|
+
let coordinates = location.provider === "os" ? [location.file] : location.provider === "gmail" ? [location.connection, location.message, location.attachment] : location.provider === "dropbox" ? [location.connection, location.file] : void 0;
|
|
2197
|
+
if (coordinates?.every((value) => typeof value == "string" && value.length > 0))
|
|
2198
|
+
return JSON.stringify([location.provider, ...coordinates]);
|
|
2199
|
+
}
|
|
2200
|
+
var source = {
|
|
2201
|
+
file(input) {
|
|
2202
|
+
return {
|
|
2203
|
+
$ref: input.$ref,
|
|
2204
|
+
type: "source",
|
|
2205
|
+
kind: "file",
|
|
2206
|
+
filename: input.file.name,
|
|
2207
|
+
media_type: input.file.mediaType,
|
|
2208
|
+
size_bytes: input.file.size,
|
|
2209
|
+
sha256: input.file.sha256,
|
|
2210
|
+
locations: input.locations.map((location) => ({ ...location }))
|
|
2211
|
+
};
|
|
2212
|
+
},
|
|
2213
|
+
location: {
|
|
2214
|
+
os(file2) {
|
|
2215
|
+
return { provider: "os", file: file2.id };
|
|
2216
|
+
},
|
|
2217
|
+
gmail(input) {
|
|
2218
|
+
return {
|
|
2219
|
+
provider: "gmail",
|
|
2220
|
+
connection: input.connection,
|
|
2221
|
+
message: input.message,
|
|
2222
|
+
attachment: input.attachment,
|
|
2223
|
+
...input.url === void 0 ? {} : { url: input.url }
|
|
2224
|
+
};
|
|
2225
|
+
},
|
|
2226
|
+
dropbox(input) {
|
|
2227
|
+
return {
|
|
2228
|
+
provider: "dropbox",
|
|
2229
|
+
connection: input.connection,
|
|
2230
|
+
file: input.file,
|
|
2231
|
+
...input.revision === void 0 ? {} : { revision: input.revision },
|
|
2232
|
+
...input.path === void 0 ? {} : { path: input.path },
|
|
2233
|
+
...input.url === void 0 ? {} : { url: input.url }
|
|
2234
|
+
};
|
|
2235
|
+
}
|
|
2236
|
+
},
|
|
2237
|
+
locations: {
|
|
2238
|
+
merge(existing, incoming) {
|
|
2239
|
+
let merged = existing.map((location) => ({ ...location }));
|
|
2240
|
+
for (let location of incoming) {
|
|
2241
|
+
let identity = locationIdentity(location), index = identity === void 0 ? -1 : merged.findIndex((value) => locationIdentity(value) === identity);
|
|
2242
|
+
index < 0 ? merged.push({ ...location }) : merged[index] = { ...location };
|
|
2243
|
+
}
|
|
2244
|
+
return merged;
|
|
2245
|
+
}
|
|
2246
|
+
},
|
|
2247
|
+
csv: {
|
|
2248
|
+
/** One-based CSV record position; a present header is record 1. */
|
|
2249
|
+
row(baseRef, row) {
|
|
2250
|
+
if (!validRecordRef(baseRef)) throw new TypeError("CSV row links require a base Record ref");
|
|
2251
|
+
if (!Number.isSafeInteger(row) || row < 1) throw new RangeError("CSV row must be a positive safe integer");
|
|
2252
|
+
return `${baseRef}#row=${row}`;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
};
|
|
2256
|
+
|
|
2195
2257
|
var InboxOperationError = class extends Error {
|
|
2196
2258
|
constructor(status, reason) {
|
|
2197
2259
|
super(reason === "conflict" ? "This question already has an accepted answer" : reason === "unavailable" ? "Inbox request unavailable. Retry the same action." : reason === "invalid_input" ? "Invalid Inbox request" : "Inbox access unavailable");
|
|
@@ -2268,10 +2330,10 @@ function recordReference(value) {
|
|
|
2268
2330
|
function responseDefinition(value) {
|
|
2269
2331
|
let definition = object4(value);
|
|
2270
2332
|
keys3(definition, ["type", "source"]), assert(definition.type === "selection");
|
|
2271
|
-
let
|
|
2272
|
-
if (
|
|
2273
|
-
keys3(
|
|
2274
|
-
let options = array2(
|
|
2333
|
+
let source2 = object4(definition.source);
|
|
2334
|
+
if (source2.type === "authored") {
|
|
2335
|
+
keys3(source2, ["type", "options", "suggestions", "search"], ["type", "options"]);
|
|
2336
|
+
let options = array2(source2.options);
|
|
2275
2337
|
assert(options.length > 0);
|
|
2276
2338
|
let values = options.map((value2) => {
|
|
2277
2339
|
let option = object4(value2);
|
|
@@ -2281,24 +2343,24 @@ function responseDefinition(value) {
|
|
|
2281
2343
|
}
|
|
2282
2344
|
return option.value;
|
|
2283
2345
|
});
|
|
2284
|
-
if (assert(new Set(values).size === values.length), "search" in
|
|
2285
|
-
let search = object4(
|
|
2346
|
+
if (assert(new Set(values).size === values.length), "search" in source2 || "suggestions" in source2) {
|
|
2347
|
+
let search = object4(source2.search);
|
|
2286
2348
|
keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text4(search.triggerLabel) && text4(search.placeholder) && text4(search.emptyLabel));
|
|
2287
|
-
let suggestions2 = array2(
|
|
2349
|
+
let suggestions2 = array2(source2.suggestions);
|
|
2288
2350
|
assert(suggestions2.length <= 8 && suggestions2.every((value2) => text4(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
|
|
2289
2351
|
} else assert(options.length <= 9);
|
|
2290
2352
|
return;
|
|
2291
2353
|
}
|
|
2292
|
-
assert(
|
|
2293
|
-
let collection = object4(
|
|
2294
|
-
keys3(collection, ["repository", "name"]), recordReference({ repository: collection.repository, ref: "records/example" }), assert(text4(collection.name) && /^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(collection.name)), "refPrefix" in
|
|
2295
|
-
let where = object4(
|
|
2354
|
+
assert(source2.type === "records"), keys3(source2, ["type", "collection", "refPrefix", "where", "display", "suggestions"], ["type", "collection", "display"]);
|
|
2355
|
+
let collection = object4(source2.collection);
|
|
2356
|
+
keys3(collection, ["repository", "name"]), recordReference({ repository: collection.repository, ref: "records/example" }), assert(text4(collection.name) && /^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(collection.name)), "refPrefix" in source2 && assert(text4(source2.refPrefix) && source2.refPrefix.length <= 512 && /^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)*\/$/.test(source2.refPrefix));
|
|
2357
|
+
let where = object4(source2.where ?? {});
|
|
2296
2358
|
assert(Object.entries(where).every(([name2, value2]) => /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name2) && !["constructor", "prototype"].includes(name2) && (value2 === null || typeof value2 == "string" || typeof value2 == "boolean" || typeof value2 == "number" && Number.isFinite(value2))));
|
|
2297
|
-
let display = object4(
|
|
2359
|
+
let display = object4(source2.display);
|
|
2298
2360
|
keys3(display, ["labelFields"]);
|
|
2299
2361
|
let labels = array2(display.labelFields);
|
|
2300
2362
|
assert(labels.length > 0 && labels.length <= 2 && new Set(labels).size === labels.length && labels.every((value2) => text4(value2) && /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(value2)));
|
|
2301
|
-
let suggestions = array2(
|
|
2363
|
+
let suggestions = array2(source2.suggestions ?? []), refs = suggestions.map((value2) => {
|
|
2302
2364
|
let suggestion = object4(value2);
|
|
2303
2365
|
keys3(suggestion, ["record", "reason"], ["record"]);
|
|
2304
2366
|
let record4 = recordReference(suggestion.record);
|
|
@@ -3017,16 +3079,16 @@ async function send2(operation2, input, admitted) {
|
|
|
3017
3079
|
}), unavailable3();
|
|
3018
3080
|
if (operation2 === "files.read") {
|
|
3019
3081
|
if (!response2.body) throw unavailable3();
|
|
3020
|
-
let
|
|
3082
|
+
let source2 = response2.body, reader, size = 0, cancel = async (reason) => {
|
|
3021
3083
|
try {
|
|
3022
|
-
await (reader ? reader.cancel(reason) :
|
|
3084
|
+
await (reader ? reader.cancel(reason) : source2.cancel(reason));
|
|
3023
3085
|
} finally {
|
|
3024
3086
|
reader?.releaseLock();
|
|
3025
3087
|
}
|
|
3026
3088
|
}, body = new ReadableStream({
|
|
3027
3089
|
async pull(controller) {
|
|
3028
3090
|
try {
|
|
3029
|
-
check(), reader ??=
|
|
3091
|
+
check(), reader ??= source2.getReader();
|
|
3030
3092
|
let next = await reader.read();
|
|
3031
3093
|
if (check(), next.done) {
|
|
3032
3094
|
reader.releaseLock(), controller.close();
|
|
@@ -3126,8 +3188,8 @@ var inbox = {
|
|
|
3126
3188
|
};
|
|
3127
3189
|
|
|
3128
3190
|
var sources = /* @__PURE__ */ new WeakMap();
|
|
3129
|
-
function registerBrowserAuth(handle2,
|
|
3130
|
-
sources.set(handle2,
|
|
3191
|
+
function registerBrowserAuth(handle2, source2) {
|
|
3192
|
+
sources.set(handle2, source2);
|
|
3131
3193
|
}
|
|
3132
3194
|
function browserAuthSource(handle2) {
|
|
3133
3195
|
return sources.get(handle2);
|
|
@@ -3867,7 +3929,7 @@ function validateFileAddOptions(value) {
|
|
|
3867
3929
|
var PREPARED_RECORD_INPUT_LIMIT = 64 * 1024 * 1024;
|
|
3868
3930
|
|
|
3869
3931
|
function routineDataEnvelope(command) {
|
|
3870
|
-
return "
|
|
3932
|
+
return "apply" in command ? { operation: "changes.publish", captured: command.apply } : { operation: "changes.publish", request: command };
|
|
3871
3933
|
}
|
|
3872
3934
|
|
|
3873
3935
|
function routinePublicationClient2(options = {}) {
|
|
@@ -3970,5 +4032,6 @@ export {
|
|
|
3970
4032
|
richTextBlock,
|
|
3971
4033
|
routinePublicationClient2 as routinePublicationClient,
|
|
3972
4034
|
schema,
|
|
3973
|
-
selection
|
|
4035
|
+
selection,
|
|
4036
|
+
source
|
|
3974
4037
|
};
|