deepline 0.2.55 → 0.2.57
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/dist/bundling-sources/sdk/src/client.ts +14 -0
- package/dist/bundling-sources/sdk/src/http.ts +19 -1
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/stream-reconnect.ts +6 -0
- package/dist/bundling-sources/sdk/src/types.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +146 -12
- package/dist/bundling-sources/shared_libs/play-runtime/batch-runtime.ts +6 -3
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +1631 -748
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +81 -52
- package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +146 -6
- package/dist/bundling-sources/shared_libs/play-runtime/gateway-auth-session.ts +56 -22
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +14 -11
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +21 -2
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +81 -21
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +27 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +49 -10
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +96 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +341 -67
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-capacity-policy.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +8 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-pg.ts +17 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +4 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +17 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +16 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-writer.ts +25 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +80 -1
- package/dist/bundling-sources/shared_libs/plays/docflow.ts +113 -14
- package/dist/bundling-sources/shared_libs/plays/play-exports.ts +53 -4
- package/dist/bundling-sources/shared_libs/security/safe-fetch.ts +9 -0
- package/dist/bundling-sources/shared_libs/security/safe-outbound-fetch.ts +85 -48
- package/dist/cli/index.js +429 -54
- package/dist/cli/index.mjs +409 -28
- package/dist/{compiler-manifest-Bl8kmLx9.d.mts → compiler-manifest-TgaC4DeD.d.mts} +13 -0
- package/dist/{compiler-manifest-Bl8kmLx9.d.ts → compiler-manifest-TgaC4DeD.d.ts} +13 -0
- package/dist/index.d.mts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +29 -2
- package/dist/index.mjs +29 -2
- package/dist/install-integrity.json +2 -2
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/plays/bundle-play-file.mjs +78 -18
- package/package.json +1 -1
|
@@ -34,6 +34,16 @@ export type PlayFileExport = {
|
|
|
34
34
|
name: string;
|
|
35
35
|
/** Other export names that resolve to the same `definePlay` call. */
|
|
36
36
|
aliases: string[];
|
|
37
|
+
/**
|
|
38
|
+
* The play's own name — `definePlay('<this>', …)` — when it is a literal.
|
|
39
|
+
*
|
|
40
|
+
* An export name is a module detail (`scalar`, `batch`); the play name is what
|
|
41
|
+
* the product, the registry and the customer call this thing. So it is a legal
|
|
42
|
+
* way to address the play, which is why an `@mermaid <name>` header may write
|
|
43
|
+
* either. Null when the first argument is not a string literal, which is only
|
|
44
|
+
* possible for a play the registry could not name either.
|
|
45
|
+
*/
|
|
46
|
+
playName: string | null;
|
|
37
47
|
};
|
|
38
48
|
|
|
39
49
|
function getIdentifierName(node: unknown): string | null {
|
|
@@ -83,6 +93,16 @@ export function isDefinePlayCall(node: AstNode | null): boolean {
|
|
|
83
93
|
return false;
|
|
84
94
|
}
|
|
85
95
|
|
|
96
|
+
/** The literal name a `definePlay('…', …)` call declares, when it is one. */
|
|
97
|
+
function definePlayName(node: AstNode | null): string | null {
|
|
98
|
+
const expression = unwrapStaticExpression(node);
|
|
99
|
+
if (!expression || expression.type !== 'CallExpression') return null;
|
|
100
|
+
const first = astArray(expression.arguments)[0] ?? null;
|
|
101
|
+
return first?.type === 'Literal' && typeof first.value === 'string'
|
|
102
|
+
? first.value
|
|
103
|
+
: null;
|
|
104
|
+
}
|
|
105
|
+
|
|
86
106
|
/**
|
|
87
107
|
* The plays `sourceCode` exports, default first, then named exports in source
|
|
88
108
|
* order. `null` means acorn could not parse the file — the caller abstains and
|
|
@@ -163,13 +183,26 @@ export function listPlayFileExports(
|
|
|
163
183
|
.map(([exported]) => exported)
|
|
164
184
|
: [];
|
|
165
185
|
if (defaultLocalName) aliasedLocals.add(defaultLocalName);
|
|
166
|
-
exports.push({
|
|
186
|
+
exports.push({
|
|
187
|
+
name: PLAY_DEFAULT_EXPORT,
|
|
188
|
+
aliases,
|
|
189
|
+
playName: definePlayName(
|
|
190
|
+
defaultLocalName
|
|
191
|
+
? (declarations.get(defaultLocalName) ?? null)
|
|
192
|
+
: defaultExpression,
|
|
193
|
+
),
|
|
194
|
+
});
|
|
167
195
|
}
|
|
168
196
|
for (const [exportedName, localName] of namedExports) {
|
|
169
197
|
if (exportedName === PLAY_DEFAULT_EXPORT) continue;
|
|
170
198
|
if (aliasedLocals.has(localName)) continue;
|
|
171
|
-
|
|
172
|
-
|
|
199
|
+
const declaration = declarations.get(localName) ?? null;
|
|
200
|
+
if (!isDefinePlayCall(declaration)) continue;
|
|
201
|
+
exports.push({
|
|
202
|
+
name: exportedName,
|
|
203
|
+
aliases: [],
|
|
204
|
+
playName: definePlayName(declaration),
|
|
205
|
+
});
|
|
173
206
|
}
|
|
174
207
|
|
|
175
208
|
return exports;
|
|
@@ -180,6 +213,12 @@ export function listPlayFileExports(
|
|
|
180
213
|
* canonical name. `scalar` in `export default scalar` resolves to `default`;
|
|
181
214
|
* an unknown name resolves to `null` so the caller can fail loudly with the
|
|
182
215
|
* available set rather than silently binding nothing.
|
|
216
|
+
*
|
|
217
|
+
* The play's own name resolves too, and is the better thing to write: a diagram
|
|
218
|
+
* headed `@mermaid scalar` names a module-local binding, while one headed
|
|
219
|
+
* `@mermaid name-and-domain-to-email-waterfall` names the play the reader came
|
|
220
|
+
* here for. Export names keep working because every diagram authored before this
|
|
221
|
+
* used one.
|
|
183
222
|
*/
|
|
184
223
|
export function canonicalPlayExportName(
|
|
185
224
|
exportName: string | null | undefined,
|
|
@@ -191,6 +230,12 @@ export function canonicalPlayExportName(
|
|
|
191
230
|
return entry.name;
|
|
192
231
|
}
|
|
193
232
|
}
|
|
233
|
+
// Second pass, so an export literally named after another play's play name
|
|
234
|
+
// can never lose to it. Ambiguity between two plays' names is impossible:
|
|
235
|
+
// the registry rejects a duplicate play name before this ever runs.
|
|
236
|
+
for (const entry of exports) {
|
|
237
|
+
if (entry.playName === requested) return entry.name;
|
|
238
|
+
}
|
|
194
239
|
return null;
|
|
195
240
|
}
|
|
196
241
|
|
|
@@ -198,5 +243,9 @@ export function canonicalPlayExportName(
|
|
|
198
243
|
export function playExportNamesForMessage(
|
|
199
244
|
exports: readonly PlayFileExport[],
|
|
200
245
|
): string[] {
|
|
201
|
-
return exports.flatMap((entry) => [
|
|
246
|
+
return exports.flatMap((entry) => [
|
|
247
|
+
...(entry.playName ? [entry.playName] : []),
|
|
248
|
+
entry.name,
|
|
249
|
+
...entry.aliases,
|
|
250
|
+
]);
|
|
202
251
|
}
|
|
@@ -19,6 +19,10 @@ function removeHeader(headers: Headers, name: string) {
|
|
|
19
19
|
if (headers.has(name)) headers.delete(name);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function cancelResponseBodyBestEffort(response: Response): void {
|
|
23
|
+
void response.body?.cancel().catch(() => undefined);
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
function requestInitForRedirect(
|
|
23
27
|
init: RequestInit,
|
|
24
28
|
from: URL,
|
|
@@ -83,6 +87,7 @@ export async function safePublicFetch(
|
|
|
83
87
|
return response;
|
|
84
88
|
}
|
|
85
89
|
if (redirectMode === 'error') {
|
|
90
|
+
cancelResponseBodyBestEffort(response);
|
|
86
91
|
throw new Error(
|
|
87
92
|
`Redirect blocked while fetching ${currentUrl.toString()}.`,
|
|
88
93
|
);
|
|
@@ -96,11 +101,15 @@ export async function safePublicFetch(
|
|
|
96
101
|
return response;
|
|
97
102
|
}
|
|
98
103
|
if (redirectCount === maxRedirects) {
|
|
104
|
+
cancelResponseBodyBestEffort(response);
|
|
99
105
|
throw new Error(
|
|
100
106
|
`Too many redirects while fetching ${currentUrl.toString()}.`,
|
|
101
107
|
);
|
|
102
108
|
}
|
|
103
109
|
|
|
110
|
+
// A redirect response can stream an unbounded body. The next request must
|
|
111
|
+
// not leave that body/socket flowing in the background.
|
|
112
|
+
cancelResponseBodyBestEffort(response);
|
|
104
113
|
const nextUrl = resolveRedirectUrl(location, currentUrl);
|
|
105
114
|
currentInit = requestInitForRedirect(
|
|
106
115
|
currentInit,
|
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
type NodeSafeFetchOptions = {
|
|
15
15
|
maxRedirects?: number;
|
|
16
16
|
maxResponseBytes?: number;
|
|
17
|
+
/** Return after validated headers so the caller can enforce a body deadline. */
|
|
18
|
+
streamResponseBody?: boolean;
|
|
17
19
|
truncateResponseBody?: boolean;
|
|
18
20
|
sensitiveHeaders?: Iterable<string>;
|
|
19
21
|
validateUrl?: (url: URL) => void;
|
|
@@ -219,62 +221,83 @@ function createRequest(
|
|
|
219
221
|
);
|
|
220
222
|
return;
|
|
221
223
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
let receivedBytes = 0;
|
|
225
|
-
let settled = false;
|
|
226
|
-
const resolveResponse = () => {
|
|
227
|
-
if (settled) return;
|
|
228
|
-
settled = true;
|
|
224
|
+
if (noBodyResponse) {
|
|
225
|
+
response.resume();
|
|
229
226
|
resolve(
|
|
230
|
-
new Response(
|
|
227
|
+
new Response(null, {
|
|
231
228
|
status,
|
|
232
229
|
statusText: response.statusMessage,
|
|
233
230
|
headers: response.headers as HeadersInit,
|
|
234
231
|
}),
|
|
235
232
|
);
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
let receivedBytes = 0;
|
|
237
|
+
let bodySettled = false;
|
|
238
|
+
const body = new ReadableStream<Uint8Array>({
|
|
239
|
+
start(controller) {
|
|
240
|
+
response.on('data', (chunk) => {
|
|
241
|
+
if (bodySettled) return;
|
|
242
|
+
const buffer = Buffer.isBuffer(chunk)
|
|
243
|
+
? chunk
|
|
244
|
+
: Buffer.from(chunk);
|
|
245
|
+
const previousReceivedBytes = receivedBytes;
|
|
246
|
+
receivedBytes += buffer.byteLength;
|
|
247
|
+
if (
|
|
248
|
+
maxResponseBytes !== undefined &&
|
|
249
|
+
receivedBytes > maxResponseBytes &&
|
|
250
|
+
!truncateResponseBody
|
|
251
|
+
) {
|
|
252
|
+
bodySettled = true;
|
|
253
|
+
const error = new Error(
|
|
254
|
+
`Response body exceeds ${maxResponseBytes} byte limit.`,
|
|
255
|
+
);
|
|
256
|
+
controller.error(error);
|
|
257
|
+
response.destroy(error);
|
|
258
|
+
return;
|
|
262
259
|
}
|
|
263
|
-
if (
|
|
264
|
-
|
|
265
|
-
|
|
260
|
+
if (maxResponseBytes !== undefined && truncateResponseBody) {
|
|
261
|
+
const remainingBytes = Math.max(
|
|
262
|
+
0,
|
|
263
|
+
maxResponseBytes - previousReceivedBytes,
|
|
264
|
+
);
|
|
265
|
+
if (remainingBytes > 0) {
|
|
266
|
+
controller.enqueue(buffer.subarray(0, remainingBytes));
|
|
267
|
+
}
|
|
268
|
+
if (receivedBytes >= maxResponseBytes) {
|
|
269
|
+
bodySettled = true;
|
|
270
|
+
controller.close();
|
|
271
|
+
response.destroy();
|
|
272
|
+
}
|
|
273
|
+
return;
|
|
266
274
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
275
|
+
controller.enqueue(buffer);
|
|
276
|
+
});
|
|
277
|
+
response.on('error', (error) => {
|
|
278
|
+
if (bodySettled) return;
|
|
279
|
+
bodySettled = true;
|
|
280
|
+
controller.error(error);
|
|
281
|
+
});
|
|
282
|
+
response.on('end', () => {
|
|
283
|
+
if (bodySettled) return;
|
|
284
|
+
bodySettled = true;
|
|
285
|
+
controller.close();
|
|
286
|
+
});
|
|
287
|
+
},
|
|
288
|
+
cancel(reason) {
|
|
289
|
+
if (bodySettled) return;
|
|
290
|
+
bodySettled = true;
|
|
291
|
+
response.destroy(reason instanceof Error ? reason : undefined);
|
|
292
|
+
},
|
|
271
293
|
});
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
294
|
+
resolve(
|
|
295
|
+
new Response(body, {
|
|
296
|
+
status,
|
|
297
|
+
statusText: response.statusMessage,
|
|
298
|
+
headers: response.headers as HeadersInit,
|
|
299
|
+
}),
|
|
300
|
+
);
|
|
278
301
|
},
|
|
279
302
|
);
|
|
280
303
|
|
|
@@ -359,9 +382,21 @@ export async function safeOutboundFetch(
|
|
|
359
382
|
});
|
|
360
383
|
|
|
361
384
|
if (!isRedirectStatus(response.status)) {
|
|
362
|
-
return response;
|
|
385
|
+
if (options.streamResponseBody) return response;
|
|
386
|
+
const body = response.body ? await response.arrayBuffer() : null;
|
|
387
|
+
const buffered = new Response(body, {
|
|
388
|
+
status: response.status,
|
|
389
|
+
statusText: response.statusText,
|
|
390
|
+
headers: response.headers,
|
|
391
|
+
});
|
|
392
|
+
Object.defineProperty(buffered, 'url', {
|
|
393
|
+
configurable: true,
|
|
394
|
+
value: response.url,
|
|
395
|
+
});
|
|
396
|
+
return buffered;
|
|
363
397
|
}
|
|
364
398
|
if (redirectMode === 'error') {
|
|
399
|
+
void response.body?.cancel().catch(() => undefined);
|
|
365
400
|
throw new Error(
|
|
366
401
|
`Redirect blocked while fetching ${currentUrl.toString()}.`,
|
|
367
402
|
);
|
|
@@ -375,11 +410,13 @@ export async function safeOutboundFetch(
|
|
|
375
410
|
return response;
|
|
376
411
|
}
|
|
377
412
|
if (redirectCount === maxRedirects) {
|
|
413
|
+
void response.body?.cancel().catch(() => undefined);
|
|
378
414
|
throw new Error(
|
|
379
415
|
`Too many redirects while fetching ${currentUrl.toString()}.`,
|
|
380
416
|
);
|
|
381
417
|
}
|
|
382
418
|
|
|
419
|
+
void response.body?.cancel().catch(() => undefined);
|
|
383
420
|
const nextUrl = resolveRedirectUrl(location, currentUrl);
|
|
384
421
|
currentInit = initForRedirect(
|
|
385
422
|
currentInit,
|