@oddington/sdk 0.1.7 → 0.1.8
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 +64 -2
- package/dist/browser.js +1965 -0
- package/dist/index.js +420 -151
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -21668,7 +21668,7 @@ function managedConnections(capability) {
|
|
|
21668
21668
|
}
|
|
21669
21669
|
|
|
21670
21670
|
// src/connections.ts
|
|
21671
|
-
var connections = createConnections(async (name, operation, input) => {
|
|
21671
|
+
var connections = /* @__PURE__ */ createConnections(async (name, operation, input) => {
|
|
21672
21672
|
try {
|
|
21673
21673
|
const managed = process.env[MANAGED_CONNECTION_CAPABILITY_ENV];
|
|
21674
21674
|
if (managed) {
|
|
@@ -22000,7 +22000,15 @@ function oddingtonOrigin(environment = process.env) {
|
|
|
22000
22000
|
}
|
|
22001
22001
|
|
|
22002
22002
|
// src/routine-local-transport.ts
|
|
22003
|
-
|
|
22003
|
+
var nodeRequest;
|
|
22004
|
+
var nodeReadable;
|
|
22005
|
+
if (typeof __ODDINGTON_BROWSER__ === "undefined" || !__ODDINGTON_BROWSER__) {
|
|
22006
|
+
({ request: nodeRequest } = await import("node:http"));
|
|
22007
|
+
({ Readable: nodeReadable } = await import("node:stream"));
|
|
22008
|
+
}
|
|
22009
|
+
function privateRoutineRequest(environment = typeof __ODDINGTON_BROWSER__ !== "undefined" && __ODDINGTON_BROWSER__ ? {} : typeof process === "undefined" ? {} : process.env) {
|
|
22010
|
+
if (typeof __ODDINGTON_BROWSER__ !== "undefined" && __ODDINGTON_BROWSER__)
|
|
22011
|
+
return;
|
|
22004
22012
|
const prepared = ["ODDINGTON_ROUTINE_LOCAL", "ODDINGTON_ROUTINE_LOCAL_SOCKET", "ODDINGTON_ROUTINE_LOCAL_TOKEN"].some((key) => environment[key] !== undefined);
|
|
22005
22013
|
const managed = ["ODDINGTON_FILES_SOCKET", "ODDINGTON_FILES_TOKEN"].some((key) => environment[key] !== undefined);
|
|
22006
22014
|
if (!prepared && !managed)
|
|
@@ -22013,83 +22021,302 @@ function privateRoutineRequest(environment = typeof process === "undefined" ? {}
|
|
|
22013
22021
|
ODDINGTON_ROUTINE_LOCAL_TOKEN: token
|
|
22014
22022
|
});
|
|
22015
22023
|
const isCurrent = () => prepared ? environment.ODDINGTON_ROUTINE_LOCAL === "1" && environment.ODDINGTON_ROUTINE_LOCAL_SOCKET === socket && environment.ODDINGTON_ROUTINE_LOCAL_TOKEN === token : environment.ODDINGTON_FILES_SOCKET === socket && environment.ODDINGTON_FILES_TOKEN === token;
|
|
22016
|
-
|
|
22017
|
-
|
|
22018
|
-
|
|
22019
|
-
const {
|
|
22020
|
-
|
|
22021
|
-
|
|
22022
|
-
|
|
22023
|
-
|
|
22024
|
-
|
|
22025
|
-
|
|
22026
|
-
|
|
22027
|
-
|
|
22028
|
-
|
|
22029
|
-
|
|
22030
|
-
|
|
22031
|
-
|
|
22032
|
-
|
|
22033
|
-
|
|
22034
|
-
|
|
22035
|
-
|
|
22024
|
+
if (!nodeRequest || !nodeReadable)
|
|
22025
|
+
throw new Error("Files transport unavailable");
|
|
22026
|
+
const httpRequest = nodeRequest, Readable = nodeReadable;
|
|
22027
|
+
const files = async (suffix, init, signal) => {
|
|
22028
|
+
if (!isCurrent())
|
|
22029
|
+
throw new FileOperationError("unsupported_context", 400);
|
|
22030
|
+
const tcp = /^tcp:\/\/127\.0\.0\.1:([1-9][0-9]{0,4})$/.exec(socket);
|
|
22031
|
+
const endpoint = tcp ? { hostname: "127.0.0.1", port: Number(tcp[1]) } : { socketPath: socket };
|
|
22032
|
+
const id2 = crypto.randomUUID();
|
|
22033
|
+
if (init.body instanceof ReadableStream) {
|
|
22034
|
+
await new Promise((resolve, reject) => {
|
|
22035
|
+
const admission = httpRequest({
|
|
22036
|
+
...endpoint,
|
|
22037
|
+
path: "/files/admit",
|
|
22038
|
+
method: "POST",
|
|
22039
|
+
timeout: 30000,
|
|
22040
|
+
signal,
|
|
22041
|
+
agent: false,
|
|
22042
|
+
headers: {
|
|
22043
|
+
...Object.fromEntries(new Headers(init.headers)),
|
|
22044
|
+
authorization: `Bearer ${token}`,
|
|
22045
|
+
"x-oddington-files-suffix": encodeURIComponent(suffix),
|
|
22046
|
+
"x-oddington-files-method": init.method ?? "GET"
|
|
22047
|
+
}
|
|
22048
|
+
}, (response) => {
|
|
22049
|
+
const bytes = Buffer.alloc(16384);
|
|
22050
|
+
let size = 0;
|
|
22051
|
+
response.on("data", (chunk) => {
|
|
22052
|
+
size += chunk.length;
|
|
22053
|
+
if (size > 16384)
|
|
22054
|
+
response.destroy(new Error("Files admission result exceeds supported size"));
|
|
22055
|
+
else
|
|
22056
|
+
bytes.set(chunk, size - chunk.length);
|
|
22057
|
+
});
|
|
22058
|
+
response.once("error", reject);
|
|
22059
|
+
response.once("end", () => {
|
|
22060
|
+
if (response.statusCode === 204) {
|
|
22061
|
+
resolve();
|
|
22062
|
+
return;
|
|
22063
|
+
}
|
|
22064
|
+
try {
|
|
22065
|
+
const value = JSON.parse(bytes.subarray(0, size).toString());
|
|
22066
|
+
const code = value?.error?.code;
|
|
22067
|
+
const status = response.statusCode ?? 503;
|
|
22068
|
+
if (["invalid_input", "request_too_large", "unsupported_context", "access_denied", "capacity", "unavailable"].includes(code))
|
|
22069
|
+
reject(new FileOperationError(code, status, code === "capacity" || code === "unavailable"));
|
|
22070
|
+
else
|
|
22071
|
+
reject(new FileOperationError("unavailable", 503, true));
|
|
22072
|
+
} catch {
|
|
22073
|
+
reject(new FileOperationError("unavailable", 503, true));
|
|
22074
|
+
}
|
|
22075
|
+
});
|
|
22076
|
+
});
|
|
22077
|
+
admission.once("error", () => reject(new FileOperationError("unavailable", 503, true)));
|
|
22078
|
+
admission.once("timeout", () => admission.destroy(new Error("Files admission stalled")));
|
|
22079
|
+
admission.end();
|
|
22080
|
+
});
|
|
22081
|
+
if (!isCurrent())
|
|
22082
|
+
throw new FileOperationError("unsupported_context", 400);
|
|
22083
|
+
}
|
|
22084
|
+
let cancellation;
|
|
22085
|
+
const cancelCall = () => cancellation ??= new Promise((resolve, reject) => {
|
|
22086
|
+
const cancel = httpRequest({
|
|
22036
22087
|
...endpoint,
|
|
22037
|
-
path:
|
|
22088
|
+
path: "/files/cancel",
|
|
22038
22089
|
method: "POST",
|
|
22039
|
-
|
|
22040
|
-
|
|
22090
|
+
timeout: 30000,
|
|
22091
|
+
headers: { authorization: `Bearer ${token}`, "x-oddington-files-call": id2 }
|
|
22041
22092
|
}, (response) => {
|
|
22042
|
-
|
|
22043
|
-
|
|
22044
|
-
response.
|
|
22045
|
-
|
|
22046
|
-
|
|
22093
|
+
response.resume();
|
|
22094
|
+
response.once("end", resolve);
|
|
22095
|
+
response.once("error", reject);
|
|
22096
|
+
});
|
|
22097
|
+
cancel.once("error", reject);
|
|
22098
|
+
cancel.once("timeout", () => cancel.destroy(new Error("Files cancellation stalled")));
|
|
22099
|
+
cancel.end();
|
|
22100
|
+
});
|
|
22101
|
+
let pumping = Promise.resolve();
|
|
22102
|
+
let sourceReader;
|
|
22103
|
+
const result = new Promise((resolve, reject) => {
|
|
22104
|
+
const call = httpRequest({
|
|
22105
|
+
...endpoint,
|
|
22106
|
+
path: "/files/stream",
|
|
22107
|
+
method: "POST",
|
|
22108
|
+
headers: {
|
|
22109
|
+
...Object.fromEntries(new Headers(init.headers)),
|
|
22110
|
+
authorization: `Bearer ${token}`,
|
|
22111
|
+
"x-oddington-files-call": id2,
|
|
22112
|
+
"x-oddington-files-suffix": encodeURIComponent(suffix),
|
|
22113
|
+
"x-oddington-files-method": init.method ?? "GET"
|
|
22114
|
+
},
|
|
22115
|
+
signal,
|
|
22116
|
+
timeout: 30000,
|
|
22117
|
+
agent: false
|
|
22118
|
+
}, async (response) => {
|
|
22119
|
+
try {
|
|
22120
|
+
call.setTimeout(0);
|
|
22121
|
+
if ((response.statusCode ?? 503) >= 400) {
|
|
22122
|
+
await sourceReader?.cancel().catch(() => {});
|
|
22123
|
+
call.end();
|
|
22124
|
+
}
|
|
22125
|
+
await pumping;
|
|
22126
|
+
if (!isCurrent()) {
|
|
22047
22127
|
response.destroy();
|
|
22048
|
-
reject(new
|
|
22049
|
-
|
|
22050
|
-
|
|
22051
|
-
|
|
22052
|
-
|
|
22053
|
-
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
"
|
|
22067
|
-
|
|
22068
|
-
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
|
|
22072
|
-
|
|
22073
|
-
|
|
22074
|
-
|
|
22075
|
-
|
|
22128
|
+
reject(new FileOperationError("unsupported_context", 400));
|
|
22129
|
+
return;
|
|
22130
|
+
}
|
|
22131
|
+
const headers = new Headers;
|
|
22132
|
+
for (const [key, value] of Object.entries(response.headers))
|
|
22133
|
+
if (value !== undefined)
|
|
22134
|
+
headers.set(key, Array.isArray(value) ? value.join(", ") : value);
|
|
22135
|
+
const source = Readable.toWeb(response, { strategy: {
|
|
22136
|
+
highWaterMark: 65536,
|
|
22137
|
+
size: (chunk) => chunk.byteLength
|
|
22138
|
+
} });
|
|
22139
|
+
const reader = source.getReader();
|
|
22140
|
+
let closed = false;
|
|
22141
|
+
const body = new ReadableStream({
|
|
22142
|
+
async pull(controller) {
|
|
22143
|
+
let timer;
|
|
22144
|
+
try {
|
|
22145
|
+
if (!isCurrent())
|
|
22146
|
+
throw new FileOperationError("unsupported_context", 400);
|
|
22147
|
+
timer = setTimeout(() => response.destroy(new Error("Files delivery stalled")), 30000);
|
|
22148
|
+
const next = await reader.read();
|
|
22149
|
+
if (closed)
|
|
22150
|
+
return;
|
|
22151
|
+
if (next.done) {
|
|
22152
|
+
closed = true;
|
|
22153
|
+
reader.releaseLock();
|
|
22154
|
+
controller.close();
|
|
22155
|
+
} else
|
|
22156
|
+
controller.enqueue(next.value);
|
|
22157
|
+
} catch (error) {
|
|
22158
|
+
closed = true;
|
|
22159
|
+
controller.error(error);
|
|
22160
|
+
await cancelCall().catch(() => {});
|
|
22161
|
+
response.socket?.destroy();
|
|
22162
|
+
response.destroy();
|
|
22163
|
+
await reader.cancel(error).catch(() => {});
|
|
22164
|
+
reader.releaseLock();
|
|
22165
|
+
} finally {
|
|
22166
|
+
clearTimeout(timer);
|
|
22076
22167
|
}
|
|
22077
|
-
|
|
22078
|
-
|
|
22168
|
+
},
|
|
22169
|
+
async cancel(reason) {
|
|
22170
|
+
closed = true;
|
|
22171
|
+
await cancelCall().catch(() => {});
|
|
22172
|
+
response.socket?.destroy();
|
|
22173
|
+
response.destroy();
|
|
22174
|
+
call.destroy();
|
|
22175
|
+
await reader.cancel(reason).catch(() => {});
|
|
22176
|
+
reader.releaseLock();
|
|
22177
|
+
}
|
|
22178
|
+
}, { highWaterMark: 0 });
|
|
22179
|
+
resolve(new Response(body, { status: response.statusCode ?? 503, headers }));
|
|
22180
|
+
} catch (error) {
|
|
22181
|
+
response.destroy();
|
|
22182
|
+
reject(error instanceof FileOperationError ? error : new FileOperationError("unavailable", 503, true));
|
|
22183
|
+
}
|
|
22184
|
+
});
|
|
22185
|
+
call.on("error", (error) => {
|
|
22186
|
+
cancelCall().catch(() => {});
|
|
22187
|
+
reject(error instanceof FileOperationError ? error : new FileOperationError("unavailable", 503, true));
|
|
22188
|
+
});
|
|
22189
|
+
call.on("timeout", () => call.destroy(new Error("Files I/O stalled")));
|
|
22190
|
+
call.on("information", () => call.setTimeout(30000));
|
|
22191
|
+
if (init.body instanceof ReadableStream) {
|
|
22192
|
+
call.flushHeaders();
|
|
22193
|
+
const reader = sourceReader = init.body.getReader();
|
|
22194
|
+
const abort = () => {
|
|
22195
|
+
reader.cancel(signal.reason).catch(() => {});
|
|
22196
|
+
};
|
|
22197
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
22198
|
+
call.once("close", abort);
|
|
22199
|
+
pumping = (async () => {
|
|
22200
|
+
try {
|
|
22201
|
+
for (;; ) {
|
|
22202
|
+
const next = await reader.read();
|
|
22203
|
+
if (next.done)
|
|
22204
|
+
break;
|
|
22205
|
+
if (!(next.value instanceof Uint8Array))
|
|
22206
|
+
throw new FileOperationError("invalid_input", 400);
|
|
22207
|
+
if (!isCurrent())
|
|
22208
|
+
throw new FileOperationError("unsupported_context", 400);
|
|
22209
|
+
for (let offset = 0;offset < next.value.byteLength; offset += 262144) {
|
|
22210
|
+
if (call.destroyed)
|
|
22211
|
+
throw new Error("Files parent disconnected");
|
|
22212
|
+
await new Promise((done, fail3) => {
|
|
22213
|
+
const closed = () => fail3(new Error("Files parent disconnected"));
|
|
22214
|
+
call.once("close", closed);
|
|
22215
|
+
call.write(next.value.subarray(offset, offset + 262144), (error) => {
|
|
22216
|
+
call.removeListener("close", closed);
|
|
22217
|
+
error ? fail3(error) : done();
|
|
22218
|
+
});
|
|
22219
|
+
});
|
|
22079
22220
|
}
|
|
22080
|
-
throw new Error(typeof result.error === "string" ? result.error : "Preparation failed");
|
|
22081
22221
|
}
|
|
22082
|
-
|
|
22222
|
+
call.end();
|
|
22083
22223
|
} catch (error) {
|
|
22084
|
-
|
|
22224
|
+
call.destroy(error instanceof Error ? error : new Error("Files transport failed"));
|
|
22225
|
+
} finally {
|
|
22226
|
+
await reader.cancel().catch(() => {});
|
|
22227
|
+
signal.removeEventListener("abort", abort);
|
|
22228
|
+
call.removeListener("close", abort);
|
|
22229
|
+
reader.releaseLock();
|
|
22085
22230
|
}
|
|
22086
|
-
});
|
|
22087
|
-
}
|
|
22088
|
-
|
|
22089
|
-
call.on("timeout", () => call.destroy(new Error("Preparation timed out")));
|
|
22090
|
-
call.end(JSON.stringify(input));
|
|
22231
|
+
})();
|
|
22232
|
+
} else
|
|
22233
|
+
call.end(init.body === undefined ? undefined : Buffer.from(init.body));
|
|
22091
22234
|
});
|
|
22235
|
+
try {
|
|
22236
|
+
return await result;
|
|
22237
|
+
} finally {
|
|
22238
|
+
await pumping;
|
|
22239
|
+
}
|
|
22092
22240
|
};
|
|
22241
|
+
return { request, files, isCurrent, identity: `private:${socket}` };
|
|
22242
|
+
}
|
|
22243
|
+
function localRoutineRequest(environment = typeof __ODDINGTON_BROWSER__ !== "undefined" && __ODDINGTON_BROWSER__ ? {} : typeof process === "undefined" ? {} : process.env) {
|
|
22244
|
+
if (typeof __ODDINGTON_BROWSER__ === "undefined" || !__ODDINGTON_BROWSER__) {
|
|
22245
|
+
const {
|
|
22246
|
+
ODDINGTON_ROUTINE_LOCAL: mode,
|
|
22247
|
+
ODDINGTON_ROUTINE_LOCAL_SOCKET: socket,
|
|
22248
|
+
ODDINGTON_ROUTINE_LOCAL_TOKEN: token
|
|
22249
|
+
} = environment;
|
|
22250
|
+
if (mode === undefined && socket === undefined && token === undefined)
|
|
22251
|
+
return;
|
|
22252
|
+
if (mode !== "1" || !socket || !token || !/^[0-9a-f]{64}$/.test(token))
|
|
22253
|
+
throw new Error("Preparation transport unavailable; nothing can publish");
|
|
22254
|
+
const tcp = /^tcp:\/\/127\.0\.0\.1:([1-9][0-9]{0,4})$/.exec(socket);
|
|
22255
|
+
const endpoint = tcp && tcp[0] === socket && Number(tcp[1]) <= 65535 ? { hostname: "127.0.0.1", port: Number(tcp[1]) } : socket.startsWith("/") && !socket.startsWith("//") && !socket.includes("\x00") ? { socketPath: socket } : undefined;
|
|
22256
|
+
if (!endpoint)
|
|
22257
|
+
throw new Error("Preparation transport unavailable; nothing can publish");
|
|
22258
|
+
return async (operation, input) => {
|
|
22259
|
+
const { request } = await import("node:http");
|
|
22260
|
+
return await new Promise((resolve, reject) => {
|
|
22261
|
+
const call = request({
|
|
22262
|
+
...endpoint,
|
|
22263
|
+
path: `/${operation}`,
|
|
22264
|
+
method: "POST",
|
|
22265
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
22266
|
+
timeout: 120000
|
|
22267
|
+
}, (response) => {
|
|
22268
|
+
const bytes = Buffer.alloc(33554432);
|
|
22269
|
+
let size = 0;
|
|
22270
|
+
response.on("data", (chunk) => {
|
|
22271
|
+
size += chunk.length;
|
|
22272
|
+
if (size > 33554432) {
|
|
22273
|
+
response.destroy();
|
|
22274
|
+
reject(new Error("Local result exceeds supported size"));
|
|
22275
|
+
} else
|
|
22276
|
+
bytes.set(chunk, size - chunk.length);
|
|
22277
|
+
});
|
|
22278
|
+
response.on("error", reject);
|
|
22279
|
+
response.on("end", () => {
|
|
22280
|
+
try {
|
|
22281
|
+
const result = JSON.parse(bytes.subarray(0, size).toString());
|
|
22282
|
+
if (response.statusCode !== 200) {
|
|
22283
|
+
if (operation === "files/request") {
|
|
22284
|
+
const error = result.error;
|
|
22285
|
+
const status = response.statusCode ?? 503;
|
|
22286
|
+
const codes = [
|
|
22287
|
+
"invalid_input",
|
|
22288
|
+
"unsupported_context",
|
|
22289
|
+
"unauthenticated",
|
|
22290
|
+
"access_denied",
|
|
22291
|
+
"request_too_large",
|
|
22292
|
+
"conflict",
|
|
22293
|
+
"local_only",
|
|
22294
|
+
"integrity",
|
|
22295
|
+
"unavailable",
|
|
22296
|
+
"capacity",
|
|
22297
|
+
"method_not_allowed"
|
|
22298
|
+
];
|
|
22299
|
+
if (error?.code && codes.includes(error.code))
|
|
22300
|
+
throw new FileOperationError(error.code, status, error.code === "capacity" || error.code === "unavailable");
|
|
22301
|
+
throw new FileOperationError("unavailable", 503, true);
|
|
22302
|
+
}
|
|
22303
|
+
if (operation === "data/query") {
|
|
22304
|
+
throw dataTransportError(response.statusCode ?? 0, result);
|
|
22305
|
+
}
|
|
22306
|
+
throw new Error(typeof result.error === "string" ? result.error : "Preparation failed");
|
|
22307
|
+
}
|
|
22308
|
+
resolve(result);
|
|
22309
|
+
} catch (error) {
|
|
22310
|
+
reject(error);
|
|
22311
|
+
}
|
|
22312
|
+
});
|
|
22313
|
+
});
|
|
22314
|
+
call.on("error", () => reject(new Error("Preparation transport unavailable; nothing was published")));
|
|
22315
|
+
call.on("timeout", () => call.destroy(new Error("Preparation timed out")));
|
|
22316
|
+
call.end(JSON.stringify(input));
|
|
22317
|
+
});
|
|
22318
|
+
};
|
|
22319
|
+
}
|
|
22093
22320
|
}
|
|
22094
22321
|
|
|
22095
22322
|
// src/data-context.ts
|
|
@@ -22116,12 +22343,14 @@ async function resolveAppContext() {
|
|
|
22116
22343
|
}
|
|
22117
22344
|
async function resolveDataContext() {
|
|
22118
22345
|
try {
|
|
22119
|
-
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22346
|
+
if (typeof __ODDINGTON_BROWSER__ === "undefined" || !__ODDINGTON_BROWSER__) {
|
|
22347
|
+
const local = localRoutineRequest();
|
|
22348
|
+
if (local)
|
|
22349
|
+
return { local };
|
|
22350
|
+
const managed = privateRoutineRequest();
|
|
22351
|
+
if (managed)
|
|
22352
|
+
return { local: managed.request };
|
|
22353
|
+
}
|
|
22125
22354
|
const host = memberContext;
|
|
22126
22355
|
if (host !== undefined) {
|
|
22127
22356
|
const context = await host();
|
|
@@ -22133,25 +22362,31 @@ async function resolveDataContext() {
|
|
|
22133
22362
|
throw new Error;
|
|
22134
22363
|
return checked(context.workspace, context.endpoint, { authorization: `Bearer ${context.accessToken}` });
|
|
22135
22364
|
}
|
|
22136
|
-
|
|
22137
|
-
|
|
22138
|
-
|
|
22139
|
-
|
|
22365
|
+
if (typeof __ODDINGTON_BROWSER__ === "undefined" || !__ODDINGTON_BROWSER__) {
|
|
22366
|
+
const environment = typeof process === "undefined" ? undefined : process.env;
|
|
22367
|
+
if (!environment || !/^[0-9a-f]{64}$/.test(environment.ODDINGTON_ROUTINE_RUN ?? ""))
|
|
22368
|
+
throw new Error;
|
|
22369
|
+
return checked(environment.ODDINGTON_ROUTINE_WORKSPACE, oddingtonOrigin(environment), { "x-oddington-run": environment.ODDINGTON_ROUTINE_RUN });
|
|
22370
|
+
}
|
|
22371
|
+
throw new Error;
|
|
22140
22372
|
} catch {
|
|
22141
22373
|
throw new DataOperationError("context_unavailable");
|
|
22142
22374
|
}
|
|
22143
22375
|
}
|
|
22144
22376
|
async function resolveFilesContext() {
|
|
22145
22377
|
try {
|
|
22146
|
-
const environment = typeof process === "undefined" ? {} : process.env;
|
|
22147
|
-
|
|
22148
|
-
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
|
|
22153
|
-
|
|
22154
|
-
|
|
22378
|
+
const environment = typeof __ODDINGTON_BROWSER__ !== "undefined" && __ODDINGTON_BROWSER__ ? {} : typeof process === "undefined" ? {} : process.env;
|
|
22379
|
+
if (typeof __ODDINGTON_BROWSER__ === "undefined" || !__ODDINGTON_BROWSER__) {
|
|
22380
|
+
const local = privateRoutineRequest(environment);
|
|
22381
|
+
if (local)
|
|
22382
|
+
return {
|
|
22383
|
+
url: local.identity,
|
|
22384
|
+
headers: {},
|
|
22385
|
+
isCurrent: local.isCurrent,
|
|
22386
|
+
local: local.request,
|
|
22387
|
+
localFiles: local.files
|
|
22388
|
+
};
|
|
22389
|
+
}
|
|
22155
22390
|
const host = memberContext;
|
|
22156
22391
|
if (host) {
|
|
22157
22392
|
const context = await host();
|
|
@@ -22162,13 +22397,17 @@ async function resolveFilesContext() {
|
|
|
22162
22397
|
return {
|
|
22163
22398
|
...filesContext(context.workspace, context.endpoint, { authorization: `Bearer ${context.accessToken}` }),
|
|
22164
22399
|
isCurrent: context.isCurrent,
|
|
22165
|
-
local: undefined
|
|
22400
|
+
local: undefined,
|
|
22401
|
+
localFiles: undefined
|
|
22166
22402
|
};
|
|
22167
22403
|
}
|
|
22168
|
-
if (
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
|
|
22404
|
+
if (typeof __ODDINGTON_BROWSER__ === "undefined" || !__ODDINGTON_BROWSER__) {
|
|
22405
|
+
if (!/^[0-9a-f]{64}$/.test(environment.ODDINGTON_ROUTINE_RUN ?? ""))
|
|
22406
|
+
throw new Error;
|
|
22407
|
+
const workspace = environment.ODDINGTON_ROUTINE_WORKSPACE;
|
|
22408
|
+
return { ...filesContext(workspace, `https://${workspace}.oddington.ai`, { "x-oddington-run": environment.ODDINGTON_ROUTINE_RUN }), local: undefined, localFiles: undefined };
|
|
22409
|
+
}
|
|
22410
|
+
throw new Error;
|
|
22172
22411
|
} catch {
|
|
22173
22412
|
throw new FileOperationError("unsupported_context", 400);
|
|
22174
22413
|
}
|
|
@@ -22330,6 +22569,7 @@ var MAX_BYTES = 16 * 1024 * 1024;
|
|
|
22330
22569
|
var PART_BYTES = 8 * 1024 * 1024;
|
|
22331
22570
|
var METADATA_BYTES = 4096;
|
|
22332
22571
|
var RESULT_BYTES = 16 * 1024;
|
|
22572
|
+
var CONTROL_RESULT_BYTES = 128 * 1024;
|
|
22333
22573
|
var TIMEOUT_MS = 30000;
|
|
22334
22574
|
var MAX_ACTIVE = 4;
|
|
22335
22575
|
var ATTEMPTS = 2;
|
|
@@ -22390,15 +22630,15 @@ async function timed(work, parent, timeout = TIMEOUT_MS) {
|
|
|
22390
22630
|
parent?.removeEventListener("abort", abort);
|
|
22391
22631
|
}
|
|
22392
22632
|
}
|
|
22393
|
-
async function result(response) {
|
|
22633
|
+
async function result(response, maximum = RESULT_BYTES) {
|
|
22394
22634
|
try {
|
|
22395
|
-
const bytes = await boundedBytes(response.body,
|
|
22635
|
+
const bytes = await boundedBytes(response.body, maximum);
|
|
22396
22636
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
22397
22637
|
} catch {
|
|
22398
22638
|
throw unavailable();
|
|
22399
22639
|
}
|
|
22400
22640
|
}
|
|
22401
|
-
async function hostedContent(url, init, parent) {
|
|
22641
|
+
async function hostedContent(url, init, parent, upstream = fetch) {
|
|
22402
22642
|
const delivery = new AbortController;
|
|
22403
22643
|
const abort = () => delivery.abort(parent.reason);
|
|
22404
22644
|
parent.addEventListener("abort", abort, { once: true });
|
|
@@ -22406,7 +22646,7 @@ async function hostedContent(url, init, parent) {
|
|
|
22406
22646
|
abort();
|
|
22407
22647
|
const detach = () => parent.removeEventListener("abort", abort);
|
|
22408
22648
|
try {
|
|
22409
|
-
const response = await
|
|
22649
|
+
const response = await upstream(url, { ...init, signal: delivery.signal });
|
|
22410
22650
|
if (delivery.signal.aborted) {
|
|
22411
22651
|
response.body?.cancel().catch(() => {});
|
|
22412
22652
|
throw unavailable();
|
|
@@ -22482,26 +22722,7 @@ async function send(suffix, init, descriptor, initial, parent) {
|
|
|
22482
22722
|
throw new FileOperationError("unsupported_context", 400);
|
|
22483
22723
|
try {
|
|
22484
22724
|
return await (async () => {
|
|
22485
|
-
const response = context.
|
|
22486
|
-
const body = init.body instanceof ArrayBuffer ? new Uint8Array(init.body) : undefined;
|
|
22487
|
-
let binary = "";
|
|
22488
|
-
if (body)
|
|
22489
|
-
for (let offset = 0;offset < body.length; offset += 8192)
|
|
22490
|
-
binary += String.fromCharCode(...body.subarray(offset, offset + 8192));
|
|
22491
|
-
const value2 = await context.local("files/request", {
|
|
22492
|
-
suffix,
|
|
22493
|
-
method: init.method,
|
|
22494
|
-
headers: Object.fromEntries(new Headers(init.headers)),
|
|
22495
|
-
...body ? { bytes: btoa(binary) } : {}
|
|
22496
|
-
});
|
|
22497
|
-
if (value2.bytes !== undefined) {
|
|
22498
|
-
if (value2.bytes.length > Math.ceil(MAX_BYTES / 3) * 4)
|
|
22499
|
-
throw unavailable();
|
|
22500
|
-
const data2 = atob(value2.bytes);
|
|
22501
|
-
return new Response(Uint8Array.from(data2, (c) => c.charCodeAt(0)), { status: value2.status, headers: value2.headers });
|
|
22502
|
-
}
|
|
22503
|
-
return Response.json(value2.json, { status: value2.status, headers: value2.headers });
|
|
22504
|
-
})() : await (async () => {
|
|
22725
|
+
const response = context.localFiles ? await context.localFiles(suffix, init, parent) : await (async () => {
|
|
22505
22726
|
const url = `${context.url}${suffix}`;
|
|
22506
22727
|
const request = {
|
|
22507
22728
|
...init,
|
|
@@ -22531,7 +22752,7 @@ async function send(suffix, init, descriptor, initial, parent) {
|
|
|
22531
22752
|
}
|
|
22532
22753
|
if (!descriptor)
|
|
22533
22754
|
return response;
|
|
22534
|
-
const value = await result(response);
|
|
22755
|
+
const value = await result(response, descriptor === "control" ? CONTROL_RESULT_BYTES : RESULT_BYTES);
|
|
22535
22756
|
if (descriptor === "control") {
|
|
22536
22757
|
checkCurrent();
|
|
22537
22758
|
return value;
|
|
@@ -22551,7 +22772,7 @@ async function send(suffix, init, descriptor, initial, parent) {
|
|
|
22551
22772
|
})();
|
|
22552
22773
|
} catch (error) {
|
|
22553
22774
|
const failure = error instanceof FileOperationError ? error : unavailable();
|
|
22554
|
-
if (!failure.retryable || attempt + 1 === ATTEMPTS)
|
|
22775
|
+
if (init.body instanceof ReadableStream || !failure.retryable || attempt + 1 === ATTEMPTS)
|
|
22555
22776
|
throw failure;
|
|
22556
22777
|
}
|
|
22557
22778
|
}
|
|
@@ -22562,7 +22783,10 @@ function idPath(id2) {
|
|
|
22562
22783
|
throw invalid2();
|
|
22563
22784
|
return `/${id2}`;
|
|
22564
22785
|
}
|
|
22565
|
-
async function multipartCreate(input, metadata,
|
|
22786
|
+
async function multipartCreate(input, metadata, exchange, release = () => {
|
|
22787
|
+
active--;
|
|
22788
|
+
}, upload) {
|
|
22789
|
+
const route = upload ? `${idPath(upload.file.id)}/upload/multipart` : "/multipart";
|
|
22566
22790
|
let ticket;
|
|
22567
22791
|
let reader;
|
|
22568
22792
|
let chunk, offset = 0;
|
|
@@ -22580,11 +22804,11 @@ async function multipartCreate(input, metadata, context) {
|
|
|
22580
22804
|
body: JSON.stringify(body)
|
|
22581
22805
|
});
|
|
22582
22806
|
try {
|
|
22583
|
-
const start = await request((signal) =>
|
|
22807
|
+
const start = await request((signal) => exchange(`${route}/start`, control(upload?.file ?? metadata), "control", signal));
|
|
22584
22808
|
if (!start || typeof start !== "object" || Array.isArray(start))
|
|
22585
22809
|
throw unavailable();
|
|
22586
22810
|
const session = start;
|
|
22587
|
-
if (Object.keys(session).sort().join(",") !== "partBytes,ticket" || session.partBytes !== PART_BYTES || typeof session.ticket !== "string" || !session.ticket || session.ticket.length >
|
|
22811
|
+
if (Object.keys(session).sort().join(",") !== "partBytes,ticket" || session.partBytes !== PART_BYTES || typeof session.ticket !== "string" || !session.ticket || session.ticket.length > 64 * 1024)
|
|
22588
22812
|
throw unavailable();
|
|
22589
22813
|
ticket = session.ticket;
|
|
22590
22814
|
if (input.file instanceof ReadableStream)
|
|
@@ -22603,7 +22827,7 @@ async function multipartCreate(input, metadata, context) {
|
|
|
22603
22827
|
throw error;
|
|
22604
22828
|
}
|
|
22605
22829
|
};
|
|
22606
|
-
for (let sent = 0, partNumber = 1;sent < metadata.size; partNumber++) {
|
|
22830
|
+
for (let sent = 0, partNumber = 1;sent < metadata.size || metadata.size === 0 && partNumber === 1; partNumber++) {
|
|
22607
22831
|
const length = Math.min(PART_BYTES, metadata.size - sent);
|
|
22608
22832
|
let part;
|
|
22609
22833
|
if (input.file instanceof Uint8Array)
|
|
@@ -22649,11 +22873,12 @@ async function multipartCreate(input, metadata, context) {
|
|
|
22649
22873
|
throw invalid2();
|
|
22650
22874
|
}
|
|
22651
22875
|
}
|
|
22652
|
-
const value = await request((signal) =>
|
|
22876
|
+
const value = await request((signal) => exchange(`${route}/part`, {
|
|
22653
22877
|
method: "POST",
|
|
22654
22878
|
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket, "x-oddington-part": String(partNumber) },
|
|
22655
22879
|
body: part.buffer
|
|
22656
|
-
}, "control",
|
|
22880
|
+
}, "control", signal));
|
|
22881
|
+
part = undefined;
|
|
22657
22882
|
const receipt = value;
|
|
22658
22883
|
if (!receipt || typeof receipt !== "object" || Object.keys(receipt).sort().join(",") !== "etag,partNumber" || receipt.partNumber !== partNumber || typeof receipt.etag !== "string" || !receipt.etag || receipt.etag.length > 256 || /[\u0000-\u001f\u007f]/.test(receipt.etag))
|
|
22659
22884
|
throw unavailable();
|
|
@@ -22661,25 +22886,35 @@ async function multipartCreate(input, metadata, context) {
|
|
|
22661
22886
|
sent += length;
|
|
22662
22887
|
lastProgress = Date.now();
|
|
22663
22888
|
}
|
|
22889
|
+
if (upload)
|
|
22890
|
+
for (const name of Object.keys(upload.file.enrichments)) {
|
|
22891
|
+
const bytes = await request(() => upload.enrichment(name));
|
|
22892
|
+
if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES)
|
|
22893
|
+
throw invalid2();
|
|
22894
|
+
await request((signal) => exchange(`${route}/enrichments/${encodeURIComponent(name)}`, {
|
|
22895
|
+
method: "POST",
|
|
22896
|
+
headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket },
|
|
22897
|
+
body: bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)
|
|
22898
|
+
}, "control", signal));
|
|
22899
|
+
}
|
|
22900
|
+
await upload?.beforeComplete();
|
|
22664
22901
|
const completion = control({ parts: receipts });
|
|
22665
22902
|
if (new TextEncoder().encode(completion.body).byteLength > 128 * 1024)
|
|
22666
22903
|
throw unavailable();
|
|
22667
|
-
return await request((signal) =>
|
|
22904
|
+
return parseFileDescriptor(await request((signal) => exchange(`${route}/complete`, completion, true, signal), TIMEOUT_MS + Math.ceil(metadata.size / (1024 * 1024)) * 1000));
|
|
22668
22905
|
} catch (error) {
|
|
22669
22906
|
if (reader)
|
|
22670
22907
|
await reader.cancel(error).catch(() => {});
|
|
22671
22908
|
if (ticket)
|
|
22672
|
-
await request((signal) =>
|
|
22909
|
+
await request((signal) => exchange(`${route}/abort`, control({}), "control", signal)).catch(() => {});
|
|
22673
22910
|
throw error instanceof FileOperationError ? error : unavailable();
|
|
22674
22911
|
} finally {
|
|
22675
22912
|
chunk = undefined;
|
|
22676
22913
|
reader?.releaseLock();
|
|
22677
22914
|
if (pending.size)
|
|
22678
|
-
Promise.allSettled([...pending]).then(
|
|
22679
|
-
active--;
|
|
22680
|
-
});
|
|
22915
|
+
Promise.allSettled([...pending]).then(release);
|
|
22681
22916
|
else
|
|
22682
|
-
|
|
22917
|
+
release();
|
|
22683
22918
|
}
|
|
22684
22919
|
}
|
|
22685
22920
|
async function operation(work, initial, parent) {
|
|
@@ -22687,6 +22922,13 @@ async function operation(work, initial, parent) {
|
|
|
22687
22922
|
if (active >= MAX_ACTIVE)
|
|
22688
22923
|
throw new FileOperationError("capacity", 429, true);
|
|
22689
22924
|
active++;
|
|
22925
|
+
if (context.localFiles) {
|
|
22926
|
+
try {
|
|
22927
|
+
return await work(context, parent ?? new AbortController().signal);
|
|
22928
|
+
} finally {
|
|
22929
|
+
active--;
|
|
22930
|
+
}
|
|
22931
|
+
}
|
|
22690
22932
|
return timed(async (signal) => {
|
|
22691
22933
|
try {
|
|
22692
22934
|
return await work(context, signal);
|
|
@@ -22776,7 +23018,7 @@ var files = {
|
|
|
22776
23018
|
storage: input.storage,
|
|
22777
23019
|
csv: input.csv,
|
|
22778
23020
|
requestKey: options?.requestKey === undefined ? crypto.randomUUID() : options.requestKey
|
|
22779
|
-
},
|
|
23021
|
+
}, FILE_ORIGINAL_MAX_BYTES);
|
|
22780
23022
|
if (!context.local && metadata.storage === "local")
|
|
22781
23023
|
throw new FileOperationError("unsupported_context", 400);
|
|
22782
23024
|
const header = encodeURIComponent(JSON.stringify(metadata));
|
|
@@ -22785,8 +23027,32 @@ var files = {
|
|
|
22785
23027
|
if (active >= MAX_ACTIVE)
|
|
22786
23028
|
throw new FileOperationError("capacity", 429, true);
|
|
22787
23029
|
active++;
|
|
23030
|
+
if (context.localFiles && metadata.size > MAX_BYTES) {
|
|
23031
|
+
const controller = new AbortController;
|
|
23032
|
+
const file = input.file;
|
|
23033
|
+
let offset = 0;
|
|
23034
|
+
const body = file instanceof ReadableStream ? file : file instanceof Blob ? file.stream() : new ReadableStream({
|
|
23035
|
+
pull(controller2) {
|
|
23036
|
+
if (offset === file.byteLength) {
|
|
23037
|
+
controller2.close();
|
|
23038
|
+
return;
|
|
23039
|
+
}
|
|
23040
|
+
const end = Math.min(offset + 256 * 1024, file.byteLength);
|
|
23041
|
+
controller2.enqueue(file.subarray(offset, end));
|
|
23042
|
+
offset = end;
|
|
23043
|
+
}
|
|
23044
|
+
}, { highWaterMark: 0 });
|
|
23045
|
+
try {
|
|
23046
|
+
return await send("", { method: "POST", headers: {
|
|
23047
|
+
"content-type": "application/octet-stream",
|
|
23048
|
+
"x-oddington-file": header
|
|
23049
|
+
}, body }, true, context, controller.signal);
|
|
23050
|
+
} finally {
|
|
23051
|
+
active--;
|
|
23052
|
+
}
|
|
23053
|
+
}
|
|
22788
23054
|
if (metadata.size > MAX_BYTES)
|
|
22789
|
-
return multipartCreate(input, metadata, context);
|
|
23055
|
+
return multipartCreate(input, metadata, (suffix, init, kind, signal) => kind === true ? send(suffix, init, true, context, signal) : send(suffix, init, "control", context, signal));
|
|
22790
23056
|
return timed(async (signal) => {
|
|
22791
23057
|
try {
|
|
22792
23058
|
const bytes = array2 ? input.file.slice() : await boundedBytes(blob ? input.file.stream() : input.file, metadata.size);
|
|
@@ -23561,7 +23827,7 @@ function freeze(value) {
|
|
|
23561
23827
|
}
|
|
23562
23828
|
return value;
|
|
23563
23829
|
}
|
|
23564
|
-
if (typeof process !== "undefined" && process.env.ODDINGTON_APP_RUN !== undefined) {
|
|
23830
|
+
if ((typeof __ODDINGTON_BROWSER__ === "undefined" || !__ODDINGTON_BROWSER__) && typeof process !== "undefined" && process.env.ODDINGTON_APP_RUN !== undefined) {
|
|
23565
23831
|
let fail4 = function() {
|
|
23566
23832
|
broken = true;
|
|
23567
23833
|
pending?.reject(unavailable2());
|
|
@@ -23712,13 +23978,13 @@ init_inbox_contract();
|
|
|
23712
23978
|
init_inbox_contract();
|
|
23713
23979
|
init_inbox_files();
|
|
23714
23980
|
function routinePublicationClient(options = {}) {
|
|
23715
|
-
const environment = typeof process === "undefined" ? {} : process.env;
|
|
23981
|
+
const environment = typeof __ODDINGTON_BROWSER__ !== "undefined" && __ODDINGTON_BROWSER__ ? {} : typeof process === "undefined" ? {} : process.env;
|
|
23716
23982
|
const local = localRoutineRequest(environment);
|
|
23717
23983
|
const workspace = options.workspace ?? environment.ODDINGTON_ROUTINE_WORKSPACE;
|
|
23718
23984
|
const capability = options.capability ?? environment.ODDINGTON_ROUTINE_RUN;
|
|
23719
23985
|
if (!workspace || !/^[a-z0-9][a-z0-9-]*$/.test(workspace) || capability !== undefined && !/^[0-9a-f]{64}$/.test(capability))
|
|
23720
23986
|
throw new Error("A workspace and valid optional routine capability are required");
|
|
23721
|
-
const workingRoot = options.workingRoot ?? environment.ODDINGTON_INBOX_WORKING_ROOT ?? (typeof process === "undefined" ? undefined : process.cwd());
|
|
23987
|
+
const workingRoot = options.workingRoot ?? environment.ODDINGTON_INBOX_WORKING_ROOT ?? (typeof __ODDINGTON_BROWSER__ !== "undefined" && __ODDINGTON_BROWSER__ ? undefined : typeof process === "undefined" ? undefined : process.cwd());
|
|
23722
23988
|
const headers = capability ? { "x-oddington-run": capability } : {};
|
|
23723
23989
|
const request = options.request ?? (capability ? async (path, init2) => {
|
|
23724
23990
|
const origin = oddingtonOrigin();
|
|
@@ -23783,22 +24049,25 @@ function routinePublicationClient(options = {}) {
|
|
|
23783
24049
|
return validateInboxFile(await local("files/add", input));
|
|
23784
24050
|
if (!workingRoot)
|
|
23785
24051
|
throw new Error("Inbox file reads require a working root");
|
|
23786
|
-
|
|
23787
|
-
|
|
23788
|
-
|
|
23789
|
-
|
|
23790
|
-
|
|
23791
|
-
|
|
23792
|
-
|
|
23793
|
-
|
|
23794
|
-
|
|
23795
|
-
|
|
23796
|
-
|
|
23797
|
-
|
|
23798
|
-
|
|
23799
|
-
|
|
23800
|
-
|
|
23801
|
-
|
|
24052
|
+
if (typeof __ODDINGTON_BROWSER__ === "undefined" || !__ODDINGTON_BROWSER__) {
|
|
24053
|
+
const { readInboxPublicationFile: readInboxPublicationFile2 } = await Promise.resolve().then(() => (init_inbox_publication_file(), exports_inbox_publication_file));
|
|
24054
|
+
const bytes = await readInboxPublicationFile2(workingRoot, input);
|
|
24055
|
+
const name = input.name ?? input.path.split("/").at(-1);
|
|
24056
|
+
const response = await request(`/api/cli/workspaces/${workspace}/inbox/files/upload`, {
|
|
24057
|
+
method: "POST",
|
|
24058
|
+
headers: {
|
|
24059
|
+
"content-type": "application/octet-stream",
|
|
24060
|
+
...headers,
|
|
24061
|
+
"x-oddington-file": JSON.stringify({ name, ...input.csv ? { csv: input.csv } : {} })
|
|
24062
|
+
},
|
|
24063
|
+
body: Uint8Array.from(bytes).buffer
|
|
24064
|
+
});
|
|
24065
|
+
const result2 = await response.json();
|
|
24066
|
+
if (!response.ok)
|
|
24067
|
+
throw new Error(result2.error ?? "Could not retain file");
|
|
24068
|
+
return await verifyInboxFile(bytes, validateInboxFile(result2));
|
|
24069
|
+
}
|
|
24070
|
+
throw new Error("Inbox file reads require a Node working root");
|
|
23802
24071
|
}
|
|
23803
24072
|
},
|
|
23804
24073
|
async check(body2) {
|