@oddington/sdk 0.1.44 → 0.1.46
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 +71 -18
- package/dist/browser.js +414 -140
- package/dist/index.js +3 -3
- package/dist/types/packages/sdk/src/data-schema-types.d.ts +3 -3
- package/dist/types/packages/sdk/src/public.d.ts +3 -3
- package/dist/types/shared/connections.d.ts +81 -0
- package/dist/types/shared/data-contract.d.ts +4 -22
- package/dist/types/shared/data-repositories.d.ts +23 -0
- package/dist/types/shared/inbox-contract.d.ts +15 -3
- package/dist/types/shared/inbox-member-contract.d.ts +14 -3
- package/dist/types/shared/inbox-member-types.d.ts +7 -2
- package/dist/types/shared/record-selection.d.ts +11 -1
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -319,6 +319,52 @@ function validateRoutineSchemaValue(schema2, value, rejected) {
|
|
|
319
319
|
check(schema2, value, "$");
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
function validDropboxRootPath(value) {
|
|
323
|
+
return typeof value == "string" && value.length <= 2048 && value.startsWith("/") && !/[\\\x00-\x1f\x7f]/.test(value) && value.slice(1).split("/").every((segment) => segment.length > 0 && segment.trim() === segment && segment !== "." && segment !== "..");
|
|
324
|
+
}
|
|
325
|
+
function validMicrosoftId(value) {
|
|
326
|
+
return typeof value == "string" && /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(value);
|
|
327
|
+
}
|
|
328
|
+
function validMicrosoftMailbox(value) {
|
|
329
|
+
return typeof value == "string" && value.length <= 254 && /^[^\s@/?#\\\x00-\x1f\x7f]+@[^\s@/?#\\\x00-\x1f\x7f]+\.[^\s@/?#\\\x00-\x1f\x7f]+$/.test(value);
|
|
330
|
+
}
|
|
331
|
+
function sharePointHost(value) {
|
|
332
|
+
return /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.sharepoint\.com$/.test(value);
|
|
333
|
+
}
|
|
334
|
+
function canonicalSharePointSiteUrl(value) {
|
|
335
|
+
if (!(typeof value != "string" || value.length > 2048 || /[\s\\?#\x00-\x1f\x7f]/.test(value) || !/^https:\/\/[^/:@]+(?:\/|$)/i.test(value)))
|
|
336
|
+
try {
|
|
337
|
+
let url = new URL(value);
|
|
338
|
+
if (url.protocol !== "https:" || !sharePointHost(url.hostname) || url.username || url.password || url.port) return;
|
|
339
|
+
let rawPath = value.replace(/^https:\/\/[^/]+/i, "") || "/", path = rawPath.endsWith("/") ? rawPath.slice(0, -1) : rawPath, segments = path.slice(1).split("/");
|
|
340
|
+
if (path && segments.some((segment) => !segment)) return;
|
|
341
|
+
let encoded = path ? segments.map((segment) => {
|
|
342
|
+
let decoded = decodeURIComponent(segment);
|
|
343
|
+
if (decoded === "." || decoded === ".." || /[/%\\?#\x00-\x1f\x7f]/.test(decoded)) throw new Error();
|
|
344
|
+
return encodeURIComponent(decoded);
|
|
345
|
+
}).join("/") : "", canonical = `https://${url.hostname}/${encoded}`;
|
|
346
|
+
return canonical.length <= 2048 ? canonical : void 0;
|
|
347
|
+
} catch {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function validSharePointSiteId(value, siteUrl) {
|
|
352
|
+
if (typeof value != "string" || value.length > 512) return !1;
|
|
353
|
+
let [host, collection, site, extra] = value.split(",");
|
|
354
|
+
return extra === void 0 && host === new URL(siteUrl).hostname && validMicrosoftId(collection) && validMicrosoftId(site);
|
|
355
|
+
}
|
|
356
|
+
function validGoogleScopes(value) {
|
|
357
|
+
return Array.isArray(value) && value.length > 0 && value.length <= 32 && value.every((scope) => typeof scope == "string" && scope.length <= 256 && /^(https:\/\/www\.googleapis\.com\/auth\/[A-Za-z0-9._-]+|https:\/\/mail\.google\.com\/|openid|email|profile)$/.test(scope)) && new Set(value).size === value.length;
|
|
358
|
+
}
|
|
359
|
+
var DROPBOX_FILE_SCOPES = ["account_info.read", "files.metadata.read", "files.content.read", "files.content.write"];
|
|
360
|
+
function validDropboxFileScopes(value) {
|
|
361
|
+
return Array.isArray(value) && value.length === DROPBOX_FILE_SCOPES.length && new Set(value).size === value.length && DROPBOX_FILE_SCOPES.every((scope) => value.includes(scope));
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function validDataRepositoryName(value) {
|
|
365
|
+
return typeof value == "string" && /^[a-z0-9][a-z0-9._-]{0,127}$/.test(value) && !value.includes("..");
|
|
366
|
+
}
|
|
367
|
+
|
|
322
368
|
var InboxContractError = class extends Error {
|
|
323
369
|
constructor(message2) {
|
|
324
370
|
super(message2), this.name = "InboxContractError";
|
|
@@ -575,9 +621,26 @@ function defineHandler(value) {
|
|
|
575
621
|
function respond(handler, input) {
|
|
576
622
|
return defineHandler(handler), handlerReference({ id: handler.id, input });
|
|
577
623
|
}
|
|
624
|
+
function recordRequirements(value) {
|
|
625
|
+
let source2 = object(value, "Record requirements");
|
|
626
|
+
keys(source2, ["repository", "records"], "Record requirements"), validDataRepositoryName(source2.repository) || fail("Invalid requirements repository");
|
|
627
|
+
let repository = source2.repository, records = array(source2.records, "required Records").map((entry) => {
|
|
628
|
+
let row = object(entry, "required Record");
|
|
629
|
+
keys(row, ["ref", "version"], "required Record");
|
|
630
|
+
let { ref } = validateRecordReference({ repository, ref: row.ref });
|
|
631
|
+
return (typeof row.version != "string" || !row.version.length || row.version.length > 512) && fail("Invalid required Record version"), { ref, version: row.version };
|
|
632
|
+
});
|
|
633
|
+
return new Set(records.map((record4) => record4.ref)).size !== records.length && fail("Duplicate required Record"), { repository, records };
|
|
634
|
+
}
|
|
635
|
+
function requireRecords(repository, records) {
|
|
636
|
+
return recordRequirements({ repository, records: array(records, "required Records").map((entry) => {
|
|
637
|
+
let record4 = object(entry, "Data Record");
|
|
638
|
+
return { ref: record4.$ref, version: record4.$version };
|
|
639
|
+
}) });
|
|
640
|
+
}
|
|
578
641
|
function question(value) {
|
|
579
642
|
let source2 = object(value, "question");
|
|
580
|
-
keys(source2, ["id", "to", "allowedResponders", "prompt", "instructions", "response", "handler"], "question");
|
|
643
|
+
keys(source2, ["id", "to", "allowedResponders", "prompt", "instructions", "response", "handler", "requirements"], "question");
|
|
581
644
|
let to = personReference(source2.to, "question assignee"), allowedResponders = source2.allowedResponders === void 0 ? [to] : distinctPeople(source2.allowedResponders, "allowed responders");
|
|
582
645
|
return allowedResponders.includes(to) || fail("Allowed responders must include the assignee"), {
|
|
583
646
|
id: id(source2.id, "question ID"),
|
|
@@ -586,7 +649,8 @@ function question(value) {
|
|
|
586
649
|
prompt: text(source2.prompt, "question prompt"),
|
|
587
650
|
...source2.instructions === void 0 ? {} : { instructions: text(source2.instructions, "instructions") },
|
|
588
651
|
response: validateResponseDefinition(source2.response),
|
|
589
|
-
...Object.hasOwn(source2, "handler") ? { handler: handlerReference(source2.handler) } : {}
|
|
652
|
+
...Object.hasOwn(source2, "handler") ? { handler: handlerReference(source2.handler) } : {},
|
|
653
|
+
...Object.hasOwn(source2, "requirements") ? { requirements: recordRequirements(source2.requirements) } : {}
|
|
590
654
|
};
|
|
591
655
|
}
|
|
592
656
|
function presentation(source2) {
|
|
@@ -1274,6 +1338,7 @@ var fieldProblems = ["unknown", "missing", "invalid", "source_schema"], reasons
|
|
|
1274
1338
|
boolean: "a boolean",
|
|
1275
1339
|
date: "a date in YYYY-MM-DD format",
|
|
1276
1340
|
const: "the constant declared in the schema",
|
|
1341
|
+
datetime: "a UTC date and time in YYYY-MM-DDTHH:mm:ss.sssZ format, for example 2026-09-15T14:30:00.000Z",
|
|
1277
1342
|
enum: "one of the choices declared in the schema",
|
|
1278
1343
|
link: "a link to an existing record of an allowed type",
|
|
1279
1344
|
object: "an object matching the schema",
|
|
@@ -1517,14 +1582,43 @@ function captureRecordsReadRefs(value) {
|
|
|
1517
1582
|
}
|
|
1518
1583
|
function captureRecordsReadOptions(value) {
|
|
1519
1584
|
if (value === void 0) return {};
|
|
1520
|
-
let row;
|
|
1521
1585
|
try {
|
|
1522
|
-
|
|
1586
|
+
historyProperties(value);
|
|
1523
1587
|
} catch {
|
|
1524
1588
|
throw new DataOperationError("invalid_query");
|
|
1525
1589
|
}
|
|
1526
|
-
if (!value || typeof value != "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value)) || Reflect.ownKeys(value).
|
|
1527
|
-
|
|
1590
|
+
if (!value || typeof value != "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value)) || Reflect.ownKeys(value).length)
|
|
1591
|
+
throw new DataOperationError("invalid_query");
|
|
1592
|
+
return {};
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
function capture3(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
|
|
1596
|
+
if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return value;
|
|
1597
|
+
if (!value || typeof value != "object" || ancestors.has(value) || depth > 32) throw new DataOperationError("invalid_query");
|
|
1598
|
+
ancestors.add(value);
|
|
1599
|
+
try {
|
|
1600
|
+
return Array.isArray(value) ? historyArray(value).map((item) => capture3(item, ancestors, depth + 1)) : Object.fromEntries(Object.entries(historyProperties(value)).map(([key, descriptor]) => [key, capture3(descriptor.value, ancestors, depth + 1)]));
|
|
1601
|
+
} finally {
|
|
1602
|
+
ancestors.delete(value);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
function captureRecordsAll(query, options) {
|
|
1606
|
+
let invalid9 = () => {
|
|
1607
|
+
throw new DataOperationError("invalid_query");
|
|
1608
|
+
};
|
|
1609
|
+
try {
|
|
1610
|
+
let properties = historyProperties(options), maxRecords = properties.maxRecords?.value;
|
|
1611
|
+
if (Object.keys(properties).join(",") !== "maxRecords" || !Number.isSafeInteger(maxRecords) || maxRecords < 1) return invalid9();
|
|
1612
|
+
let detached = capture3(query), selections = historyProperties(detached);
|
|
1613
|
+
if (Object.keys(selections).length < 1 || Object.keys(selections).length > 16) return invalid9();
|
|
1614
|
+
for (let selection2 of Object.values(selections)) {
|
|
1615
|
+
let fields5 = historyProperties(selection2.value);
|
|
1616
|
+
if (fields5.$ && Object.hasOwn(historyProperties(fields5.$.value), "after")) return invalid9();
|
|
1617
|
+
}
|
|
1618
|
+
return { query: detached, maxRecords };
|
|
1619
|
+
} catch {
|
|
1620
|
+
return invalid9();
|
|
1621
|
+
}
|
|
1528
1622
|
}
|
|
1529
1623
|
|
|
1530
1624
|
function validRecordBody(value) {
|
|
@@ -1711,19 +1805,19 @@ var invalid6 = () => {
|
|
|
1711
1805
|
}, unavailable = () => {
|
|
1712
1806
|
throw new DataOperationError("unavailable");
|
|
1713
1807
|
}, text2 = (value) => typeof value == "string" && value.length > 0;
|
|
1714
|
-
function
|
|
1808
|
+
function capture4(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
|
|
1715
1809
|
if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return value;
|
|
1716
1810
|
if (!value || typeof value != "object" || ancestors.has(value) || depth > 32) return invalid6();
|
|
1717
1811
|
ancestors.add(value);
|
|
1718
1812
|
try {
|
|
1719
|
-
return Array.isArray(value) ? historyArray(value).map((item) =>
|
|
1813
|
+
return Array.isArray(value) ? historyArray(value).map((item) => capture4(item, ancestors, depth + 1)) : Object.fromEntries(Object.entries(historyProperties(value)).map(([key, descriptor]) => [key, capture4(descriptor.value, ancestors, depth + 1)]));
|
|
1720
1814
|
} finally {
|
|
1721
1815
|
ancestors.delete(value);
|
|
1722
1816
|
}
|
|
1723
1817
|
}
|
|
1724
1818
|
function recordPagination(queryRecords) {
|
|
1725
1819
|
function pages(query) {
|
|
1726
|
-
let captured =
|
|
1820
|
+
let captured = capture4(query), names = Object.keys(historyProperties(captured));
|
|
1727
1821
|
for (let name2 of names) {
|
|
1728
1822
|
let selection2 = historyProperties(captured[name2]);
|
|
1729
1823
|
if (Object.hasOwn(selection2, "$")) {
|
|
@@ -1735,7 +1829,6 @@ function recordPagination(queryRecords) {
|
|
|
1735
1829
|
async function* iterate() {
|
|
1736
1830
|
let state = new Map(names.map((name2) => [name2, {
|
|
1737
1831
|
seen: /* @__PURE__ */ new Set(),
|
|
1738
|
-
total: 0,
|
|
1739
1832
|
count: void 0,
|
|
1740
1833
|
next: void 0
|
|
1741
1834
|
}])), active2 = names, version;
|
|
@@ -1745,11 +1838,11 @@ function recordPagination(queryRecords) {
|
|
|
1745
1838
|
return [name2, next === void 0 ? selection2 : { ...selection2, $: { ...selection2.$, after: next } }];
|
|
1746
1839
|
})), response2 = await queryRecords(request2), page;
|
|
1747
1840
|
try {
|
|
1748
|
-
page =
|
|
1841
|
+
page = capture4(response2);
|
|
1749
1842
|
let keys4 = Object.keys(historyProperties(page));
|
|
1750
1843
|
(keys4.length !== active2.length + 1 || keys4.some((key) => key !== "$meta" && !active2.includes(key))) && unavailable();
|
|
1751
1844
|
let meta = page.$meta;
|
|
1752
|
-
(Object.keys(historyProperties(meta)).sort().join(",") !== "collections,version" || !text2(meta.version)
|
|
1845
|
+
(Object.keys(historyProperties(meta)).sort().join(",") !== "collections,version" || !text2(meta.version)) && unavailable(), version = meta.version, Object.keys(historyProperties(meta.collections)).some((key) => !active2.includes(key)) && unavailable();
|
|
1753
1846
|
for (let name2 of active2) {
|
|
1754
1847
|
let records = historyArray(page[name2]), metadata = Object.hasOwn(meta.collections, name2) ? meta.collections[name2] : {};
|
|
1755
1848
|
(Object.keys(historyProperties(metadata)).some((key) => key !== "count" && key !== "next") || Object.hasOwn(metadata, "next") && !text2(metadata.next)) && unavailable();
|
|
@@ -1759,7 +1852,7 @@ function recordPagination(queryRecords) {
|
|
|
1759
1852
|
(!validRecordRef(row.$ref) || !text2(row.$version)) && unavailable();
|
|
1760
1853
|
}
|
|
1761
1854
|
let current2 = state.get(name2);
|
|
1762
|
-
captured[name2].$?.count === !0 ? ((!Number.isSafeInteger(metadata.count) || metadata.count < 0
|
|
1855
|
+
captured[name2].$?.count === !0 ? ((!Number.isSafeInteger(metadata.count) || metadata.count < 0) && unavailable(), current2.count = metadata.count) : Object.hasOwn(metadata, "count") && unavailable(), metadata.next !== void 0 && (current2.seen.has(metadata.next) && unavailable(), current2.seen.add(metadata.next)), current2.next = metadata.next;
|
|
1763
1856
|
}
|
|
1764
1857
|
} catch {
|
|
1765
1858
|
return unavailable();
|
|
@@ -1775,32 +1868,7 @@ function recordPagination(queryRecords) {
|
|
|
1775
1868
|
} while (active2.length);
|
|
1776
1869
|
}
|
|
1777
1870
|
}
|
|
1778
|
-
|
|
1779
|
-
let properties = historyProperties(options), maxRecords = properties.maxRecords?.value;
|
|
1780
|
-
(Object.keys(properties).join(",") !== "maxRecords" || !Number.isSafeInteger(maxRecords) || maxRecords < 1) && invalid6();
|
|
1781
|
-
let captured = capture3(query), names = Object.keys(historyProperties(captured));
|
|
1782
|
-
if (names.length === 1) {
|
|
1783
|
-
let name2 = names[0], selection2 = historyProperties(captured[name2]), selectionNames = Object.keys(selection2), authored = selection2.$ ? historyProperties(selection2.$.value) : {};
|
|
1784
|
-
selectionNames.every((key) => key === "$") && !Object.hasOwn(authored, "limit") && (captured[name2] = { ...captured[name2], $: { ...captured[name2].$, limit: Math.min(500, maxRecords) } });
|
|
1785
|
-
}
|
|
1786
|
-
let result2, total = 0;
|
|
1787
|
-
for await (let page of pages(captured)) {
|
|
1788
|
-
let names2 = Object.keys(page.$meta.collections), size = names2.reduce((sum, name2) => sum + page[name2].length, 0);
|
|
1789
|
-
if (size > maxRecords - total) throw new DataOperationError("capacity", !1, void 0, void 0, {
|
|
1790
|
-
code: "record_limit_exceeded",
|
|
1791
|
-
maxRecords,
|
|
1792
|
-
collections: names2
|
|
1793
|
-
});
|
|
1794
|
-
total += size, result2 ??= { ...Object.fromEntries(names2.map((name2) => [name2, []])), $meta: page.$meta };
|
|
1795
|
-
for (let name2 of names2) {
|
|
1796
|
-
let target = result2[name2];
|
|
1797
|
-
for (let record4 of page[name2]) target.push(record4);
|
|
1798
|
-
}
|
|
1799
|
-
result2.$meta = page.$meta;
|
|
1800
|
-
}
|
|
1801
|
-
return result2;
|
|
1802
|
-
}
|
|
1803
|
-
return { pages, all };
|
|
1871
|
+
return { pages };
|
|
1804
1872
|
}
|
|
1805
1873
|
|
|
1806
1874
|
var genericData = {
|
|
@@ -1837,6 +1905,7 @@ var genericData = {
|
|
|
1837
1905
|
read: read2,
|
|
1838
1906
|
query: queryRecords,
|
|
1839
1907
|
...recordPagination(queryRecords),
|
|
1908
|
+
all: async (query, options) => send3({ operation: "records.all", ...captureRecordsAll(query, options) }),
|
|
1840
1909
|
search: async (query, options) => send3({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
|
|
1841
1910
|
},
|
|
1842
1911
|
history: {
|
|
@@ -2374,48 +2443,6 @@ var files = {
|
|
|
2374
2443
|
read
|
|
2375
2444
|
};
|
|
2376
2445
|
|
|
2377
|
-
function validDropboxRootPath(value) {
|
|
2378
|
-
return typeof value == "string" && value.length <= 2048 && value.startsWith("/") && !/[\\\x00-\x1f\x7f]/.test(value) && value.slice(1).split("/").every((segment) => segment.length > 0 && segment.trim() === segment && segment !== "." && segment !== "..");
|
|
2379
|
-
}
|
|
2380
|
-
function validMicrosoftId(value) {
|
|
2381
|
-
return typeof value == "string" && /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(value);
|
|
2382
|
-
}
|
|
2383
|
-
function validMicrosoftMailbox(value) {
|
|
2384
|
-
return typeof value == "string" && value.length <= 254 && /^[^\s@/?#\\\x00-\x1f\x7f]+@[^\s@/?#\\\x00-\x1f\x7f]+\.[^\s@/?#\\\x00-\x1f\x7f]+$/.test(value);
|
|
2385
|
-
}
|
|
2386
|
-
function sharePointHost(value) {
|
|
2387
|
-
return /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.sharepoint\.com$/.test(value);
|
|
2388
|
-
}
|
|
2389
|
-
function canonicalSharePointSiteUrl(value) {
|
|
2390
|
-
if (!(typeof value != "string" || value.length > 2048 || /[\s\\?#\x00-\x1f\x7f]/.test(value) || !/^https:\/\/[^/:@]+(?:\/|$)/i.test(value)))
|
|
2391
|
-
try {
|
|
2392
|
-
let url = new URL(value);
|
|
2393
|
-
if (url.protocol !== "https:" || !sharePointHost(url.hostname) || url.username || url.password || url.port) return;
|
|
2394
|
-
let rawPath = value.replace(/^https:\/\/[^/]+/i, "") || "/", path = rawPath.endsWith("/") ? rawPath.slice(0, -1) : rawPath, segments = path.slice(1).split("/");
|
|
2395
|
-
if (path && segments.some((segment) => !segment)) return;
|
|
2396
|
-
let encoded = path ? segments.map((segment) => {
|
|
2397
|
-
let decoded = decodeURIComponent(segment);
|
|
2398
|
-
if (decoded === "." || decoded === ".." || /[/%\\?#\x00-\x1f\x7f]/.test(decoded)) throw new Error();
|
|
2399
|
-
return encodeURIComponent(decoded);
|
|
2400
|
-
}).join("/") : "", canonical = `https://${url.hostname}/${encoded}`;
|
|
2401
|
-
return canonical.length <= 2048 ? canonical : void 0;
|
|
2402
|
-
} catch {
|
|
2403
|
-
return;
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
function validSharePointSiteId(value, siteUrl) {
|
|
2407
|
-
if (typeof value != "string" || value.length > 512) return !1;
|
|
2408
|
-
let [host, collection, site, extra] = value.split(",");
|
|
2409
|
-
return extra === void 0 && host === new URL(siteUrl).hostname && validMicrosoftId(collection) && validMicrosoftId(site);
|
|
2410
|
-
}
|
|
2411
|
-
function validGoogleScopes(value) {
|
|
2412
|
-
return Array.isArray(value) && value.length > 0 && value.length <= 32 && value.every((scope) => typeof scope == "string" && scope.length <= 256 && /^(https:\/\/www\.googleapis\.com\/auth\/[A-Za-z0-9._-]+|https:\/\/mail\.google\.com\/|openid|email|profile)$/.test(scope)) && new Set(value).size === value.length;
|
|
2413
|
-
}
|
|
2414
|
-
var DROPBOX_FILE_SCOPES = ["account_info.read", "files.metadata.read", "files.content.read", "files.content.write"];
|
|
2415
|
-
function validDropboxFileScopes(value) {
|
|
2416
|
-
return Array.isArray(value) && value.length === DROPBOX_FILE_SCOPES.length && new Set(value).size === value.length && DROPBOX_FILE_SCOPES.every((scope) => value.includes(scope));
|
|
2417
|
-
}
|
|
2418
|
-
|
|
2419
2446
|
var ROUTINE_CONNECTION_CREDENTIALS_ENV = "OS_ROUTINE_CONNECTION_CREDENTIALS";
|
|
2420
2447
|
function parseRoutineConnectionNames(value) {
|
|
2421
2448
|
if (!Array.isArray(value) || value.some((name2) => typeof name2 != "string" || !/^(gmail|airtable|dropbox|outlook|sharepoint)\/[a-z0-9][a-z0-9-]{0,62}$/.test(name2)) || new Set(value).size !== value.length)
|
|
@@ -2903,14 +2930,41 @@ var source = {
|
|
|
2903
2930
|
};
|
|
2904
2931
|
|
|
2905
2932
|
var InboxOperationError = class extends Error {
|
|
2906
|
-
constructor(status, reason) {
|
|
2907
|
-
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");
|
|
2933
|
+
constructor(status, reason, requirementsRepository) {
|
|
2934
|
+
super(reason === "records_need_attention" ? "Records need to be pushed or reviewed." : reason === "records_unavailable" ? "Records temporarily unavailable. Try again shortly." : reason === "handler_unavailable" ? "Deploy the routine that owns this question\u2019s response handler." : 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");
|
|
2908
2935
|
this.status = status;
|
|
2909
2936
|
this.reason = reason;
|
|
2937
|
+
this.requirementsRepository = requirementsRepository;
|
|
2910
2938
|
}
|
|
2911
2939
|
status;
|
|
2912
2940
|
reason;
|
|
2913
|
-
|
|
2941
|
+
requirementsRepository;
|
|
2942
|
+
};
|
|
2943
|
+
function parseQuestionAvailability(value, available = !1) {
|
|
2944
|
+
let state = object4(value);
|
|
2945
|
+
return keys3(state, ["unavailableReason", "requirementsRepository"], []), "unavailableReason" in state ? (assert(!available && typeof state.unavailableReason == "string" && ["handler_unavailable", "records_need_attention", "records_unavailable"].includes(String(state.unavailableReason))), state.unavailableReason === "records_need_attention" ? assert(validDataRepositoryName(state.requirementsRepository)) : assert(!("requirementsRepository" in state)), {
|
|
2946
|
+
unavailableReason: state.unavailableReason,
|
|
2947
|
+
...state.unavailableReason === "records_need_attention" ? { requirementsRepository: state.requirementsRepository } : {}
|
|
2948
|
+
}) : (assert(!("requirementsRepository" in state)), {});
|
|
2949
|
+
}
|
|
2950
|
+
function questionAvailability(value, available = !1) {
|
|
2951
|
+
return parseQuestionAvailability({
|
|
2952
|
+
..."unavailableReason" in value ? { unavailableReason: value.unavailableReason } : {},
|
|
2953
|
+
..."requirementsRepository" in value ? { requirementsRepository: value.requirementsRepository } : {}
|
|
2954
|
+
}, available);
|
|
2955
|
+
}
|
|
2956
|
+
function parseInboxUnavailableFailure(value, status) {
|
|
2957
|
+
try {
|
|
2958
|
+
if (status !== 503) return;
|
|
2959
|
+
let envelope = object4(value);
|
|
2960
|
+
keys3(envelope, ["error", "unavailableReason", "requirementsRepository"], ["error", "unavailableReason"]), assert(text4(envelope.error));
|
|
2961
|
+
let state = questionAvailability(envelope);
|
|
2962
|
+
return new InboxOperationError(503, state.unavailableReason, state.requirementsRepository);
|
|
2963
|
+
} catch {
|
|
2964
|
+
return;
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
var INBOX_RESULT_BYTES = 8 * 1024 * 1024, INBOX_INPUT_BYTES = 8192, INBOX_LOCAL_INPUT_BYTES = 256 * 1024, INBOX_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
2914
2968
|
function isAppQuestionOperation(operation2) {
|
|
2915
2969
|
return operation2 === "questions.list" || operation2 === "questions.answer" || operation2 === "questions.searchRecords";
|
|
2916
2970
|
}
|
|
@@ -3090,7 +3144,7 @@ function parseInboxItem(value) {
|
|
|
3090
3144
|
assert(id2(person.id) && text4(person.name));
|
|
3091
3145
|
}), array2(item.questions).forEach((value2) => {
|
|
3092
3146
|
let question2 = object4(value2);
|
|
3093
|
-
if (assert(text4(question2.id) && id2(question2.to) && text4(question2.prompt) && (question2.instructions === null || text4(question2.instructions, !0)) && typeof question2.available == "boolean"), responseDefinition(question2.response), assert(array2(question2.allowedResponders).every(id2)), question2.acceptedResponse !== null) {
|
|
3147
|
+
if (assert(text4(question2.id) && id2(question2.to) && text4(question2.prompt) && (question2.instructions === null || text4(question2.instructions, !0)) && typeof question2.available == "boolean"), questionAvailability(question2, question2.available), assert(!("requirements" in question2) && !("handler" in question2)), responseDefinition(question2.response), assert(array2(question2.allowedResponders).every(id2)), question2.acceptedResponse !== null) {
|
|
3094
3148
|
let accepted = object4(question2.acceptedResponse);
|
|
3095
3149
|
assert(id2(accepted.id) && id2(accepted.userId) && date(accepted.acceptedAt)), response(accepted.response), accepted.label === null ? delete accepted.label : "label" in accepted && assert(text4(accepted.label)), "acceptanceOrder" in accepted && assert(integer(accepted.acceptanceOrder));
|
|
3096
3150
|
}
|
|
@@ -3123,11 +3177,11 @@ function parseAnswerableQuestion(value) {
|
|
|
3123
3177
|
let entry = object4(json(value));
|
|
3124
3178
|
keys3(
|
|
3125
3179
|
entry,
|
|
3126
|
-
["itemId", "number", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "tags", "recordRefs", "instructions"],
|
|
3180
|
+
["itemId", "number", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "tags", "recordRefs", "instructions", "unavailableReason", "requirementsRepository"],
|
|
3127
3181
|
["itemId", "number", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable"]
|
|
3128
3182
|
), assert(id2(entry.itemId) && integer(entry.number) && integer(entry.revision) && text4(entry.title) && text4(entry.inboxUrl));
|
|
3129
3183
|
let link = new URL(entry.inboxUrl), slug = link.hostname.slice(0, -13);
|
|
3130
|
-
return assert(link.hostname.endsWith(".oddington.ai") && slug.length <= 63 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug) && !["auth", "www", "api", "os"].includes(slug) && entry.inboxUrl === `https://${slug}.oddington.ai/inbox/${entry.itemId}`), assert(isAppRoutineName(entry.routine) && text4(entry.questionId) && entry.questionId === entry.questionId.trim() && text4(entry.prompt) && (!("instructions" in entry) || text4(entry.instructions, !0)) && typeof entry.answerable == "boolean"), responseDefinition(entry.response), askMetadata(entry), entry;
|
|
3184
|
+
return assert(link.hostname.endsWith(".oddington.ai") && slug.length <= 63 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug) && !["auth", "www", "api", "os"].includes(slug) && entry.inboxUrl === `https://${slug}.oddington.ai/inbox/${entry.itemId}`), assert(isAppRoutineName(entry.routine) && text4(entry.questionId) && entry.questionId === entry.questionId.trim() && text4(entry.prompt) && (!("instructions" in entry) || text4(entry.instructions, !0)) && typeof entry.answerable == "boolean"), questionAvailability(entry, entry.answerable), responseDefinition(entry.response), askMetadata(entry), entry;
|
|
3131
3185
|
}
|
|
3132
3186
|
function askMetadata(entry) {
|
|
3133
3187
|
let tags = array2(entry.tags === void 0 ? [] : entry.tags);
|
|
@@ -3332,7 +3386,7 @@ function isAppOrigin(value) {
|
|
|
3332
3386
|
return !1;
|
|
3333
3387
|
}
|
|
3334
3388
|
}
|
|
3335
|
-
function appContext(origin, active2) {
|
|
3389
|
+
function appContext(origin, active2, changed) {
|
|
3336
3390
|
let binding, credential, pair, serialized, denied = !1, controller = new AbortController(), access = new AbortController(), expiry, startup, renewalTimer, renewal, observation, resolution2, disposed = !1, stored = () => globalThis.localStorage.getItem(sessionKey), alive = () => {
|
|
3337
3391
|
try {
|
|
3338
3392
|
return !denied && !disposed && active2() && globalThis.location.origin === origin;
|
|
@@ -3342,12 +3396,20 @@ function appContext(origin, active2) {
|
|
|
3342
3396
|
}, cancel = () => {
|
|
3343
3397
|
controller.abort(), access.abort(), clearTimeout(expiry), clearTimeout(startup), clearTimeout(renewalTimer), clearInterval(monitor), globalThis.removeEventListener?.("storage", storageChanged);
|
|
3344
3398
|
for (let event of ["pageshow", "focus", "visibilitychange"]) globalThis.removeEventListener?.(event, wake);
|
|
3345
|
-
},
|
|
3346
|
-
denied = !0, cancel();
|
|
3399
|
+
}, notify = (state) => {
|
|
3347
3400
|
try {
|
|
3348
|
-
|
|
3401
|
+
changed?.(state);
|
|
3349
3402
|
} catch {
|
|
3350
3403
|
}
|
|
3404
|
+
}, invalidate = (state = "unavailable") => {
|
|
3405
|
+
if (!denied) {
|
|
3406
|
+
denied = !0, cancel();
|
|
3407
|
+
try {
|
|
3408
|
+
!disposed && active2() && globalThis.location.origin === origin && (!serialized || globalThis.localStorage.getItem(sessionKey) === serialized) && globalThis.localStorage.removeItem(sessionKey);
|
|
3409
|
+
} catch {
|
|
3410
|
+
}
|
|
3411
|
+
notify(state);
|
|
3412
|
+
}
|
|
3351
3413
|
}, current2 = () => {
|
|
3352
3414
|
try {
|
|
3353
3415
|
return alive() && !!binding && binding.expiresAt > Date.now() && stored() === serialized;
|
|
@@ -3359,10 +3421,10 @@ function appContext(origin, active2) {
|
|
|
3359
3421
|
if (!validPair(value) || value.context.expiresAt > Date.now() + 6e5 || !sameSession(value.context)) throw new Error();
|
|
3360
3422
|
return value;
|
|
3361
3423
|
}, expireAccess = () => {
|
|
3362
|
-
binding && binding.expiresAt <= Date.now() && access.abort();
|
|
3424
|
+
binding && binding.expiresAt <= Date.now() && !access.signal.aborted && (access.abort(), notify("expired"));
|
|
3363
3425
|
};
|
|
3364
3426
|
async function send3(path, candidate, signal, init2 = {}) {
|
|
3365
|
-
let url = `${origin}/_os/app/${path}`, response2;
|
|
3427
|
+
let url = path === "auth" ? `${origin}/api/auth` : `${origin}/_os/app/${path}`, response2;
|
|
3366
3428
|
try {
|
|
3367
3429
|
response2 = await fetch(url, {
|
|
3368
3430
|
...init2,
|
|
@@ -3400,7 +3462,7 @@ function appContext(origin, active2) {
|
|
|
3400
3462
|
expiry = setTimeout(expireAccess, remaining), renewalTimer = setTimeout(() => {
|
|
3401
3463
|
renew().catch(() => {
|
|
3402
3464
|
});
|
|
3403
|
-
}, remaining - Math.min(6e4, remaining / 5));
|
|
3465
|
+
}, remaining - Math.min(6e4, remaining / 5)), notify("connected");
|
|
3404
3466
|
}
|
|
3405
3467
|
async function synchronize(signal = controller.signal) {
|
|
3406
3468
|
if (!alive()) throw new Error();
|
|
@@ -3436,7 +3498,7 @@ function appContext(origin, active2) {
|
|
|
3436
3498
|
observation === observed && (observation = void 0);
|
|
3437
3499
|
}
|
|
3438
3500
|
}
|
|
3439
|
-
async function renew() {
|
|
3501
|
+
async function renew(initialConnection = !1) {
|
|
3440
3502
|
if (renewal) return renewal;
|
|
3441
3503
|
if (!binding || !pair || !alive()) throw new Error();
|
|
3442
3504
|
renewal = (async () => {
|
|
@@ -3462,7 +3524,7 @@ function appContext(origin, active2) {
|
|
|
3462
3524
|
await synchronize(requestController.signal);
|
|
3463
3525
|
return;
|
|
3464
3526
|
}
|
|
3465
|
-
if (!response2.ok) throw new Error();
|
|
3527
|
+
if (!response2.ok) throw response2.status === 401 || response2.status === 403 ? new AppContextDenied() : new Error();
|
|
3466
3528
|
if (!alive() || !validPair(value) || !bounded3(value.context) || (/* @__PURE__ */ new Set([value.credential, value.renewalCredential, pair.credential, pair.renewalCredential])).size !== 4) throw new Error();
|
|
3467
3529
|
if (stored() !== previous) {
|
|
3468
3530
|
await synchronize(requestController.signal);
|
|
@@ -3471,6 +3533,7 @@ function appContext(origin, active2) {
|
|
|
3471
3533
|
let raw = JSON.stringify(value);
|
|
3472
3534
|
globalThis.localStorage.setItem(sessionKey, raw), install(value.context, value, raw);
|
|
3473
3535
|
} catch (error) {
|
|
3536
|
+
if (initialConnection && error instanceof AppContextDenied) throw error;
|
|
3474
3537
|
try {
|
|
3475
3538
|
if (alive() && stored() && stored() !== previous) {
|
|
3476
3539
|
await synchronize(requestController.signal);
|
|
@@ -3520,28 +3583,28 @@ function appContext(origin, active2) {
|
|
|
3520
3583
|
for (await synchronize(); alive() && stored() !== serialized; ) await synchronize();
|
|
3521
3584
|
if (signal.aborted || !current2()) throw new Error();
|
|
3522
3585
|
}
|
|
3523
|
-
async function requestData(operation2, input) {
|
|
3586
|
+
async function requestData(operation2, input, parent) {
|
|
3524
3587
|
try {
|
|
3525
3588
|
if (operation2 !== "data/query" || !current2()) throw new Error();
|
|
3526
|
-
let admitted = credential, signal = access.signal, response2 = await send3("data", credential, signal, { method: "POST", body: JSON.stringify(input) });
|
|
3589
|
+
let admitted = credential, signal = parent ? AbortSignal.any([access.signal, parent]) : access.signal, response2 = await send3("data", credential, signal, { method: "POST", body: JSON.stringify(input) });
|
|
3527
3590
|
if (await settledAccess(signal), response2.status === 401 || response2.status === 403)
|
|
3528
3591
|
throw admitted === credential && current2() && invalidate(), new DataOperationError("access_denied");
|
|
3529
3592
|
let result2 = await appResponse(response2, Number.MAX_SAFE_INTEGER, signal);
|
|
3530
3593
|
if (await settledAccess(signal), !response2.ok) throw dataTransportError(response2.status, result2);
|
|
3531
3594
|
return result2;
|
|
3532
3595
|
} catch (error) {
|
|
3533
|
-
throw error instanceof DataOperationError ? error : !current2() || controller.signal.aborted ? new DataOperationError("context_unavailable") : new DataOperationError("unavailable", !0);
|
|
3596
|
+
throw error instanceof DataOperationError ? error : !current2() || controller.signal.aborted || parent?.aborted ? new DataOperationError("context_unavailable") : new DataOperationError("unavailable", !0);
|
|
3534
3597
|
}
|
|
3535
3598
|
}
|
|
3536
|
-
async function requestInbox(operation2, input) {
|
|
3599
|
+
async function requestInbox(operation2, input, signal) {
|
|
3537
3600
|
if (!["questions.list", "questions.answer", "questions.searchRecords"].includes(operation2)) throw new Error("Inbox operation unavailable");
|
|
3538
|
-
return requestChecked("inbox", { method: "POST", body: JSON.stringify({ operation: operation2, input }) }, !0);
|
|
3601
|
+
return requestChecked("inbox", { method: "POST", body: JSON.stringify({ operation: operation2, input }), signal }, !0);
|
|
3539
3602
|
}
|
|
3540
3603
|
async function requestRoutine(key, suffix, init2 = {}) {
|
|
3541
3604
|
return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, init2);
|
|
3542
3605
|
}
|
|
3543
|
-
async function requestRetainedRoutine(key, suffix) {
|
|
3544
|
-
return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, {}, !1, !0);
|
|
3606
|
+
async function requestRetainedRoutine(key, suffix, signal) {
|
|
3607
|
+
return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, { signal }, !1, !0);
|
|
3545
3608
|
}
|
|
3546
3609
|
async function requestFiles(suffix, init2, parent) {
|
|
3547
3610
|
let unavailable5 = () => new FileOperationError("unsupported_context", 400);
|
|
@@ -3564,7 +3627,7 @@ function appContext(origin, active2) {
|
|
|
3564
3627
|
}
|
|
3565
3628
|
async function requestChecked(path, init2, inbox2 = !1, retained2 = !1) {
|
|
3566
3629
|
if (!current2()) throw new Error("Local app context unavailable.");
|
|
3567
|
-
let admitted = credential, signal = access.signal, response2 = await send3(path, credential, signal, init2), check = async () => {
|
|
3630
|
+
let admitted = credential, signal = init2.signal ? AbortSignal.any([access.signal, init2.signal]) : access.signal, response2 = await send3(path, credential, signal, init2), check = async () => {
|
|
3568
3631
|
if (retained2) {
|
|
3569
3632
|
if (signal.aborted || !current2()) throw new Error("Local app context unavailable.");
|
|
3570
3633
|
} else await settledAccess(signal);
|
|
@@ -3599,8 +3662,32 @@ function appContext(origin, active2) {
|
|
|
3599
3662
|
try {
|
|
3600
3663
|
if (!alive()) throw new Error();
|
|
3601
3664
|
if (!pair) {
|
|
3602
|
-
let candidate2 = stored()
|
|
3603
|
-
|
|
3665
|
+
let candidate2 = stored();
|
|
3666
|
+
if (candidate2)
|
|
3667
|
+
try {
|
|
3668
|
+
let retained3 = readPair(candidate2);
|
|
3669
|
+
if (retained3.context.expiresAt <= Date.now()) {
|
|
3670
|
+
if (pair = retained3, binding = { ...retained3.context }, credential = retained3.credential, serialized = candidate2, await renew(!0), !current2()) throw new AppRenewalUnavailable();
|
|
3671
|
+
return context();
|
|
3672
|
+
}
|
|
3673
|
+
let value3 = await proof(retained3.credential);
|
|
3674
|
+
return stored() !== candidate2 ? resolveOnce() : (install(value3, retained3, candidate2), context());
|
|
3675
|
+
} catch (error) {
|
|
3676
|
+
if (error instanceof AppRenewalUnavailable || error instanceof AppResponseReadError || !(error instanceof AppContextDenied) || !alive() || expiry) throw error;
|
|
3677
|
+
pair = void 0, binding = void 0, credential = void 0, serialized = void 0;
|
|
3678
|
+
}
|
|
3679
|
+
let response2 = await untilAborted(fetch(`${origin}/_os/app/connect`, {
|
|
3680
|
+
method: "POST",
|
|
3681
|
+
credentials: "omit",
|
|
3682
|
+
redirect: "error",
|
|
3683
|
+
cache: "no-store",
|
|
3684
|
+
referrerPolicy: "no-referrer",
|
|
3685
|
+
signal: controller.signal
|
|
3686
|
+
}), controller.signal), value2 = await appResponse(response2, 4096, controller.signal);
|
|
3687
|
+
if (!response2.ok || response2.redirected || response2.url && response2.url !== `${origin}/_os/app/connect` || !alive() || !validPair(value2) || !bounded3(value2.context)) throw new Error();
|
|
3688
|
+
if (stored() !== candidate2 && stored()) return resolveOnce();
|
|
3689
|
+
let raw = JSON.stringify(value2);
|
|
3690
|
+
return globalThis.localStorage.setItem(sessionKey, raw), install(value2.context, value2, raw), context();
|
|
3604
3691
|
}
|
|
3605
3692
|
if (expireAccess(), binding.expiresAt <= Date.now()) {
|
|
3606
3693
|
if (await renew(), !current2()) throw new AppRenewalUnavailable();
|
|
@@ -3629,17 +3716,41 @@ function appContext(origin, active2) {
|
|
|
3629
3716
|
}, resolve = () => resolution2 || (resolution2 = resolveOnce().finally(() => {
|
|
3630
3717
|
resolution2 = void 0;
|
|
3631
3718
|
}), resolution2);
|
|
3632
|
-
return {
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3719
|
+
return {
|
|
3720
|
+
resolve,
|
|
3721
|
+
retained: async () => {
|
|
3722
|
+
if (!expiry && alive() && (binding ? current2() && resolution2 : !stored() || readPair(stored()).context.expiresAt > Date.now()))
|
|
3723
|
+
return resolve();
|
|
3724
|
+
if (!expiry || !current2()) throw new Error("Local app context unavailable.");
|
|
3725
|
+
return context();
|
|
3726
|
+
},
|
|
3727
|
+
start: () => {
|
|
3728
|
+
startup = setTimeout(() => {
|
|
3729
|
+
alive() && !resolution2 && !binding && resolve().catch(() => {
|
|
3730
|
+
});
|
|
3731
|
+
}, 0);
|
|
3732
|
+
},
|
|
3733
|
+
invalidate,
|
|
3734
|
+
dispose,
|
|
3735
|
+
account: async () => {
|
|
3736
|
+
await resolve();
|
|
3737
|
+
let signal = access.signal, response2 = await requestChecked("auth", { method: "GET" }), value = await appResponse(response2, 4096, signal);
|
|
3738
|
+
if (!response2.ok || !current2() || !value || Object.keys(value).join(",") !== "account" || !value.account || Object.keys(value.account).sort().join(",") !== "displayName,email" || typeof value.account.email != "string" || value.account.email.length > 320 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.account.email) || typeof value.account.displayName != "string" || !value.account.displayName.trim() || value.account.displayName.length > 320)
|
|
3739
|
+
throw new Error("Local app account unavailable.");
|
|
3740
|
+
return Object.freeze({ email: value.account.email, displayName: value.account.displayName });
|
|
3741
|
+
},
|
|
3742
|
+
signOut: async () => {
|
|
3743
|
+
if (current2() || await resolve(), !current2()) throw new Error("Local app context unavailable.");
|
|
3744
|
+
let signal = AbortSignal.timeout(2e4), pending = send3("sign-out", credential, signal, { method: "POST" });
|
|
3745
|
+
invalidate("signed_out");
|
|
3746
|
+
let response2 = await pending, value = await appResponse(response2, 4096, signal);
|
|
3747
|
+
if (!response2.ok || !value || Object.keys(value).join(",") !== "signedOut" || value.signedOut !== !0)
|
|
3748
|
+
throw new Error("Local app sign-out unavailable.");
|
|
3749
|
+
},
|
|
3750
|
+
isCurrent() {
|
|
3751
|
+
return expireAccess(), current2();
|
|
3752
|
+
}
|
|
3753
|
+
};
|
|
3643
3754
|
}
|
|
3644
3755
|
function validProof(value) {
|
|
3645
3756
|
return typeof value == "string" && /^[A-Za-z0-9_-]{43}$/.test(value);
|
|
@@ -3681,7 +3792,7 @@ async function send2(operation2, input, resolved) {
|
|
|
3681
3792
|
};
|
|
3682
3793
|
try {
|
|
3683
3794
|
let response2 = await context.requestInbox(operation2, envelope.input), value = await appResponse(response2, INBOX_RESULT_BYTES, context.signal);
|
|
3684
|
-
if (check2(), !response2.ok) throw new InboxOperationError(
|
|
3795
|
+
if (check2(), !response2.ok) throw parseInboxUnavailableFailure(value, response2.status) ?? new InboxOperationError(
|
|
3685
3796
|
[400, 401, 403, 409].includes(response2.status) ? response2.status : 503,
|
|
3686
3797
|
response2.status === 400 ? "invalid_input" : response2.status === 401 ? "authority_unavailable" : response2.status === 403 ? "access_denied" : response2.status === 409 ? "conflict" : "unavailable"
|
|
3687
3798
|
);
|
|
@@ -3723,12 +3834,20 @@ async function send2(operation2, input, resolved) {
|
|
|
3723
3834
|
throw response2.body?.cancel().catch(() => {
|
|
3724
3835
|
}), error;
|
|
3725
3836
|
}
|
|
3726
|
-
if (!response2.ok)
|
|
3727
|
-
|
|
3728
|
-
|
|
3837
|
+
if (!response2.ok) {
|
|
3838
|
+
let value2;
|
|
3839
|
+
try {
|
|
3840
|
+
let bytes2 = await limitedBody(response2, 8192);
|
|
3841
|
+
check(), bytes2 && (value2 = JSON.parse(new TextDecoder().decode(bytes2)));
|
|
3842
|
+
} catch {
|
|
3843
|
+
check();
|
|
3844
|
+
}
|
|
3845
|
+
let refusal = parseInboxUnavailableFailure(value2, response2.status);
|
|
3846
|
+
throw refusal || new InboxOperationError(
|
|
3729
3847
|
[400, 401, 403, 409].includes(response2.status) ? response2.status : 503,
|
|
3730
3848
|
response2.status === 400 ? "invalid_input" : response2.status === 401 ? "authority_unavailable" : response2.status === 403 ? "access_denied" : response2.status === 409 ? "conflict" : "unavailable"
|
|
3731
3849
|
);
|
|
3850
|
+
}
|
|
3732
3851
|
if (response2.status !== 200)
|
|
3733
3852
|
throw response2.body?.cancel().catch(() => {
|
|
3734
3853
|
}), unavailable3();
|
|
@@ -3839,8 +3958,37 @@ function init({ auth: input }) {
|
|
|
3839
3958
|
url.protocol === "https:" && !url.port && !url.username && !url.password && !url.search && !url.hash && url.pathname === "/" && /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(slug) && slug !== "auth" && (endpoint = url.origin, workspace = slug);
|
|
3840
3959
|
} catch {
|
|
3841
3960
|
}
|
|
3842
|
-
let active2 = !0, revision = 0, person, token, binding = {}, local2 = localOrigin ? appContext(localOrigin, () => active2) : void 0, subscription, stopDisposal,
|
|
3843
|
-
|
|
3961
|
+
let active2 = !0, revision = 0, person, token, binding = {}, installation = new AbortController(), sharedLocal = localOrigin && registered?.localContext?.origin === localOrigin ? registered.localContext.connection : void 0, local2 = sharedLocal ?? (localOrigin ? appContext(localOrigin, () => active2) : void 0), subscription, stopDisposal, owned = (context) => {
|
|
3962
|
+
let signal = AbortSignal.any([context.signal, installation.signal]);
|
|
3963
|
+
return {
|
|
3964
|
+
...context,
|
|
3965
|
+
get expiresAt() {
|
|
3966
|
+
return context.expiresAt;
|
|
3967
|
+
},
|
|
3968
|
+
signal,
|
|
3969
|
+
isCurrent: () => active2 && !signal.aborted && context.isCurrent(),
|
|
3970
|
+
requestData: (operation2, input2) => context.requestData(operation2, input2, signal),
|
|
3971
|
+
requestInbox: (operation2, input2) => context.requestInbox(operation2, input2, signal),
|
|
3972
|
+
requestFiles: (suffix, init2, parent) => context.requestFiles(
|
|
3973
|
+
suffix,
|
|
3974
|
+
init2,
|
|
3975
|
+
parent ? AbortSignal.any([signal, parent]) : signal
|
|
3976
|
+
),
|
|
3977
|
+
requestRoutine: (key, suffix, init2 = {}) => context.requestRoutine(
|
|
3978
|
+
key,
|
|
3979
|
+
suffix,
|
|
3980
|
+
{ ...init2, signal: init2.signal ? AbortSignal.any([signal, init2.signal]) : signal }
|
|
3981
|
+
),
|
|
3982
|
+
requestRetainedRoutine: (key, suffix) => context.requestRetainedRoutine(key, suffix, signal),
|
|
3983
|
+
requestAvailability: (key) => context.requestRoutine(key, "availability", { method: "GET", signal })
|
|
3984
|
+
};
|
|
3985
|
+
}, resolve = async () => {
|
|
3986
|
+
if (local2) {
|
|
3987
|
+
if (!active2) throw new Error("Local app context unavailable.");
|
|
3988
|
+
let context = await local2.resolve();
|
|
3989
|
+
if (!active2) throw new Error("Local app context unavailable.");
|
|
3990
|
+
return owned(context);
|
|
3991
|
+
}
|
|
3844
3992
|
if (registered && await registered.ready(), !active2 || !endpoint || !workspace || globalThis.location.origin !== endpoint) throw new Error("Hosted Data context unavailable.");
|
|
3845
3993
|
let started = revision, { data: { session }, error } = await auth2.getSession();
|
|
3846
3994
|
if (!active2 || globalThis.location.origin !== endpoint || started !== revision || error || !session || person !== void 0 && person !== session.user.id)
|
|
@@ -3860,13 +4008,18 @@ function init({ auth: input }) {
|
|
|
3860
4008
|
memberId: session.user.id,
|
|
3861
4009
|
binding
|
|
3862
4010
|
};
|
|
3863
|
-
}, uninstall = installMemberContext(resolve, local2 ?
|
|
3864
|
-
|
|
4011
|
+
}, uninstall = installMemberContext(resolve, local2 ? async () => {
|
|
4012
|
+
if (!active2 || !local2) throw new Error("Local app context unavailable.");
|
|
4013
|
+
let context = await local2.retained();
|
|
4014
|
+
if (!active2) throw new Error("Local app context unavailable.");
|
|
4015
|
+
return owned(context);
|
|
4016
|
+
} : resolve), dispose = () => {
|
|
4017
|
+
active2 && (active2 = !1, installation.abort(), sharedLocal || local2?.dispose(), revision++, subscription?.unsubscribe(), stopDisposal?.(), uninstall(), installedDispose === dispose && (installedDispose = void 0));
|
|
3865
4018
|
};
|
|
3866
|
-
installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (subscription = auth2.onAuthStateChange((event, session) => {
|
|
4019
|
+
installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (sharedLocal || (subscription = auth2.onAuthStateChange((event, session) => {
|
|
3867
4020
|
let next = session?.user.id ?? null;
|
|
3868
4021
|
(event === "SIGNED_OUT" || person !== void 0 && next !== person || person !== void 0 && event === "SIGNED_IN" && token !== session?.access_token) && (revision++, local2?.invalidate()), person = next, token = session?.access_token;
|
|
3869
|
-
}).data.subscription, local2?.start());
|
|
4022
|
+
}).data.subscription), sharedLocal || local2?.start());
|
|
3870
4023
|
}
|
|
3871
4024
|
var os = { init };
|
|
3872
4025
|
|
|
@@ -3906,9 +4059,127 @@ function authorizationFailure(error) {
|
|
|
3906
4059
|
return Object.freeze({ status: status === 404 || status === 410 || status === 400 ? "expired" : status === 401 ? "signed_out" : status === 403 || status === 422 ? "invalid" : "unavailable" });
|
|
3907
4060
|
}
|
|
3908
4061
|
|
|
4062
|
+
var coordinators = /* @__PURE__ */ new Map(), publish = (c, state) => {
|
|
4063
|
+
c.state = Object.freeze(state);
|
|
4064
|
+
for (let listener of c.listeners)
|
|
4065
|
+
try {
|
|
4066
|
+
listener(c.state);
|
|
4067
|
+
} catch {
|
|
4068
|
+
}
|
|
4069
|
+
};
|
|
4070
|
+
function refresh(c) {
|
|
4071
|
+
let revision = c.revision;
|
|
4072
|
+
if (c.loading?.revision === revision) return c.loading.promise;
|
|
4073
|
+
let promise = (async () => {
|
|
4074
|
+
try {
|
|
4075
|
+
let account = await c.context.account();
|
|
4076
|
+
c.active && !c.closed && c.revision === revision && publish(c, { status: "signed_in", account });
|
|
4077
|
+
} catch {
|
|
4078
|
+
c.active && !c.closed && c.revision === revision && publish(c, { status: "unavailable", error: "unavailable" });
|
|
4079
|
+
}
|
|
4080
|
+
})().finally(() => {
|
|
4081
|
+
c.loading?.promise === promise && (c.loading = void 0);
|
|
4082
|
+
});
|
|
4083
|
+
return c.loading = { revision, promise }, promise;
|
|
4084
|
+
}
|
|
4085
|
+
function createLocalBrowserAuth(origin, failure) {
|
|
4086
|
+
let c = coordinators.get(origin);
|
|
4087
|
+
if (!c) {
|
|
4088
|
+
let coordinator2 = {
|
|
4089
|
+
context: void 0,
|
|
4090
|
+
state: Object.freeze({ status: "initializing" }),
|
|
4091
|
+
active: !0,
|
|
4092
|
+
closed: !1,
|
|
4093
|
+
refs: 0,
|
|
4094
|
+
revision: 0,
|
|
4095
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
4096
|
+
ready: Promise.resolve()
|
|
4097
|
+
};
|
|
4098
|
+
coordinator2.context = appContext(origin, () => coordinator2.active, (state) => {
|
|
4099
|
+
!coordinator2.active || coordinator2.closed || (state === "connected" ? coordinator2.state.status !== "initializing" && (coordinator2.revision++, refresh(coordinator2)) : (coordinator2.revision++, publish(coordinator2, { status: state === "expired" ? "expired" : state === "signed_out" ? "signed_out" : "unavailable" })));
|
|
4100
|
+
}), c = coordinator2, coordinators.set(origin, c), c.ready = Promise.resolve().then(() => refresh(coordinator2));
|
|
4101
|
+
}
|
|
4102
|
+
let coordinator = c;
|
|
4103
|
+
coordinator.refs++;
|
|
4104
|
+
let active2 = !0, lastState = coordinator.state, listeners = /* @__PURE__ */ new Set(), disposals = /* @__PURE__ */ new Set(), observe = (state) => {
|
|
4105
|
+
lastState = state;
|
|
4106
|
+
for (let listener of listeners)
|
|
4107
|
+
try {
|
|
4108
|
+
listener(state);
|
|
4109
|
+
} catch {
|
|
4110
|
+
}
|
|
4111
|
+
};
|
|
4112
|
+
coordinator.listeners.add(observe);
|
|
4113
|
+
let assertActive = () => {
|
|
4114
|
+
if (!active2) throw failure("disposed");
|
|
4115
|
+
}, unavailable5 = async () => Object.freeze({
|
|
4116
|
+
status: active2 ? coordinator.state.status === "signed_out" ? "signed_out" : "unavailable" : "disposed"
|
|
4117
|
+
}), handle2 = Object.freeze({
|
|
4118
|
+
authorization: Object.freeze({ get: unavailable5, approve: unavailable5, deny: unavailable5 }),
|
|
4119
|
+
getState() {
|
|
4120
|
+
return active2 && !coordinator.state.pending && coordinator.state.status === "signed_in" && !coordinator.context.isCurrent() && coordinator.state.status === "signed_in" && publish(coordinator, { status: "unavailable", error: "unavailable" }), lastState;
|
|
4121
|
+
},
|
|
4122
|
+
subscribe(listener) {
|
|
4123
|
+
return assertActive(), listeners.add(listener), () => {
|
|
4124
|
+
listeners.delete(listener);
|
|
4125
|
+
};
|
|
4126
|
+
},
|
|
4127
|
+
async sendCode() {
|
|
4128
|
+
throw assertActive(), failure("unavailable");
|
|
4129
|
+
},
|
|
4130
|
+
async verifyCode() {
|
|
4131
|
+
throw assertActive(), failure("unavailable");
|
|
4132
|
+
},
|
|
4133
|
+
async signOut() {
|
|
4134
|
+
if (assertActive(), coordinator.state.pending === "sign_out") throw failure("busy");
|
|
4135
|
+
if (coordinator.closed) throw failure("unavailable");
|
|
4136
|
+
coordinator.closed = !0, coordinator.revision++, publish(coordinator, { status: coordinator.state.status, pending: "sign_out" });
|
|
4137
|
+
try {
|
|
4138
|
+
await coordinator.context.signOut();
|
|
4139
|
+
} catch {
|
|
4140
|
+
throw coordinator.context.invalidate(), coordinator.active && publish(coordinator, { status: "unavailable", error: "unavailable" }), failure(active2 ? "unavailable" : "disposed");
|
|
4141
|
+
}
|
|
4142
|
+
coordinator.active && publish(coordinator, { status: "signed_out" }), assertActive();
|
|
4143
|
+
},
|
|
4144
|
+
dispose() {
|
|
4145
|
+
if (active2) {
|
|
4146
|
+
active2 = !1, coordinator.listeners.delete(observe), listeners.clear();
|
|
4147
|
+
for (let callback of disposals)
|
|
4148
|
+
try {
|
|
4149
|
+
callback();
|
|
4150
|
+
} catch {
|
|
4151
|
+
}
|
|
4152
|
+
disposals.clear(), --coordinator.refs === 0 && (coordinator.active = !1, coordinator.revision++, coordinator.context.dispose(), coordinator.listeners.clear(), coordinators.delete(origin));
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
});
|
|
4156
|
+
return registerBrowserAuth(handle2, {
|
|
4157
|
+
localContext: { origin, connection: coordinator.context },
|
|
4158
|
+
async ready() {
|
|
4159
|
+
assertActive(), await coordinator.ready, assertActive();
|
|
4160
|
+
},
|
|
4161
|
+
async checkWorkspaceAccess() {
|
|
4162
|
+
assertActive(), await coordinator.context.resolve(), assertActive();
|
|
4163
|
+
},
|
|
4164
|
+
onDispose(callback) {
|
|
4165
|
+
return active2 ? (disposals.add(callback), () => {
|
|
4166
|
+
disposals.delete(callback);
|
|
4167
|
+
}) : (callback(), () => {
|
|
4168
|
+
});
|
|
4169
|
+
},
|
|
4170
|
+
async getSession() {
|
|
4171
|
+
return assertActive(), { data: { session: null }, error: null };
|
|
4172
|
+
},
|
|
4173
|
+
onAuthStateChange(callback) {
|
|
4174
|
+
return callback("INITIAL_SESSION", null), { data: { subscription: { unsubscribe() {
|
|
4175
|
+
} } } };
|
|
4176
|
+
}
|
|
4177
|
+
}), handle2;
|
|
4178
|
+
}
|
|
4179
|
+
|
|
3909
4180
|
function createBrowserAuth(runtime) {
|
|
3910
|
-
let
|
|
3911
|
-
function
|
|
4181
|
+
let coordinators2 = /* @__PURE__ */ new Map();
|
|
4182
|
+
function publish2(c, state) {
|
|
3912
4183
|
c.state = Object.freeze(state);
|
|
3913
4184
|
for (let listener of c.listeners)
|
|
3914
4185
|
try {
|
|
@@ -3924,7 +4195,7 @@ function createBrowserAuth(runtime) {
|
|
|
3924
4195
|
}
|
|
3925
4196
|
}
|
|
3926
4197
|
function expire(c) {
|
|
3927
|
-
!c.active || !c.session && c.state.status === "expired" || (c.revision++, c.timer && clearTimeout(c.timer), c.session = null,
|
|
4198
|
+
!c.active || !c.session && c.state.status === "expired" || (c.revision++, c.timer && clearTimeout(c.timer), c.session = null, publish2(c, { status: "expired" }), notify(c, "SIGNED_OUT"));
|
|
3928
4199
|
}
|
|
3929
4200
|
function accept(c, event, session) {
|
|
3930
4201
|
if (!c.active || event === "INITIAL_SESSION" && c.state.status !== "initializing" || event === "TOKEN_REFRESHED" && !c.session && c.state.status !== "initializing") return;
|
|
@@ -3932,7 +4203,7 @@ function createBrowserAuth(runtime) {
|
|
|
3932
4203
|
replaced && c.revision++, c.timer && clearTimeout(c.timer);
|
|
3933
4204
|
let pending = c.state.pending;
|
|
3934
4205
|
if (!session) {
|
|
3935
|
-
c.session = null,
|
|
4206
|
+
c.session = null, publish2(c, { status: c.state.status === "expired" ? "expired" : "signed_out", ...pending ? { pending } : {} }), notify(c, "SIGNED_OUT");
|
|
3936
4207
|
return;
|
|
3937
4208
|
}
|
|
3938
4209
|
if (!validSession(session)) {
|
|
@@ -3941,7 +4212,7 @@ function createBrowserAuth(runtime) {
|
|
|
3941
4212
|
}
|
|
3942
4213
|
c.session = session;
|
|
3943
4214
|
let email = typeof session.user.email == "string" ? session.user.email.trim() : "", metadata = session.user.user_metadata, name2 = ["name", "full_name", "first_name"].map((key) => metadata?.[key]).find((value) => typeof value == "string" && value.trim())?.trim() || email, account = !replaced && c.state.account?.email === email && c.state.account.displayName === name2 ? c.state.account : Object.freeze({ email, displayName: name2 });
|
|
3944
|
-
notify(c, event),
|
|
4215
|
+
notify(c, event), publish2(c, { status: "signed_in", account, ...pending ? { pending } : {} });
|
|
3945
4216
|
let checkExpiry = () => {
|
|
3946
4217
|
if (!c.active || !c.session) return;
|
|
3947
4218
|
let remaining = c.session.expires_at * 1e3 - Date.now();
|
|
@@ -3988,9 +4259,9 @@ function createBrowserAuth(runtime) {
|
|
|
3988
4259
|
c.unsubscribe = () => subscription.unsubscribe();
|
|
3989
4260
|
let started = c.revision, { data: data3, error } = await c.provider.getSession();
|
|
3990
4261
|
if (!current2(c, origin, started)) return;
|
|
3991
|
-
error ? terminalSessionFailure(error) ? expire(c) : (!c.session || !validSession(c.session)) &&
|
|
4262
|
+
error ? terminalSessionFailure(error) ? expire(c) : (!c.session || !validSession(c.session)) && publish2(c, { status: "unavailable", error: "unavailable" }) : c.state.pending !== "sign_out" && accept(c, "INITIAL_SESSION", data3.session);
|
|
3992
4263
|
} catch {
|
|
3993
|
-
current2(c, origin, revision) &&
|
|
4264
|
+
current2(c, origin, revision) && publish2(c, { status: "unavailable", error: "unavailable" });
|
|
3994
4265
|
}
|
|
3995
4266
|
})(), c;
|
|
3996
4267
|
}
|
|
@@ -4028,8 +4299,10 @@ function createBrowserAuth(runtime) {
|
|
|
4028
4299
|
if (await c.workspaceAccess.result, !current2(c, origin, revision)) throw runtime.failure("stale");
|
|
4029
4300
|
}
|
|
4030
4301
|
return { create() {
|
|
4031
|
-
let origin = globalThis.location?.origin ?? ""
|
|
4032
|
-
|
|
4302
|
+
let origin = globalThis.location?.origin ?? "";
|
|
4303
|
+
if (isAppOrigin(origin) && origin !== "http://127.0.0.1:5176") return createLocalBrowserAuth(origin, runtime.failure);
|
|
4304
|
+
let c = coordinators2.get(origin);
|
|
4305
|
+
c || (c = createCoordinator(origin), coordinators2.set(origin, c));
|
|
4033
4306
|
let coordinator = c;
|
|
4034
4307
|
coordinator.refs++;
|
|
4035
4308
|
let active2 = !0, ownedAction, authorizationId, authorizationGeneration = 0, inspected, observers = /* @__PURE__ */ new Set(), sessionObservers = /* @__PURE__ */ new Set(), disposalObservers = /* @__PURE__ */ new Set(), lastState = coordinator.state, observation = (state) => {
|
|
@@ -4050,15 +4323,15 @@ function createBrowserAuth(runtime) {
|
|
|
4050
4323
|
let marker = {};
|
|
4051
4324
|
coordinator.action = marker, ownedAction = marker;
|
|
4052
4325
|
let revision = coordinator.revision;
|
|
4053
|
-
|
|
4326
|
+
publish2(coordinator, { ...coordinator.state, error: void 0, pending: kind });
|
|
4054
4327
|
try {
|
|
4055
4328
|
if (await coordinator.ready, assertActive(), !coordinator.provider || !coordinator.active || globalThis.location?.origin !== origin) throw runtime.failure("unavailable");
|
|
4056
4329
|
if (!current2(coordinator, origin, revision) || coordinator.action !== marker || (await work(coordinator.provider), assertActive(), coordinator.action !== marker) || !current2(coordinator, origin, revision) && kind !== "verify_code" && kind !== "sign_out") throw runtime.failure("stale");
|
|
4057
4330
|
} catch (error) {
|
|
4058
4331
|
let reason = active2 ? current2(coordinator, origin, revision) ? safeReason(error) ?? "unavailable" : "stale" : "disposed";
|
|
4059
|
-
throw active2 && current2(coordinator, origin, revision) &&
|
|
4332
|
+
throw active2 && current2(coordinator, origin, revision) && publish2(coordinator, { ...coordinator.state, error: reason }), runtime.failure(reason);
|
|
4060
4333
|
} finally {
|
|
4061
|
-
coordinator.action === marker && (coordinator.action = void 0, coordinator.active && (
|
|
4334
|
+
coordinator.action === marker && (coordinator.action = void 0, coordinator.active && (publish2(coordinator, { ...coordinator.state, pending: void 0 }), kind === "sign_out" && coordinator.session && notify(coordinator, "TOKEN_REFRESHED"))), ownedAction === marker && (ownedAction = void 0);
|
|
4062
4335
|
}
|
|
4063
4336
|
}
|
|
4064
4337
|
async function authorize(kind, id3) {
|
|
@@ -4155,7 +4428,7 @@ function createBrowserAuth(runtime) {
|
|
|
4155
4428
|
}
|
|
4156
4429
|
disposalObservers.clear();
|
|
4157
4430
|
for (let listener of sessionObservers) coordinator.sessions.delete(listener);
|
|
4158
|
-
sessionObservers.clear(), --coordinator.refs === 0 && (coordinator.active = !1, coordinator.revision++, coordinator.timer && clearTimeout(coordinator.timer), coordinator.unsubscribe?.(), coordinator.provider?.dispose(), coordinator.provider = void 0, coordinator.session = null, coordinator.listeners.clear(), coordinator.sessions.clear(),
|
|
4431
|
+
sessionObservers.clear(), --coordinator.refs === 0 && (coordinator.active = !1, coordinator.revision++, coordinator.timer && clearTimeout(coordinator.timer), coordinator.unsubscribe?.(), coordinator.provider?.dispose(), coordinator.provider = void 0, coordinator.session = null, coordinator.listeners.clear(), coordinator.sessions.clear(), coordinators2.delete(origin));
|
|
4159
4432
|
}
|
|
4160
4433
|
}
|
|
4161
4434
|
});
|
|
@@ -4728,6 +5001,7 @@ export {
|
|
|
4728
5001
|
question,
|
|
4729
5002
|
recordBlock,
|
|
4730
5003
|
recordsBlock,
|
|
5004
|
+
requireRecords,
|
|
4731
5005
|
resolveAsk,
|
|
4732
5006
|
respond,
|
|
4733
5007
|
richTextBlock,
|