@oddington/sdk 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -9
- package/dist/browser.js +319 -101
- package/dist/index.js +428 -114
- package/dist/types/packages/sdk/src/public.d.ts +1 -1
- package/dist/types/shared/data-contract.d.ts +26 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21709,44 +21709,91 @@ class DataOperationError extends Error {
|
|
|
21709
21709
|
}
|
|
21710
21710
|
}
|
|
21711
21711
|
|
|
21712
|
-
// ../../shared/data-
|
|
21712
|
+
// ../../shared/data-history-input.ts
|
|
21713
21713
|
var invalid = () => {
|
|
21714
21714
|
throw new DataOperationError("invalid_query");
|
|
21715
21715
|
};
|
|
21716
|
-
var
|
|
21717
|
-
function
|
|
21718
|
-
|
|
21716
|
+
var historyText = (value) => typeof value === "string" && !/[\u0000\uD800-\uDFFF]/u.test(value);
|
|
21717
|
+
function historyVersion(value) {
|
|
21718
|
+
return historyText(value) && value.length > 0 && new TextEncoder().encode(value).length <= 1024 && !/[\u0000-\u001f\u007f-\u009f]/.test(value) && !/^[0-9a-f]{40}$/i.test(value);
|
|
21719
|
+
}
|
|
21720
|
+
function historyProperties(value) {
|
|
21721
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
|
|
21722
|
+
return invalid();
|
|
21723
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
21724
|
+
if (Reflect.ownKeys(value).some((key) => typeof key !== "string" || !descriptors[key]?.enumerable || !Object.hasOwn(descriptors[key], "value")))
|
|
21725
|
+
return invalid();
|
|
21726
|
+
return descriptors;
|
|
21727
|
+
}
|
|
21728
|
+
function captureHistoryListOptions(value) {
|
|
21729
|
+
if (value === undefined)
|
|
21730
|
+
return {};
|
|
21731
|
+
const descriptors = historyProperties(value), result = {};
|
|
21732
|
+
if (Object.keys(descriptors).some((key) => !["limit", "before"].includes(key)))
|
|
21733
|
+
return invalid();
|
|
21734
|
+
if (Object.hasOwn(descriptors, "limit")) {
|
|
21735
|
+
const limit = descriptors.limit.value;
|
|
21736
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
21737
|
+
return invalid();
|
|
21738
|
+
result.limit = limit;
|
|
21739
|
+
}
|
|
21740
|
+
if (Object.hasOwn(descriptors, "before")) {
|
|
21741
|
+
const before = descriptors.before.value;
|
|
21742
|
+
if (!historyVersion(before))
|
|
21743
|
+
return invalid();
|
|
21744
|
+
result.before = before;
|
|
21745
|
+
}
|
|
21746
|
+
return result;
|
|
21747
|
+
}
|
|
21748
|
+
function captureHistoryInstant(value) {
|
|
21749
|
+
if (!historyText(value) || value.length > 1024)
|
|
21750
|
+
return invalid();
|
|
21751
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.\d+)?([Zz]|([+-])(\d{2}):(\d{2}))$/.exec(value);
|
|
21752
|
+
if (!match)
|
|
21719
21753
|
return invalid();
|
|
21754
|
+
const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number);
|
|
21755
|
+
const days = new Date(Date.UTC(year, month, 0));
|
|
21756
|
+
days.setUTCFullYear(year);
|
|
21757
|
+
if (year < 1 || month < 1 || month > 12 || day < 1 || day > days.getUTCDate() || hour > 23 || minute > 59 || second > 59 || Number(match[9] ?? 0) > 23 || Number(match[10] ?? 0) > 59)
|
|
21758
|
+
return invalid();
|
|
21759
|
+
return value;
|
|
21760
|
+
}
|
|
21761
|
+
|
|
21762
|
+
// ../../shared/data-search-input.ts
|
|
21763
|
+
var invalid2 = () => {
|
|
21764
|
+
throw new DataOperationError("invalid_query");
|
|
21765
|
+
};
|
|
21766
|
+
function captureRecordsSearchInput(query, options) {
|
|
21767
|
+
if (!historyText(query))
|
|
21768
|
+
return invalid2();
|
|
21720
21769
|
const length = [...query.trim()].length;
|
|
21721
21770
|
if (length < 1 || length > 256)
|
|
21722
|
-
return
|
|
21771
|
+
return invalid2();
|
|
21723
21772
|
if (options === undefined)
|
|
21724
21773
|
return { query };
|
|
21725
|
-
|
|
21726
|
-
|
|
21727
|
-
|
|
21728
|
-
if (Reflect.ownKeys(options).some((key) => typeof key !== "string" || !["collections", "limit"].includes(key) || !descriptors[key]?.enumerable || !Object.hasOwn(descriptors[key], "value")))
|
|
21729
|
-
return invalid();
|
|
21774
|
+
const descriptors = historyProperties(options);
|
|
21775
|
+
if (Object.keys(descriptors).some((key) => !["collections", "limit"].includes(key)))
|
|
21776
|
+
return invalid2();
|
|
21730
21777
|
const captured = {};
|
|
21731
21778
|
if (Object.hasOwn(descriptors, "collections")) {
|
|
21732
21779
|
const supplied = descriptors.collections.value;
|
|
21733
21780
|
if (!Array.isArray(supplied) || supplied.length < 1 || supplied.length > 16 || Reflect.ownKeys(supplied).length !== supplied.length + 1)
|
|
21734
|
-
return
|
|
21781
|
+
return invalid2();
|
|
21735
21782
|
const collections = [];
|
|
21736
21783
|
for (let index = 0;index < supplied.length; index++) {
|
|
21737
21784
|
const descriptor = Object.getOwnPropertyDescriptor(supplied, String(index));
|
|
21738
|
-
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value") || !
|
|
21739
|
-
return
|
|
21785
|
+
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value") || !historyText(descriptor.value))
|
|
21786
|
+
return invalid2();
|
|
21740
21787
|
collections.push(descriptor.value);
|
|
21741
21788
|
}
|
|
21742
21789
|
if (new Set(collections).size !== collections.length)
|
|
21743
|
-
return
|
|
21790
|
+
return invalid2();
|
|
21744
21791
|
captured.collections = collections;
|
|
21745
21792
|
}
|
|
21746
21793
|
if (Object.hasOwn(descriptors, "limit")) {
|
|
21747
21794
|
const supplied = descriptors.limit.value;
|
|
21748
21795
|
if (!Number.isInteger(supplied) || supplied < 1 || supplied > 100)
|
|
21749
|
-
return
|
|
21796
|
+
return invalid2();
|
|
21750
21797
|
captured.limit = supplied;
|
|
21751
21798
|
}
|
|
21752
21799
|
return { query, options: captured };
|
|
@@ -21886,55 +21933,55 @@ class FileOperationError extends Error {
|
|
|
21886
21933
|
var FILE_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
21887
21934
|
var FILE_ORIGINAL_MAX_BYTES = 5 * 1024 ** 3;
|
|
21888
21935
|
function parseFileDescriptor(value) {
|
|
21889
|
-
const
|
|
21936
|
+
const invalid3 = () => {
|
|
21890
21937
|
throw new FileOperationError("unavailable", 503, true);
|
|
21891
21938
|
};
|
|
21892
21939
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
21893
|
-
return
|
|
21940
|
+
return invalid3();
|
|
21894
21941
|
const f = value;
|
|
21895
21942
|
if (Object.keys(f).sort().join(",") !== "details,enrichments,id,mediaType,name,path,sha256,size" || typeof f.id !== "string" || !FILE_ID_PATTERN.test(f.id) || !safeFileName(f.name) || !safeFilePath(f.path) || !Number.isSafeInteger(f.size) || f.size < 0 || f.size > FILE_ORIGINAL_MAX_BYTES || typeof f.sha256 !== "string" || !/^[0-9a-f]{64}$/.test(f.sha256) || !f.enrichments || typeof f.enrichments !== "object" || Array.isArray(f.enrichments) || !f.details || typeof f.details !== "object" || Array.isArray(f.details))
|
|
21896
|
-
return
|
|
21943
|
+
return invalid3();
|
|
21897
21944
|
const d = f.details;
|
|
21898
21945
|
if (d.kind === "other") {
|
|
21899
21946
|
if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream")
|
|
21900
|
-
return
|
|
21947
|
+
return invalid3();
|
|
21901
21948
|
} else if (d.kind === "csv") {
|
|
21902
21949
|
if (Object.keys(d).sort().join(",") !== "dataRows,delimiter,encoding,headerRow,kind" || f.mediaType !== "text/csv" || !["utf-8", "windows-1252"].includes(d.encoding) || ![",", ";", "\t"].includes(d.delimiter) || !Number.isSafeInteger(d.headerRow) || d.headerRow < 1 || !Number.isSafeInteger(d.dataRows) || d.dataRows < 0)
|
|
21903
|
-
return
|
|
21950
|
+
return invalid3();
|
|
21904
21951
|
} else
|
|
21905
|
-
return
|
|
21952
|
+
return invalid3();
|
|
21906
21953
|
for (const [name, descriptor] of Object.entries(f.enrichments)) {
|
|
21907
21954
|
if (!safeEnrichmentName(name))
|
|
21908
|
-
return
|
|
21955
|
+
return invalid3();
|
|
21909
21956
|
parseEnrichmentDescriptor(descriptor);
|
|
21910
21957
|
}
|
|
21911
21958
|
if (new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024)
|
|
21912
|
-
return
|
|
21959
|
+
return invalid3();
|
|
21913
21960
|
return f;
|
|
21914
21961
|
}
|
|
21915
21962
|
function parseEnrichmentDescriptor(value) {
|
|
21916
|
-
const
|
|
21963
|
+
const invalid3 = () => {
|
|
21917
21964
|
throw new FileOperationError("unavailable", 503, true);
|
|
21918
21965
|
};
|
|
21919
21966
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
21920
|
-
return
|
|
21967
|
+
return invalid3();
|
|
21921
21968
|
const d = value;
|
|
21922
21969
|
if (Object.keys(d).sort().join(",") !== "mediaType,sha256,size" || !["application/octet-stream", "text/plain", "text/markdown", "application/json"].includes(d.mediaType) || !Number.isSafeInteger(d.size) || d.size < 0 || d.size > 16 * 1024 * 1024 || typeof d.sha256 !== "string" || !/^[0-9a-f]{64}$/.test(d.sha256))
|
|
21923
|
-
return
|
|
21970
|
+
return invalid3();
|
|
21924
21971
|
return d;
|
|
21925
21972
|
}
|
|
21926
21973
|
function safeEnrichmentName(value) {
|
|
21927
21974
|
return safeFileName(value) && !/^original(?:\.|$)/i.test(value);
|
|
21928
21975
|
}
|
|
21929
21976
|
function parseFileEnrichMetadata(value, maxBytes) {
|
|
21930
|
-
const
|
|
21977
|
+
const invalid3 = () => {
|
|
21931
21978
|
throw new FileOperationError("invalid_input", 400);
|
|
21932
21979
|
};
|
|
21933
21980
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
21934
|
-
return
|
|
21981
|
+
return invalid3();
|
|
21935
21982
|
const d = value;
|
|
21936
21983
|
if (Object.keys(d).some((key) => !["name", "size", "mediaType", "replace"].includes(key)) || !safeEnrichmentName(d.name) || !Number.isSafeInteger(d.size) || d.size < 0 || d.mediaType !== undefined && (typeof d.mediaType !== "string" || d.mediaType.length > 255 || /[\u0000-\u001f\u007f]/.test(d.mediaType)) || d.replace !== undefined && (typeof d.replace !== "string" || !/^[0-9a-f]{64}$/.test(d.replace)))
|
|
21937
|
-
return
|
|
21984
|
+
return invalid3();
|
|
21938
21985
|
if (d.size > maxBytes)
|
|
21939
21986
|
throw new FileOperationError("request_too_large", 413);
|
|
21940
21987
|
return d;
|
|
@@ -21946,37 +21993,37 @@ function safeFilePath(value) {
|
|
|
21946
21993
|
return typeof value === "string" && value.length <= 1024 && value.split("/").every(safeFileName);
|
|
21947
21994
|
}
|
|
21948
21995
|
function parseFileCreateMetadata(value, maxBytes) {
|
|
21949
|
-
const
|
|
21996
|
+
const invalid3 = () => {
|
|
21950
21997
|
throw new FileOperationError("invalid_input", 400);
|
|
21951
21998
|
};
|
|
21952
21999
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
21953
|
-
return
|
|
22000
|
+
return invalid3();
|
|
21954
22001
|
const input = value;
|
|
21955
22002
|
if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "size", "requestKey"].includes(key)))
|
|
21956
|
-
return
|
|
22003
|
+
return invalid3();
|
|
21957
22004
|
const path = input.path === undefined ? "Files" : input.path;
|
|
21958
22005
|
if (!safeFileName(input.name) || !safeFilePath(path))
|
|
21959
|
-
return
|
|
22006
|
+
return invalid3();
|
|
21960
22007
|
if (input.storage !== undefined && input.storage !== "remote" && input.storage !== "local")
|
|
21961
|
-
return
|
|
22008
|
+
return invalid3();
|
|
21962
22009
|
if (!Number.isSafeInteger(input.size) || input.size < 0)
|
|
21963
|
-
return
|
|
22010
|
+
return invalid3();
|
|
21964
22011
|
if (input.size > maxBytes)
|
|
21965
22012
|
throw new FileOperationError("request_too_large", 413);
|
|
21966
22013
|
if (typeof input.requestKey !== "string" || input.requestKey.length < 1 || input.requestKey.length > 256 || input.requestKey !== input.requestKey.trim() || /[\u0000-\u001f\u007f]/.test(input.requestKey))
|
|
21967
|
-
return
|
|
22014
|
+
return invalid3();
|
|
21968
22015
|
let csv;
|
|
21969
22016
|
if (input.csv !== undefined) {
|
|
21970
22017
|
if (!input.csv || typeof input.csv !== "object" || Array.isArray(input.csv))
|
|
21971
|
-
return
|
|
22018
|
+
return invalid3();
|
|
21972
22019
|
const hints = input.csv;
|
|
21973
22020
|
if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key)))
|
|
21974
|
-
return
|
|
22021
|
+
return invalid3();
|
|
21975
22022
|
const encoding = hints.encoding === undefined ? "utf-8" : hints.encoding;
|
|
21976
22023
|
const delimiter = hints.delimiter === undefined ? "," : hints.delimiter;
|
|
21977
22024
|
const headerRow = hints.headerRow === undefined ? 1 : hints.headerRow;
|
|
21978
22025
|
if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", "\t"].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5)
|
|
21979
|
-
return
|
|
22026
|
+
return invalid3();
|
|
21980
22027
|
csv = { encoding, delimiter, headerRow };
|
|
21981
22028
|
}
|
|
21982
22029
|
return {
|
|
@@ -22030,7 +22077,7 @@ function privateRoutineRequest(environment = typeof __ODDINGTON_BROWSER__ !== "u
|
|
|
22030
22077
|
const tcp = /^tcp:\/\/127\.0\.0\.1:([1-9][0-9]{0,4})$/.exec(socket);
|
|
22031
22078
|
const endpoint = tcp ? { hostname: "127.0.0.1", port: Number(tcp[1]) } : { socketPath: socket };
|
|
22032
22079
|
const id2 = crypto.randomUUID();
|
|
22033
|
-
if (init.body instanceof ReadableStream) {
|
|
22080
|
+
if (init.body instanceof ReadableStream || suffix === "" && init.method === "POST") {
|
|
22034
22081
|
await new Promise((resolve, reject) => {
|
|
22035
22082
|
const admission = httpRequest({
|
|
22036
22083
|
...endpoint,
|
|
@@ -22432,15 +22479,16 @@ var data = {
|
|
|
22432
22479
|
async function send(input) {
|
|
22433
22480
|
const context = await resolveDataContext();
|
|
22434
22481
|
try {
|
|
22435
|
-
|
|
22482
|
+
const envelope = { repository, ...input };
|
|
22483
|
+
checkDataRequestSize(envelope);
|
|
22436
22484
|
if ("local" in context)
|
|
22437
|
-
return await context.local("data/query",
|
|
22485
|
+
return await context.local("data/query", envelope);
|
|
22438
22486
|
const response = await fetch(context.url, {
|
|
22439
22487
|
method: "POST",
|
|
22440
22488
|
redirect: "error",
|
|
22441
22489
|
cache: "no-store",
|
|
22442
22490
|
headers: { "content-type": "application/json", ...context.headers },
|
|
22443
|
-
body: JSON.stringify(
|
|
22491
|
+
body: JSON.stringify(envelope)
|
|
22444
22492
|
});
|
|
22445
22493
|
const result = await response.json();
|
|
22446
22494
|
if (!response.ok) {
|
|
@@ -22460,13 +22508,11 @@ var data = {
|
|
|
22460
22508
|
},
|
|
22461
22509
|
records: {
|
|
22462
22510
|
select: (query) => send({ operation: "records.select", query }),
|
|
22463
|
-
search: (query, options) => {
|
|
22464
|
-
|
|
22465
|
-
|
|
22466
|
-
|
|
22467
|
-
|
|
22468
|
-
}
|
|
22469
|
-
}
|
|
22511
|
+
search: async (query, options) => send({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
|
|
22512
|
+
},
|
|
22513
|
+
history: {
|
|
22514
|
+
list: async (options) => send({ operation: "history.list", options: captureHistoryListOptions(options) }),
|
|
22515
|
+
at: async (instant) => send({ operation: "history.at", instant: captureHistoryInstant(instant) })
|
|
22470
22516
|
},
|
|
22471
22517
|
changes() {
|
|
22472
22518
|
let updates = [], creates = [], deletes = [], publicationId;
|
|
@@ -22574,7 +22620,7 @@ var TIMEOUT_MS = 30000;
|
|
|
22574
22620
|
var MAX_ACTIVE = 4;
|
|
22575
22621
|
var ATTEMPTS = 2;
|
|
22576
22622
|
var active = 0;
|
|
22577
|
-
var
|
|
22623
|
+
var invalid3 = () => new FileOperationError("invalid_input", 400);
|
|
22578
22624
|
var unavailable = () => new FileOperationError("unavailable", 503, true);
|
|
22579
22625
|
var failures = {
|
|
22580
22626
|
400: ["invalid_input", "unsupported_context"],
|
|
@@ -22598,7 +22644,7 @@ async function boundedBytes(stream, limit) {
|
|
|
22598
22644
|
if (done)
|
|
22599
22645
|
break;
|
|
22600
22646
|
if (!(value instanceof Uint8Array))
|
|
22601
|
-
throw
|
|
22647
|
+
throw invalid3();
|
|
22602
22648
|
size += value.byteLength;
|
|
22603
22649
|
if (size > limit)
|
|
22604
22650
|
throw new FileOperationError("request_too_large", 413);
|
|
@@ -22780,7 +22826,7 @@ async function send(suffix, init, descriptor, initial, parent) {
|
|
|
22780
22826
|
}
|
|
22781
22827
|
function idPath(id2) {
|
|
22782
22828
|
if (typeof id2 !== "string" || !FILE_ID_PATTERN.test(id2))
|
|
22783
|
-
throw
|
|
22829
|
+
throw invalid3();
|
|
22784
22830
|
return `/${id2}`;
|
|
22785
22831
|
}
|
|
22786
22832
|
async function multipartCreate(input, metadata, exchange, release = () => {
|
|
@@ -22844,12 +22890,12 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
22844
22890
|
offset = 0;
|
|
22845
22891
|
const value2 = await next();
|
|
22846
22892
|
if (value2.done)
|
|
22847
|
-
throw
|
|
22893
|
+
throw invalid3();
|
|
22848
22894
|
if (!(value2.value instanceof Uint8Array))
|
|
22849
|
-
throw
|
|
22895
|
+
throw invalid3();
|
|
22850
22896
|
chunk = value2.value;
|
|
22851
22897
|
if (chunk.byteLength > metadata.size - sent - filled)
|
|
22852
|
-
throw
|
|
22898
|
+
throw invalid3();
|
|
22853
22899
|
}
|
|
22854
22900
|
const take = Math.min(length - filled, chunk.byteLength - offset);
|
|
22855
22901
|
part.set(chunk.subarray(offset, offset + take), filled);
|
|
@@ -22862,7 +22908,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
22862
22908
|
}
|
|
22863
22909
|
}
|
|
22864
22910
|
if (part.byteLength !== length)
|
|
22865
|
-
throw
|
|
22911
|
+
throw invalid3();
|
|
22866
22912
|
if (reader && sent + length === metadata.size) {
|
|
22867
22913
|
lastProgress = Date.now();
|
|
22868
22914
|
for (;; ) {
|
|
@@ -22870,7 +22916,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
22870
22916
|
if (value2.done)
|
|
22871
22917
|
break;
|
|
22872
22918
|
if (!(value2.value instanceof Uint8Array) || value2.value.byteLength)
|
|
22873
|
-
throw
|
|
22919
|
+
throw invalid3();
|
|
22874
22920
|
}
|
|
22875
22921
|
}
|
|
22876
22922
|
const value = await request((signal) => exchange(`${route}/part`, {
|
|
@@ -22890,7 +22936,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
|
|
|
22890
22936
|
for (const name of Object.keys(upload.file.enrichments)) {
|
|
22891
22937
|
const bytes = await request(() => upload.enrichment(name));
|
|
22892
22938
|
if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES)
|
|
22893
|
-
throw
|
|
22939
|
+
throw invalid3();
|
|
22894
22940
|
await request((signal) => exchange(`${route}/enrichments/${encodeURIComponent(name)}`, {
|
|
22895
22941
|
method: "POST",
|
|
22896
22942
|
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket },
|
|
@@ -22944,7 +22990,7 @@ function contentPath(id2, name) {
|
|
|
22944
22990
|
if (name === undefined)
|
|
22945
22991
|
return `${path}/content`;
|
|
22946
22992
|
if (!safeEnrichmentName(name))
|
|
22947
|
-
throw
|
|
22993
|
+
throw invalid3();
|
|
22948
22994
|
return `${path}/enrichments/${encodeURIComponent(name)}/content`;
|
|
22949
22995
|
}
|
|
22950
22996
|
async function read(id2, names) {
|
|
@@ -22955,16 +23001,16 @@ async function read(id2, names) {
|
|
|
22955
23001
|
return operation((context2, signal) => send(path, { method: "GET" }, false, context2, signal), context);
|
|
22956
23002
|
}
|
|
22957
23003
|
if (!Array.isArray(names))
|
|
22958
|
-
throw
|
|
23004
|
+
throw invalid3();
|
|
22959
23005
|
const distinct = [];
|
|
22960
23006
|
const seen = new Set;
|
|
22961
23007
|
for (const name of names) {
|
|
22962
23008
|
if (typeof name !== "string" || !safeEnrichmentName(name))
|
|
22963
|
-
throw
|
|
23009
|
+
throw invalid3();
|
|
22964
23010
|
if (seen.has(name))
|
|
22965
23011
|
continue;
|
|
22966
23012
|
if (seen.size === 16)
|
|
22967
|
-
throw
|
|
23013
|
+
throw invalid3();
|
|
22968
23014
|
seen.add(name);
|
|
22969
23015
|
distinct.push(name);
|
|
22970
23016
|
}
|
|
@@ -22998,15 +23044,15 @@ var files = {
|
|
|
22998
23044
|
async create(input, options) {
|
|
22999
23045
|
const context = await resolveFilesContext();
|
|
23000
23046
|
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "size", "path", "name", "storage", "csv"].includes(key)) || options !== undefined && (!options || typeof options !== "object" || Array.isArray(options) || Object.keys(options).some((key) => key !== "requestKey")))
|
|
23001
|
-
throw
|
|
23047
|
+
throw invalid3();
|
|
23002
23048
|
const blob = input.file instanceof Blob;
|
|
23003
23049
|
const array2 = input.file instanceof Uint8Array;
|
|
23004
23050
|
const stream = input.file instanceof ReadableStream;
|
|
23005
23051
|
if (!blob && !array2 && !stream)
|
|
23006
|
-
throw
|
|
23052
|
+
throw invalid3();
|
|
23007
23053
|
const intrinsic = blob ? input.file.size : array2 ? input.file.byteLength : undefined;
|
|
23008
23054
|
if (intrinsic !== undefined && input.size !== undefined && input.size !== intrinsic)
|
|
23009
|
-
throw
|
|
23055
|
+
throw invalid3();
|
|
23010
23056
|
let name = input.name;
|
|
23011
23057
|
if (name === undefined && blob && "name" in input.file && typeof input.file.name === "string") {
|
|
23012
23058
|
name = typeof globalThis.File !== "undefined" && input.file instanceof globalThis.File ? input.file.name : input.file.name.split(/[\\/]/).at(-1);
|
|
@@ -23023,7 +23069,7 @@ var files = {
|
|
|
23023
23069
|
throw new FileOperationError("unsupported_context", 400);
|
|
23024
23070
|
const header = encodeURIComponent(JSON.stringify(metadata));
|
|
23025
23071
|
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES)
|
|
23026
|
-
throw
|
|
23072
|
+
throw invalid3();
|
|
23027
23073
|
if (active >= MAX_ACTIVE)
|
|
23028
23074
|
throw new FileOperationError("capacity", 429, true);
|
|
23029
23075
|
active++;
|
|
@@ -23057,7 +23103,7 @@ var files = {
|
|
|
23057
23103
|
try {
|
|
23058
23104
|
const bytes = array2 ? input.file.slice() : await boundedBytes(blob ? input.file.stream() : input.file, metadata.size);
|
|
23059
23105
|
if (bytes.byteLength !== metadata.size)
|
|
23060
|
-
throw
|
|
23106
|
+
throw invalid3();
|
|
23061
23107
|
if (signal.aborted)
|
|
23062
23108
|
throw unavailable();
|
|
23063
23109
|
return await send("", {
|
|
@@ -23075,7 +23121,7 @@ var files = {
|
|
|
23075
23121
|
async enrich(input) {
|
|
23076
23122
|
const context = await resolveFilesContext();
|
|
23077
23123
|
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "name", "content", "mediaType", "replace"].includes(key)) || typeof input.content !== "string" && !(input.content instanceof Uint8Array))
|
|
23078
|
-
throw
|
|
23124
|
+
throw invalid3();
|
|
23079
23125
|
const path = `${idPath(input.file)}/enrichments`;
|
|
23080
23126
|
if (typeof input.content === "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
|
|
23081
23127
|
throw new FileOperationError("request_too_large", 413);
|
|
@@ -23097,7 +23143,7 @@ var files = {
|
|
|
23097
23143
|
}, MAX_BYTES);
|
|
23098
23144
|
const header = encodeURIComponent(JSON.stringify(metadata));
|
|
23099
23145
|
if (new TextEncoder().encode(header).byteLength > METADATA_BYTES)
|
|
23100
|
-
throw
|
|
23146
|
+
throw invalid3();
|
|
23101
23147
|
const result2 = await send(path, { method: "POST", headers: {
|
|
23102
23148
|
"content-type": "application/octet-stream",
|
|
23103
23149
|
"x-oddington-enrichment": header
|
|
@@ -23114,9 +23160,16 @@ var files = {
|
|
|
23114
23160
|
};
|
|
23115
23161
|
// src/app-context.ts
|
|
23116
23162
|
var sessionKey = "_os.app.session";
|
|
23163
|
+
var responseChecks = new WeakMap;
|
|
23117
23164
|
|
|
23118
23165
|
class AppResponseReadError extends Error {
|
|
23119
23166
|
}
|
|
23167
|
+
|
|
23168
|
+
class AppContextDenied extends Error {
|
|
23169
|
+
}
|
|
23170
|
+
|
|
23171
|
+
class AppRenewalUnavailable extends Error {
|
|
23172
|
+
}
|
|
23120
23173
|
async function appResponse(response, maximum, signal) {
|
|
23121
23174
|
if (signal.aborted || !response.body || response.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() !== "application/json")
|
|
23122
23175
|
throw new Error;
|
|
@@ -23137,8 +23190,13 @@ async function appResponse(response, maximum, signal) {
|
|
|
23137
23190
|
}
|
|
23138
23191
|
if (signal.aborted)
|
|
23139
23192
|
throw new Error;
|
|
23140
|
-
if (chunk.done)
|
|
23141
|
-
|
|
23193
|
+
if (chunk.done) {
|
|
23194
|
+
const value = JSON.parse(text3 + decoder.decode());
|
|
23195
|
+
await responseChecks.get(response)?.(value);
|
|
23196
|
+
if (signal.aborted)
|
|
23197
|
+
throw new Error;
|
|
23198
|
+
return value;
|
|
23199
|
+
}
|
|
23142
23200
|
bytes += chunk.value.byteLength;
|
|
23143
23201
|
if (bytes > maximum) {
|
|
23144
23202
|
abort();
|
|
@@ -23165,38 +23223,239 @@ function appContext(origin, active2) {
|
|
|
23165
23223
|
let denied = false;
|
|
23166
23224
|
const controller = new AbortController;
|
|
23167
23225
|
let expiry;
|
|
23168
|
-
|
|
23169
|
-
|
|
23226
|
+
let startup;
|
|
23227
|
+
let renewalTimer;
|
|
23228
|
+
let renewal;
|
|
23229
|
+
let observation;
|
|
23230
|
+
let resolution2;
|
|
23231
|
+
let disposed = false;
|
|
23232
|
+
const stored = () => globalThis.localStorage.getItem(sessionKey);
|
|
23233
|
+
const alive = () => {
|
|
23234
|
+
try {
|
|
23235
|
+
return !denied && !disposed && active2() && globalThis.location.origin === origin && (!binding || binding.expiresAt > Date.now());
|
|
23236
|
+
} catch {
|
|
23237
|
+
return false;
|
|
23238
|
+
}
|
|
23239
|
+
};
|
|
23240
|
+
const cancel = () => {
|
|
23170
23241
|
controller.abort();
|
|
23171
23242
|
clearTimeout(expiry);
|
|
23243
|
+
clearTimeout(startup);
|
|
23244
|
+
clearTimeout(renewalTimer);
|
|
23172
23245
|
clearInterval(monitor);
|
|
23246
|
+
globalThis.removeEventListener?.("storage", storageChanged);
|
|
23247
|
+
};
|
|
23248
|
+
const invalidate = () => {
|
|
23249
|
+
denied = true;
|
|
23250
|
+
cancel();
|
|
23173
23251
|
try {
|
|
23174
|
-
if (active2() && globalThis.location.origin === origin && (!credential || globalThis.localStorage.getItem(sessionKey) === credential)) {
|
|
23252
|
+
if (!disposed && active2() && globalThis.location.origin === origin && (!credential || globalThis.localStorage.getItem(sessionKey) === credential)) {
|
|
23175
23253
|
globalThis.localStorage.removeItem(sessionKey);
|
|
23176
23254
|
}
|
|
23177
23255
|
} catch {}
|
|
23178
23256
|
};
|
|
23179
23257
|
const current = () => {
|
|
23180
23258
|
try {
|
|
23181
|
-
return
|
|
23259
|
+
return alive() && stored() === credential;
|
|
23182
23260
|
} catch {
|
|
23183
23261
|
return false;
|
|
23184
23262
|
}
|
|
23185
23263
|
};
|
|
23186
|
-
const
|
|
23187
|
-
|
|
23264
|
+
const sameSession = (value) => !binding || value.appId === binding.appId && value.memberId === binding.memberId && value.workspace === binding.workspace && value.sessionId === binding.sessionId;
|
|
23265
|
+
const bounded = (value) => validBinding(value) && value.expiresAt > Date.now() && value.expiresAt <= Date.now() + 600000 && sameSession(value);
|
|
23266
|
+
async function proof(candidate, signal = controller.signal) {
|
|
23267
|
+
if (!alive() || !/^[A-Za-z0-9_-]{43}$/.test(candidate))
|
|
23268
|
+
throw new Error;
|
|
23269
|
+
const url = `${origin}/_os/app/context`;
|
|
23270
|
+
const response = await fetch(url, {
|
|
23271
|
+
credentials: "omit",
|
|
23272
|
+
redirect: "error",
|
|
23273
|
+
cache: "no-store",
|
|
23274
|
+
referrerPolicy: "no-referrer",
|
|
23275
|
+
headers: { authorization: `Bearer ${candidate}` },
|
|
23276
|
+
signal
|
|
23277
|
+
});
|
|
23278
|
+
if (response.redirected || response.url && response.url !== url)
|
|
23279
|
+
throw new Error;
|
|
23280
|
+
if (response.status === 401 || response.status === 403)
|
|
23281
|
+
throw new AppContextDenied;
|
|
23282
|
+
if (!response.ok)
|
|
23283
|
+
throw new Error;
|
|
23284
|
+
const value = await appResponse(response, 4096, signal);
|
|
23285
|
+
if (!alive() || !bounded(value))
|
|
23286
|
+
throw new Error;
|
|
23287
|
+
return value;
|
|
23288
|
+
}
|
|
23289
|
+
function install(value, candidate) {
|
|
23290
|
+
binding = { ...value };
|
|
23291
|
+
credential = candidate;
|
|
23292
|
+
clearTimeout(expiry);
|
|
23293
|
+
clearTimeout(renewalTimer);
|
|
23294
|
+
const remaining = binding.expiresAt - Date.now();
|
|
23295
|
+
expiry = setTimeout(invalidate, remaining);
|
|
23296
|
+
renewalTimer = setTimeout(() => {
|
|
23297
|
+
renew();
|
|
23298
|
+
}, remaining - Math.min(60000, remaining / 5));
|
|
23299
|
+
}
|
|
23300
|
+
async function synchronize() {
|
|
23301
|
+
if (!alive())
|
|
23302
|
+
throw new Error;
|
|
23303
|
+
if (!credential)
|
|
23304
|
+
return;
|
|
23305
|
+
if (stored() === credential)
|
|
23306
|
+
return;
|
|
23307
|
+
if (!binding)
|
|
23308
|
+
throw new Error;
|
|
23309
|
+
if (observation)
|
|
23310
|
+
return observation;
|
|
23311
|
+
observation = (async () => {
|
|
23312
|
+
while (alive()) {
|
|
23313
|
+
const candidate = stored();
|
|
23314
|
+
if (!candidate)
|
|
23315
|
+
throw new Error;
|
|
23316
|
+
let value;
|
|
23317
|
+
try {
|
|
23318
|
+
value = await proof(candidate);
|
|
23319
|
+
} catch {
|
|
23320
|
+
if (stored() !== candidate)
|
|
23321
|
+
continue;
|
|
23322
|
+
throw new Error;
|
|
23323
|
+
}
|
|
23324
|
+
if (stored() !== candidate)
|
|
23325
|
+
continue;
|
|
23326
|
+
install(value, candidate);
|
|
23327
|
+
return;
|
|
23328
|
+
}
|
|
23329
|
+
throw new Error;
|
|
23330
|
+
})();
|
|
23331
|
+
try {
|
|
23332
|
+
await observation;
|
|
23333
|
+
} catch {
|
|
23334
|
+
invalidate();
|
|
23335
|
+
throw new Error("Local app context unavailable.");
|
|
23336
|
+
} finally {
|
|
23337
|
+
observation = undefined;
|
|
23338
|
+
}
|
|
23339
|
+
}
|
|
23340
|
+
async function renew() {
|
|
23341
|
+
if (renewal || !binding || !alive())
|
|
23342
|
+
return;
|
|
23343
|
+
renewal = (async () => {
|
|
23344
|
+
const deadline = binding.expiresAt;
|
|
23345
|
+
const requestController = new AbortController;
|
|
23346
|
+
const abort = () => requestController.abort();
|
|
23347
|
+
controller.signal.addEventListener("abort", abort, { once: true });
|
|
23348
|
+
const timeout = setTimeout(abort, Math.min(20000, deadline - Date.now()));
|
|
23349
|
+
const previous = credential;
|
|
23350
|
+
try {
|
|
23351
|
+
await synchronize();
|
|
23352
|
+
if (credential !== previous)
|
|
23353
|
+
return;
|
|
23354
|
+
const url = `${origin}/_os/app/renew`;
|
|
23355
|
+
let response;
|
|
23356
|
+
try {
|
|
23357
|
+
response = await fetch(url, {
|
|
23358
|
+
method: "POST",
|
|
23359
|
+
credentials: "omit",
|
|
23360
|
+
redirect: "error",
|
|
23361
|
+
cache: "no-store",
|
|
23362
|
+
referrerPolicy: "no-referrer",
|
|
23363
|
+
signal: requestController.signal,
|
|
23364
|
+
headers: { authorization: `Bearer ${previous}` }
|
|
23365
|
+
});
|
|
23366
|
+
} catch {
|
|
23367
|
+
throw new AppRenewalUnavailable;
|
|
23368
|
+
}
|
|
23369
|
+
if (response.redirected || response.url && response.url !== url)
|
|
23370
|
+
throw new Error;
|
|
23371
|
+
const value = await appResponse(response, 4096, requestController.signal);
|
|
23372
|
+
if (response.status === 503 && value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).join(",") === "error" && "error" in value && value.error === "renewal_unavailable")
|
|
23373
|
+
throw new AppRenewalUnavailable;
|
|
23374
|
+
if (response.status === 403 && value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).join(",") === "error" && "error" in value && value.error === "renewal_conflict") {
|
|
23375
|
+
while (alive() && stored() === previous && !requestController.signal.aborted) {
|
|
23376
|
+
await new Promise((resolve2, reject) => {
|
|
23377
|
+
const abortWait = () => {
|
|
23378
|
+
clearTimeout(timer);
|
|
23379
|
+
reject(new Error);
|
|
23380
|
+
};
|
|
23381
|
+
const timer = setTimeout(() => {
|
|
23382
|
+
requestController.signal.removeEventListener("abort", abortWait);
|
|
23383
|
+
resolve2();
|
|
23384
|
+
}, 100);
|
|
23385
|
+
requestController.signal.addEventListener("abort", abortWait, { once: true });
|
|
23386
|
+
});
|
|
23387
|
+
}
|
|
23388
|
+
if (requestController.signal.aborted)
|
|
23389
|
+
throw new Error;
|
|
23390
|
+
await synchronize();
|
|
23391
|
+
return;
|
|
23392
|
+
}
|
|
23393
|
+
if (!response.ok)
|
|
23394
|
+
throw new Error;
|
|
23395
|
+
if (!alive() || Date.now() >= deadline || !value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).sort().join(",") !== "context,credential")
|
|
23396
|
+
throw new Error;
|
|
23397
|
+
const result2 = value;
|
|
23398
|
+
if (!bounded(result2.context) || typeof result2.credential !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(result2.credential) || result2.credential === previous)
|
|
23399
|
+
throw new Error;
|
|
23400
|
+
if (stored() !== previous) {
|
|
23401
|
+
await synchronize();
|
|
23402
|
+
return;
|
|
23403
|
+
}
|
|
23404
|
+
globalThis.localStorage.setItem(sessionKey, result2.credential);
|
|
23405
|
+
install(result2.context, result2.credential);
|
|
23406
|
+
} catch (error) {
|
|
23407
|
+
try {
|
|
23408
|
+
if (alive() && stored() && stored() !== previous) {
|
|
23409
|
+
await synchronize();
|
|
23410
|
+
return;
|
|
23411
|
+
}
|
|
23412
|
+
} catch {}
|
|
23413
|
+
try {
|
|
23414
|
+
if (alive() && stored() && stored() !== previous) {
|
|
23415
|
+
await synchronize();
|
|
23416
|
+
return;
|
|
23417
|
+
}
|
|
23418
|
+
} catch {}
|
|
23419
|
+
if ((error instanceof AppRenewalUnavailable || error instanceof AppResponseReadError || requestController.signal.aborted) && current() && Date.now() < deadline) {
|
|
23420
|
+
renewalTimer = setTimeout(() => {
|
|
23421
|
+
renew();
|
|
23422
|
+
}, Math.min(5000, (deadline - Date.now()) / 5));
|
|
23423
|
+
} else
|
|
23424
|
+
invalidate();
|
|
23425
|
+
} finally {
|
|
23426
|
+
clearTimeout(timeout);
|
|
23427
|
+
controller.signal.removeEventListener("abort", abort);
|
|
23428
|
+
}
|
|
23429
|
+
})();
|
|
23430
|
+
try {
|
|
23431
|
+
await renewal;
|
|
23432
|
+
} finally {
|
|
23433
|
+
renewal = undefined;
|
|
23434
|
+
}
|
|
23435
|
+
}
|
|
23436
|
+
const storageChanged = () => {
|
|
23437
|
+
if (!credential)
|
|
23438
|
+
return;
|
|
23439
|
+
if (!alive()) {
|
|
23188
23440
|
invalidate();
|
|
23441
|
+
return;
|
|
23442
|
+
}
|
|
23443
|
+
synchronize().catch(invalidate);
|
|
23444
|
+
};
|
|
23445
|
+
const monitor = setInterval(() => {
|
|
23446
|
+
storageChanged();
|
|
23189
23447
|
}, 100);
|
|
23448
|
+
globalThis.addEventListener?.("storage", storageChanged);
|
|
23190
23449
|
const dispose = () => {
|
|
23191
|
-
|
|
23192
|
-
|
|
23193
|
-
clearInterval(monitor);
|
|
23450
|
+
disposed = true;
|
|
23451
|
+
cancel();
|
|
23194
23452
|
};
|
|
23195
23453
|
async function requestData(operation2, input) {
|
|
23196
23454
|
try {
|
|
23197
23455
|
if (operation2 !== "data/query" || !current())
|
|
23198
23456
|
throw new Error;
|
|
23199
23457
|
const url = `${origin}/_os/app/data`;
|
|
23458
|
+
const admitted = credential;
|
|
23200
23459
|
const response = await fetch(url, {
|
|
23201
23460
|
method: "POST",
|
|
23202
23461
|
credentials: "omit",
|
|
@@ -23207,13 +23466,20 @@ function appContext(origin, active2) {
|
|
|
23207
23466
|
headers: { "content-type": "application/json", authorization: `Bearer ${credential}` },
|
|
23208
23467
|
body: JSON.stringify(input)
|
|
23209
23468
|
});
|
|
23469
|
+
await synchronize();
|
|
23470
|
+
while (alive() && stored() !== credential)
|
|
23471
|
+
await synchronize();
|
|
23210
23472
|
if (!current() || response.redirected || response.url && response.url !== url)
|
|
23211
23473
|
throw new Error;
|
|
23212
23474
|
if (response.status === 401 || response.status === 403) {
|
|
23213
|
-
|
|
23475
|
+
if (admitted === credential)
|
|
23476
|
+
invalidate();
|
|
23214
23477
|
throw new DataOperationError("access_denied");
|
|
23215
23478
|
}
|
|
23216
23479
|
const result2 = await appResponse(response, Number.MAX_SAFE_INTEGER, controller.signal);
|
|
23480
|
+
await synchronize();
|
|
23481
|
+
while (alive() && stored() !== credential)
|
|
23482
|
+
await synchronize();
|
|
23217
23483
|
if (!current())
|
|
23218
23484
|
throw new Error;
|
|
23219
23485
|
if (!response.ok)
|
|
@@ -23233,6 +23499,7 @@ function appContext(origin, active2) {
|
|
|
23233
23499
|
throw new Error("Local app context unavailable.");
|
|
23234
23500
|
}
|
|
23235
23501
|
const url = `${origin}/_os/app/routines/${encodeURIComponent(key)}/${suffix}`;
|
|
23502
|
+
const admitted = credential;
|
|
23236
23503
|
const response = await fetch(url, {
|
|
23237
23504
|
...init,
|
|
23238
23505
|
credentials: "omit",
|
|
@@ -23242,61 +23509,107 @@ function appContext(origin, active2) {
|
|
|
23242
23509
|
signal: controller.signal,
|
|
23243
23510
|
headers: { ...init.body === undefined ? {} : { "content-type": "application/json" }, authorization: `Bearer ${credential}` }
|
|
23244
23511
|
});
|
|
23512
|
+
await synchronize();
|
|
23513
|
+
while (alive() && stored() !== credential)
|
|
23514
|
+
await synchronize();
|
|
23245
23515
|
if (!current() || response.redirected || response.url && response.url !== url) {
|
|
23246
23516
|
invalidate();
|
|
23247
23517
|
throw new Error("Local app context unavailable.");
|
|
23248
23518
|
}
|
|
23249
|
-
if (response.status === 401 || response.status === 403)
|
|
23519
|
+
if ((response.status === 401 || response.status === 403) && admitted === credential)
|
|
23250
23520
|
invalidate();
|
|
23521
|
+
responseChecks.set(response, async (value) => {
|
|
23522
|
+
await synchronize();
|
|
23523
|
+
while (alive() && stored() !== credential)
|
|
23524
|
+
await synchronize();
|
|
23525
|
+
if (admitted === credential && value && typeof value === "object" && "error" in value && value.error === "authority_unavailable")
|
|
23526
|
+
invalidate();
|
|
23527
|
+
});
|
|
23251
23528
|
return response;
|
|
23252
23529
|
}
|
|
23253
|
-
|
|
23530
|
+
function context() {
|
|
23531
|
+
const issued = credential;
|
|
23532
|
+
return {
|
|
23533
|
+
kind: "local",
|
|
23534
|
+
...binding,
|
|
23535
|
+
get expiresAt() {
|
|
23536
|
+
return binding.expiresAt;
|
|
23537
|
+
},
|
|
23538
|
+
isCurrent: current,
|
|
23539
|
+
signal: controller.signal,
|
|
23540
|
+
invalidate: () => {
|
|
23541
|
+
if (issued === credential)
|
|
23542
|
+
invalidate();
|
|
23543
|
+
},
|
|
23544
|
+
requestRoutine,
|
|
23545
|
+
requestData,
|
|
23546
|
+
requestAvailability: (key) => requestRoutine(key, "availability", { method: "GET" })
|
|
23547
|
+
};
|
|
23548
|
+
}
|
|
23549
|
+
const resolveOnce = async () => {
|
|
23550
|
+
let attempted;
|
|
23254
23551
|
try {
|
|
23255
23552
|
if (denied || !active2() || globalThis.location.origin !== origin)
|
|
23256
23553
|
throw new Error;
|
|
23257
|
-
|
|
23258
|
-
|
|
23554
|
+
if (credential)
|
|
23555
|
+
await synchronize();
|
|
23556
|
+
const candidate = stored();
|
|
23557
|
+
if (!candidate || !/^[A-Za-z0-9_-]{43}$/.test(candidate))
|
|
23259
23558
|
throw new Error;
|
|
23260
|
-
credential =
|
|
23559
|
+
credential = candidate;
|
|
23560
|
+
attempted = candidate;
|
|
23261
23561
|
if (!current())
|
|
23262
23562
|
throw new Error;
|
|
23263
|
-
const
|
|
23264
|
-
|
|
23265
|
-
|
|
23266
|
-
|
|
23267
|
-
|
|
23268
|
-
|
|
23269
|
-
}
|
|
23270
|
-
if (!
|
|
23563
|
+
const value = await proof(candidate);
|
|
23564
|
+
if (stored() !== candidate || credential !== candidate) {
|
|
23565
|
+
if (!binding)
|
|
23566
|
+
binding = { ...value };
|
|
23567
|
+
await synchronize();
|
|
23568
|
+
return context();
|
|
23569
|
+
}
|
|
23570
|
+
if (!current())
|
|
23271
23571
|
throw new Error;
|
|
23272
|
-
|
|
23273
|
-
if (!validBinding(value) || !current() || value.expiresAt <= Date.now() || value.expiresAt > Date.now() + 600000 || binding && (value.appId !== binding.appId || value.memberId !== binding.memberId || value.workspace !== binding.workspace || value.expiresAt > binding.expiresAt))
|
|
23572
|
+
if (binding && value.expiresAt > binding.expiresAt)
|
|
23274
23573
|
throw new Error;
|
|
23275
|
-
binding
|
|
23276
|
-
|
|
23277
|
-
|
|
23278
|
-
|
|
23279
|
-
|
|
23280
|
-
|
|
23281
|
-
|
|
23282
|
-
|
|
23283
|
-
|
|
23284
|
-
|
|
23285
|
-
|
|
23286
|
-
|
|
23287
|
-
|
|
23288
|
-
|
|
23574
|
+
if (!binding || value.expiresAt !== binding.expiresAt)
|
|
23575
|
+
install(value, candidate);
|
|
23576
|
+
return context();
|
|
23577
|
+
} catch (error) {
|
|
23578
|
+
try {
|
|
23579
|
+
if (binding && current() && attempted && attempted !== credential)
|
|
23580
|
+
return context();
|
|
23581
|
+
if (binding && alive() && stored() && stored() !== credential) {
|
|
23582
|
+
await synchronize();
|
|
23583
|
+
return context();
|
|
23584
|
+
}
|
|
23585
|
+
} catch {}
|
|
23586
|
+
if (error instanceof AppContextDenied && binding && alive() && renewal)
|
|
23587
|
+
throw new Error("Local app context unavailable.");
|
|
23289
23588
|
invalidate();
|
|
23290
23589
|
throw new Error("Local app context unavailable.");
|
|
23291
23590
|
}
|
|
23292
23591
|
};
|
|
23293
|
-
|
|
23592
|
+
const resolve = () => {
|
|
23593
|
+
if (resolution2)
|
|
23594
|
+
return resolution2;
|
|
23595
|
+
resolution2 = resolveOnce().finally(() => {
|
|
23596
|
+
resolution2 = undefined;
|
|
23597
|
+
});
|
|
23598
|
+
return resolution2;
|
|
23599
|
+
};
|
|
23600
|
+
const start = () => {
|
|
23601
|
+
startup = setTimeout(() => {
|
|
23602
|
+
if (alive() && !resolution2 && !binding)
|
|
23603
|
+
resolve().catch(() => {});
|
|
23604
|
+
}, 0);
|
|
23605
|
+
};
|
|
23606
|
+
return { resolve, start, invalidate, dispose };
|
|
23294
23607
|
}
|
|
23295
23608
|
function validBinding(value) {
|
|
23296
|
-
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).sort().join(",") !== "appId,expiresAt,memberId,workspace")
|
|
23609
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).sort().join(",") !== "appId,expiresAt,memberId,sessionId,workspace")
|
|
23297
23610
|
return false;
|
|
23298
23611
|
const binding = value;
|
|
23299
|
-
return typeof binding.appId === "string" && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(binding.appId) && typeof binding.workspace === "string" && /^[a-z0-9][a-z0-9-]{0,62}$/.test(binding.workspace) && typeof binding.memberId === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(binding.memberId) && typeof binding.expiresAt === "number" && Number.isFinite(binding.expiresAt);
|
|
23612
|
+
return typeof binding.appId === "string" && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(binding.appId) && typeof binding.workspace === "string" && /^[a-z0-9][a-z0-9-]{0,62}$/.test(binding.workspace) && typeof binding.memberId === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(binding.memberId) && typeof binding.sessionId === "string" && /^[A-Za-z0-9_-]{43}$/.test(binding.sessionId) && typeof binding.expiresAt === "number" && Number.isFinite(binding.expiresAt);
|
|
23300
23613
|
}
|
|
23301
23614
|
|
|
23302
23615
|
// src/os.ts
|
|
@@ -23364,6 +23677,7 @@ function init({ auth }) {
|
|
|
23364
23677
|
installedDispose = undefined;
|
|
23365
23678
|
};
|
|
23366
23679
|
installedDispose = dispose;
|
|
23680
|
+
local?.start();
|
|
23367
23681
|
}
|
|
23368
23682
|
var os = { init };
|
|
23369
23683
|
// src/app-routine-browser.ts
|