alchemy 2.0.0-beta.39 → 2.0.0-beta.40
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/bin/exec.js +5 -26
- package/bin/exec.js.map +1 -1
- package/lib/Auth/Lock.d.ts +4 -3
- package/lib/Auth/Lock.d.ts.map +1 -1
- package/lib/Auth/Lock.js +6 -5
- package/lib/Auth/Lock.js.map +1 -1
- package/lib/Axiom/Chart.d.ts +52 -2
- package/lib/Axiom/Chart.d.ts.map +1 -1
- package/lib/Bundle/Bundle.d.ts +7 -4
- package/lib/Bundle/Bundle.d.ts.map +1 -1
- package/lib/Bundle/Bundle.js +37 -14
- package/lib/Bundle/Bundle.js.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts +11 -11
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.js +28 -63
- package/lib/Cloudflare/AiGateway/AiGateway.js.map +1 -1
- package/lib/Cloudflare/Bridge.d.ts +3 -0
- package/lib/Cloudflare/Bridge.d.ts.map +1 -0
- package/lib/Cloudflare/Bridge.js +3 -0
- package/lib/Cloudflare/Bridge.js.map +1 -0
- package/lib/Cloudflare/Container/StartContainer.d.ts +2 -2
- package/lib/Cloudflare/Container/StartContainer.d.ts.map +1 -1
- package/lib/Cloudflare/Container/StartContainer.js +3 -3
- package/lib/Cloudflare/Container/StartContainer.js.map +1 -1
- package/lib/Cloudflare/Local/Sidecar.d.ts +45 -21
- package/lib/Cloudflare/Local/Sidecar.d.ts.map +1 -1
- package/lib/Cloudflare/Local/Sidecar.js +30 -6
- package/lib/Cloudflare/Local/Sidecar.js.map +1 -1
- package/lib/Cloudflare/Local/SidecarHandlers.d.ts +5 -2
- package/lib/Cloudflare/Local/SidecarHandlers.d.ts.map +1 -1
- package/lib/Cloudflare/Local/SidecarHandlers.js +323 -70
- package/lib/Cloudflare/Local/SidecarHandlers.js.map +1 -1
- package/lib/Cloudflare/Local/SidecarServer.js +9 -5
- package/lib/Cloudflare/Local/SidecarServer.js.map +1 -1
- package/lib/Cloudflare/StateStore/Api.d.ts +1 -1
- package/lib/Cloudflare/StateStore/Api.js +1 -1
- package/lib/Cloudflare/StateStore/Store.d.ts +1 -1
- package/lib/Cloudflare/Workers/HttpServer.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/HttpServer.js +3 -25
- package/lib/Cloudflare/Workers/HttpServer.js.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +1 -2
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +16 -97
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/Vite.d.ts +9 -0
- package/lib/Cloudflare/Workers/Vite.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/Vite.js +95 -0
- package/lib/Cloudflare/Workers/Vite.js.map +1 -0
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +9 -95
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.d.ts +1 -2
- package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.js +5 -4
- package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
- package/lib/Diff.d.ts +15 -1
- package/lib/Diff.d.ts.map +1 -1
- package/lib/Diff.js +13 -7
- package/lib/Diff.js.map +1 -1
- package/lib/Http.d.ts.map +1 -1
- package/lib/Http.js +12 -7
- package/lib/Http.js.map +1 -1
- package/lib/Sidecar/Lock.d.ts +4 -5
- package/lib/Sidecar/Lock.d.ts.map +1 -1
- package/lib/Sidecar/Lock.js +22 -85
- package/lib/Sidecar/Lock.js.map +1 -1
- package/lib/Sidecar/RpcHandler.d.ts +4 -1
- package/lib/Sidecar/RpcHandler.d.ts.map +1 -1
- package/lib/Sidecar/RpcHandler.js +21 -2
- package/lib/Sidecar/RpcHandler.js.map +1 -1
- package/lib/Util/PlatformServices.d.ts.map +1 -1
- package/lib/Util/PlatformServices.js +0 -2
- package/lib/Util/PlatformServices.js.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +17 -12
- package/src/AWS/EC2/hosted.ts +1 -1
- package/src/AWS/ECS/Task.ts +1 -1
- package/src/AWS/Lambda/Function.ts +1 -1
- package/src/Auth/Lock.ts +6 -5
- package/src/Axiom/Chart.ts +56 -2
- package/src/Bundle/Bundle.ts +41 -17
- package/src/Cloudflare/AiGateway/AiGateway.ts +43 -76
- package/src/Cloudflare/Bridge.ts +2 -0
- package/src/Cloudflare/Container/ContainerApplication.ts +1 -1
- package/src/Cloudflare/Container/StartContainer.ts +10 -3
- package/src/Cloudflare/Local/Sidecar.ts +50 -21
- package/src/Cloudflare/Local/SidecarHandlers.ts +395 -91
- package/src/Cloudflare/Local/SidecarServer.ts +12 -4
- package/src/Cloudflare/StateStore/Api.ts +1 -1
- package/src/Cloudflare/Workers/HttpServer.ts +5 -37
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +18 -111
- package/src/Cloudflare/Workers/Vite.ts +114 -0
- package/src/Cloudflare/Workers/Worker.ts +27 -109
- package/src/Cloudflare/Workers/WorkerBundle.ts +7 -7
- package/src/Diff.ts +29 -8
- package/src/Http.ts +14 -10
- package/src/Sidecar/Lock.ts +30 -154
- package/src/Sidecar/RpcHandler.ts +67 -40
- package/src/Util/PlatformServices.ts +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.40",
|
|
4
4
|
"homepage": "https://alchemy.run",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Sam Goodwin <sam@alchemy.run>",
|
|
@@ -130,6 +130,12 @@
|
|
|
130
130
|
"worker": "./src/Cloudflare/index.ts",
|
|
131
131
|
"import": "./lib/Cloudflare/index.js"
|
|
132
132
|
},
|
|
133
|
+
"./Cloudflare/Bridge": {
|
|
134
|
+
"types": "./lib/Cloudflare/Bridge.d.ts",
|
|
135
|
+
"bun": "./src/Cloudflare/Bridge.ts",
|
|
136
|
+
"worker": "./src/Cloudflare/Bridge.ts",
|
|
137
|
+
"import": "./lib/Cloudflare/Bridge.js"
|
|
138
|
+
},
|
|
133
139
|
"./Cloudflare/Live": {
|
|
134
140
|
"types": "./lib/Cloudflare/Live.d.ts",
|
|
135
141
|
"bun": "./src/Cloudflare/Live.ts",
|
|
@@ -270,17 +276,17 @@
|
|
|
270
276
|
"access": "public"
|
|
271
277
|
},
|
|
272
278
|
"dependencies": {
|
|
279
|
+
"@alchemy.run/node-utils": "0.0.2",
|
|
273
280
|
"@aws-sdk/credential-providers": "^3.0.0",
|
|
274
281
|
"@clack/prompts": "^0.11.0",
|
|
275
|
-
"@distilled.cloud/aws": "^0.
|
|
276
|
-
"@distilled.cloud/axiom": "^0.
|
|
277
|
-
"@distilled.cloud/cloudflare": "^0.
|
|
278
|
-
"@distilled.cloud/cloudflare-rolldown-plugin": "0.
|
|
279
|
-
"@distilled.cloud/cloudflare-runtime": "0.
|
|
280
|
-
"@distilled.cloud/cloudflare-vite-plugin": "0.
|
|
281
|
-
"@distilled.cloud/core": "^0.
|
|
282
|
-
"@distilled.cloud/neon": "^0.
|
|
283
|
-
"pg": "^8.13.0",
|
|
282
|
+
"@distilled.cloud/aws": "^0.21.0",
|
|
283
|
+
"@distilled.cloud/axiom": "^0.21.0",
|
|
284
|
+
"@distilled.cloud/cloudflare": "^0.21.0",
|
|
285
|
+
"@distilled.cloud/cloudflare-rolldown-plugin": "0.5.4",
|
|
286
|
+
"@distilled.cloud/cloudflare-runtime": "0.5.4",
|
|
287
|
+
"@distilled.cloud/cloudflare-vite-plugin": "0.5.4",
|
|
288
|
+
"@distilled.cloud/core": "^0.21.0",
|
|
289
|
+
"@distilled.cloud/neon": "^0.21.0",
|
|
284
290
|
"@effect/vitest": ">=4.0.0-beta.66 || >=4.0.0",
|
|
285
291
|
"@libsql/client": "^0.17.0",
|
|
286
292
|
"@octokit/rest": "^22.0.1",
|
|
@@ -298,8 +304,8 @@
|
|
|
298
304
|
"libsodium-wrappers": "^0.8.3",
|
|
299
305
|
"magic-string": "^0.30.21",
|
|
300
306
|
"pathe": "^2.0.3",
|
|
307
|
+
"pg": "^8.13.0",
|
|
301
308
|
"picomatch": "^4.0.4",
|
|
302
|
-
"proper-lockfile": "^4.1.2",
|
|
303
309
|
"react": "^19.2.0",
|
|
304
310
|
"rolldown": "1.0.0-rc.17",
|
|
305
311
|
"sonda": "^0.11.1",
|
|
@@ -318,7 +324,6 @@
|
|
|
318
324
|
"@types/bun": "latest",
|
|
319
325
|
"@types/node": "latest",
|
|
320
326
|
"@types/picomatch": "^4.0.0",
|
|
321
|
-
"@types/proper-lockfile": "^4.1.4",
|
|
322
327
|
"@types/react": "^19.2.2",
|
|
323
328
|
"@types/ws": "^8.18.1",
|
|
324
329
|
"better-auth": "^1.6.2",
|
package/src/AWS/EC2/hosted.ts
CHANGED
|
@@ -231,7 +231,7 @@ import * as Layer from "effect/Layer";
|
|
|
231
231
|
import * as Logger from "effect/Logger";
|
|
232
232
|
import * as Region from "@distilled.cloud/aws/Region";
|
|
233
233
|
|
|
234
|
-
import { ${handler} as handler } from
|
|
234
|
+
import { ${handler} as handler } from ${JSON.stringify(importPath)};
|
|
235
235
|
|
|
236
236
|
const platform = Layer.mergeAll(
|
|
237
237
|
NodeServices.layer,
|
package/src/AWS/ECS/Task.ts
CHANGED
|
@@ -492,7 +492,7 @@ import * as Layer from "effect/Layer";
|
|
|
492
492
|
import * as Logger from "effect/Logger";
|
|
493
493
|
import * as Region from "@distilled.cloud/aws/Region";
|
|
494
494
|
|
|
495
|
-
import { ${handler} as handler } from
|
|
495
|
+
import { ${handler} as handler } from ${JSON.stringify(importPath)};
|
|
496
496
|
|
|
497
497
|
const platform = Layer.mergeAll(
|
|
498
498
|
NodeServices.layer,
|
|
@@ -679,7 +679,7 @@ import * as Region from "@distilled.cloud/aws/Region";
|
|
|
679
679
|
import * as Context from "effect/Context";
|
|
680
680
|
import { MinimumLogLevel } from "effect/References";
|
|
681
681
|
|
|
682
|
-
import entrypoint from
|
|
682
|
+
import entrypoint from ${JSON.stringify(importPath)};
|
|
683
683
|
|
|
684
684
|
const tag = Context.Service("${Self.key}")
|
|
685
685
|
const layer = makeEntrypointLayer(tag, entrypoint);
|
package/src/Auth/Lock.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import * as lockfile from "@alchemy.run/node-utils";
|
|
1
2
|
import * as Effect from "effect/Effect";
|
|
2
3
|
import * as fs from "node:fs/promises";
|
|
3
4
|
import * as path from "pathe";
|
|
4
|
-
import lockfile from "proper-lockfile";
|
|
5
5
|
import { rootDir } from "./Profile.ts";
|
|
6
6
|
|
|
7
7
|
const lockDir = path.join(rootDir, "lock");
|
|
@@ -11,9 +11,10 @@ const lockDir = path.join(rootDir, "lock");
|
|
|
11
11
|
* critical section concurrently for the same `key`, both within this
|
|
12
12
|
* process and across other processes on the same machine.
|
|
13
13
|
*
|
|
14
|
-
* Uses
|
|
15
|
-
* (so same-process callers wait via `retries`) and uses
|
|
16
|
-
* for cross-process coordination, with stale-lock
|
|
14
|
+
* Uses `@alchemy.run/node-utils` lockfile for both: it tracks in-process
|
|
15
|
+
* holders by path (so same-process callers wait via `retries`) and uses
|
|
16
|
+
* an OS file lock for cross-process coordination, with stale-lock
|
|
17
|
+
* detection at 60s.
|
|
17
18
|
*/
|
|
18
19
|
export const withLock = <A, E, R>(
|
|
19
20
|
key: string,
|
|
@@ -23,10 +24,10 @@ export const withLock = <A, E, R>(
|
|
|
23
24
|
return Effect.acquireUseRelease(
|
|
24
25
|
Effect.promise(async () => {
|
|
25
26
|
await fs.mkdir(lockDir, { recursive: true });
|
|
26
|
-
await fs.writeFile(lockPath, "", { flag: "a" });
|
|
27
27
|
return await lockfile.lock(lockPath, {
|
|
28
28
|
retries: { retries: 600, minTimeout: 50, maxTimeout: 50 },
|
|
29
29
|
stale: 5_000,
|
|
30
|
+
realpath: false,
|
|
30
31
|
});
|
|
31
32
|
}),
|
|
32
33
|
() => effect,
|
package/src/Axiom/Chart.ts
CHANGED
|
@@ -24,7 +24,8 @@ export type ChartKind =
|
|
|
24
24
|
| "Statistic"
|
|
25
25
|
| "Heatmap"
|
|
26
26
|
| "LogStream"
|
|
27
|
-
| "Note"
|
|
27
|
+
| "Note"
|
|
28
|
+
| "SmartFilter";
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Minimum chart payload Axiom's `POST /v2/dashboards` accepts.
|
|
@@ -67,6 +68,58 @@ export interface NoteChart extends BaseChart {
|
|
|
67
68
|
readonly type: "Note";
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
/**
|
|
72
|
+
* A dashboard filter bar (Axiom calls it `SmartFilter` on the wire,
|
|
73
|
+
* `Filter bar` in the UI). Holds one or more filters whose IDs can
|
|
74
|
+
* be referenced from other charts' APL via
|
|
75
|
+
* `declare query_parameters (<filter-id>:string = "")`.
|
|
76
|
+
*
|
|
77
|
+
* Unlike data charts, `SmartFilter` has no top-level `query` field —
|
|
78
|
+
* each filter inside `filters` may carry its own option-source APL.
|
|
79
|
+
*/
|
|
80
|
+
export interface SmartFilterChart {
|
|
81
|
+
readonly id: string;
|
|
82
|
+
readonly type: "SmartFilter";
|
|
83
|
+
/** Optional display name for the filter bar element. */
|
|
84
|
+
readonly name?: string;
|
|
85
|
+
readonly filters: readonly SmartFilter[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* One filter inside a {@link SmartFilterChart}. Either a free-text
|
|
90
|
+
* `search` filter or a dropdown `select` filter. Select filters draw
|
|
91
|
+
* their options from either an inline `list` or an APL `query`.
|
|
92
|
+
*/
|
|
93
|
+
export type SmartFilter = SmartFilterSearch | SmartFilterSelect;
|
|
94
|
+
|
|
95
|
+
export interface SmartFilterSearch {
|
|
96
|
+
readonly id: string;
|
|
97
|
+
readonly type: "search";
|
|
98
|
+
readonly name?: string;
|
|
99
|
+
readonly active?: boolean;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface SmartFilterSelect {
|
|
103
|
+
readonly id: string;
|
|
104
|
+
readonly type: "select";
|
|
105
|
+
readonly name?: string;
|
|
106
|
+
readonly active?: boolean;
|
|
107
|
+
/** `"list"` for inline `options`, `"apl"` for a query-driven dropdown. */
|
|
108
|
+
readonly selectType?: "list" | "apl";
|
|
109
|
+
/**
|
|
110
|
+
* APL query that returns rows shaped `{ key, value }`. Axiom shows
|
|
111
|
+
* `key` in the dropdown and substitutes `value` into chart queries.
|
|
112
|
+
*/
|
|
113
|
+
readonly apl?: { readonly apl: string };
|
|
114
|
+
/** Inline key/value options when `selectType === "list"`. */
|
|
115
|
+
readonly options?: readonly {
|
|
116
|
+
readonly id?: string;
|
|
117
|
+
readonly key: string;
|
|
118
|
+
readonly value: string;
|
|
119
|
+
readonly default?: boolean;
|
|
120
|
+
}[];
|
|
121
|
+
}
|
|
122
|
+
|
|
70
123
|
export type Chart =
|
|
71
124
|
| TimeSeriesChart
|
|
72
125
|
| TableChart
|
|
@@ -74,7 +127,8 @@ export type Chart =
|
|
|
74
127
|
| StatisticChart
|
|
75
128
|
| HeatmapChart
|
|
76
129
|
| LogStreamChart
|
|
77
|
-
| NoteChart
|
|
130
|
+
| NoteChart
|
|
131
|
+
| SmartFilterChart;
|
|
78
132
|
|
|
79
133
|
/**
|
|
80
134
|
* Mirrors Axiom's `CreateDashboardInput.dashboard.layout` cell schema.
|
package/src/Bundle/Bundle.ts
CHANGED
|
@@ -186,34 +186,58 @@ export const watch = (
|
|
|
186
186
|
),
|
|
187
187
|
);
|
|
188
188
|
|
|
189
|
-
const
|
|
190
|
-
|
|
189
|
+
const ENTRY_PREFIX = "\0virtual:alchemy-entry:";
|
|
190
|
+
// oxlint-disable-next-line no-control-regex
|
|
191
|
+
const ENTRY_REGEX = /^\0virtual:alchemy-entry:/;
|
|
191
192
|
|
|
192
193
|
export const virtualEntryPlugin = Effect.gen(function* () {
|
|
193
194
|
const path = yield* Path.Path;
|
|
195
|
+
|
|
196
|
+
const normalizeInput = (
|
|
197
|
+
input: rolldown.InputOption,
|
|
198
|
+
): Record<string, string> => {
|
|
199
|
+
if (typeof input === "string") {
|
|
200
|
+
return { [path.parse(input).name || "index"]: input };
|
|
201
|
+
} else if (Array.isArray(input)) {
|
|
202
|
+
return Object.fromEntries(input.map((p) => [path.parse(p).name, p]));
|
|
203
|
+
} else {
|
|
204
|
+
return input;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
194
208
|
return (content: (importPath: string) => string) => {
|
|
195
|
-
|
|
209
|
+
const entries = new Map<string, string>();
|
|
196
210
|
return {
|
|
197
211
|
name: "alchemy:virtual-entry",
|
|
198
|
-
options
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
212
|
+
options: {
|
|
213
|
+
order: "pre",
|
|
214
|
+
handler(inputOptions) {
|
|
215
|
+
const cwd = inputOptions.cwd ?? process.cwd();
|
|
216
|
+
const input = normalizeInput(inputOptions.input ?? {});
|
|
217
|
+
inputOptions.input = Object.fromEntries(
|
|
218
|
+
Object.entries(input).map(([name, p]) => {
|
|
219
|
+
const id = `${ENTRY_PREFIX}${name}`;
|
|
220
|
+
entries.set(id, path.resolve(cwd, p));
|
|
221
|
+
return [name, id];
|
|
222
|
+
}),
|
|
223
|
+
);
|
|
224
|
+
},
|
|
205
225
|
},
|
|
206
226
|
resolveId: {
|
|
207
|
-
filter: { id:
|
|
208
|
-
handler() {
|
|
209
|
-
return { id:
|
|
227
|
+
filter: { id: ENTRY_REGEX },
|
|
228
|
+
handler(id) {
|
|
229
|
+
return entries.has(id) ? { id } : null;
|
|
210
230
|
},
|
|
211
231
|
},
|
|
212
232
|
load: {
|
|
213
|
-
filter: { id:
|
|
214
|
-
handler() {
|
|
215
|
-
|
|
216
|
-
|
|
233
|
+
filter: { id: ENTRY_REGEX },
|
|
234
|
+
handler(id) {
|
|
235
|
+
const entry = entries.get(id);
|
|
236
|
+
assert(entry !== undefined, `unknown alchemy entry: ${id}`);
|
|
237
|
+
return {
|
|
238
|
+
code: content(entry),
|
|
239
|
+
moduleType: "ts",
|
|
240
|
+
};
|
|
217
241
|
},
|
|
218
242
|
},
|
|
219
243
|
} satisfies rolldown.Plugin;
|
|
@@ -200,17 +200,17 @@ export type AiGateway = Resource<
|
|
|
200
200
|
rateLimitingInterval: number | null;
|
|
201
201
|
rateLimitingLimit: number | null;
|
|
202
202
|
rateLimitingTechnique: AiGatewayRateLimitingTechnique;
|
|
203
|
-
authentication: boolean
|
|
204
|
-
dlp: AiGatewayDlp |
|
|
205
|
-
isDefault: boolean
|
|
206
|
-
logManagement: number
|
|
207
|
-
logManagementStrategy: AiGatewayLogManagementStrategy
|
|
208
|
-
logpush: boolean
|
|
209
|
-
logpushPublicKey: string |
|
|
210
|
-
otel: AiGatewayOtel[] |
|
|
211
|
-
storeId: string
|
|
212
|
-
stripe: AiGatewayStripe |
|
|
213
|
-
zdr: boolean
|
|
203
|
+
authentication: boolean;
|
|
204
|
+
dlp: AiGatewayDlp | undefined;
|
|
205
|
+
isDefault: boolean;
|
|
206
|
+
logManagement: number;
|
|
207
|
+
logManagementStrategy: AiGatewayLogManagementStrategy;
|
|
208
|
+
logpush: boolean;
|
|
209
|
+
logpushPublicKey: string | undefined;
|
|
210
|
+
otel: AiGatewayOtel[] | undefined;
|
|
211
|
+
storeId: string;
|
|
212
|
+
stripe: AiGatewayStripe | undefined;
|
|
213
|
+
zdr: boolean;
|
|
214
214
|
},
|
|
215
215
|
never,
|
|
216
216
|
Providers
|
|
@@ -301,17 +301,21 @@ export const AiGatewayProvider = () =>
|
|
|
301
301
|
rateLimitingInterval: props?.rateLimitingInterval ?? null,
|
|
302
302
|
rateLimitingLimit: props?.rateLimitingLimit ?? null,
|
|
303
303
|
rateLimitingTechnique: props?.rateLimitingTechnique ?? "fixed",
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
304
|
+
// Defaults align with what Cloudflare's API returns for an
|
|
305
|
+
// unconfigured gateway, so the reconciler converges to noop
|
|
306
|
+
// when the user didn't explicitly set the field.
|
|
307
|
+
authentication: props?.authentication ?? false,
|
|
308
|
+
dlp: props?.dlp ?? undefined,
|
|
309
|
+
isDefault: props?.isDefault ?? false,
|
|
310
|
+
logManagement: props?.logManagement ?? 100_000,
|
|
311
|
+
logManagementStrategy:
|
|
312
|
+
props?.logManagementStrategy ?? "STOP_INSERTING",
|
|
313
|
+
logpush: props?.logpush ?? false,
|
|
314
|
+
logpushPublicKey: props?.logpushPublicKey ?? undefined,
|
|
315
|
+
otel: props?.otel ?? undefined,
|
|
316
|
+
storeId: props?.storeId ?? "",
|
|
317
|
+
stripe: props?.stripe ?? undefined,
|
|
318
|
+
zdr: props?.zdr ?? false,
|
|
315
319
|
};
|
|
316
320
|
});
|
|
317
321
|
|
|
@@ -334,17 +338,18 @@ export const AiGatewayProvider = () =>
|
|
|
334
338
|
rateLimitingInterval: nullIfZero(gateway.rateLimitingInterval),
|
|
335
339
|
rateLimitingLimit: nullIfZero(gateway.rateLimitingLimit),
|
|
336
340
|
rateLimitingTechnique: gateway.rateLimitingTechnique ?? "fixed",
|
|
337
|
-
authentication: gateway.authentication ??
|
|
338
|
-
dlp: gateway.dlp,
|
|
339
|
-
isDefault: gateway.isDefault ??
|
|
340
|
-
logManagement: gateway.logManagement,
|
|
341
|
-
logManagementStrategy:
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
341
|
+
authentication: gateway.authentication ?? false,
|
|
342
|
+
dlp: gateway.dlp ?? undefined,
|
|
343
|
+
isDefault: gateway.isDefault ?? false,
|
|
344
|
+
logManagement: gateway.logManagement ?? 100_000,
|
|
345
|
+
logManagementStrategy:
|
|
346
|
+
gateway.logManagementStrategy ?? "STOP_INSERTING",
|
|
347
|
+
logpush: gateway.logpush ?? false,
|
|
348
|
+
logpushPublicKey: gateway.logpushPublicKey ?? undefined,
|
|
349
|
+
otel: gateway.otel ?? undefined,
|
|
350
|
+
storeId: gateway.storeId ?? "",
|
|
351
|
+
stripe: gateway.stripe ?? undefined,
|
|
352
|
+
zdr: gateway.zdr ?? false,
|
|
348
353
|
});
|
|
349
354
|
|
|
350
355
|
const mutable = (gateway: AiGateway["Attributes"]) => ({
|
|
@@ -355,7 +360,7 @@ export const AiGatewayProvider = () =>
|
|
|
355
360
|
rateLimitingLimit: gateway.rateLimitingLimit,
|
|
356
361
|
rateLimitingTechnique: gateway.rateLimitingTechnique,
|
|
357
362
|
authentication: gateway.authentication,
|
|
358
|
-
dlp: gateway.dlp
|
|
363
|
+
dlp: gateway.dlp,
|
|
359
364
|
isDefault: gateway.isDefault,
|
|
360
365
|
logManagement: gateway.logManagement,
|
|
361
366
|
logManagementStrategy: gateway.logManagementStrategy,
|
|
@@ -434,48 +439,10 @@ export const AiGatewayProvider = () =>
|
|
|
434
439
|
return { action: "replace" } as const;
|
|
435
440
|
}
|
|
436
441
|
|
|
437
|
-
const oldMutable =
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
cacheInvalidateOnUpdate: old.cacheInvalidateOnUpdate,
|
|
442
|
-
cacheTtl: old.cacheTtl,
|
|
443
|
-
collectLogs: old.collectLogs,
|
|
444
|
-
rateLimitingInterval: old.rateLimitingInterval,
|
|
445
|
-
rateLimitingLimit: old.rateLimitingLimit,
|
|
446
|
-
rateLimitingTechnique: old.rateLimitingTechnique,
|
|
447
|
-
authentication: old.authentication,
|
|
448
|
-
dlp: old.dlp,
|
|
449
|
-
isDefault: old.isDefault,
|
|
450
|
-
logManagement: old.logManagement,
|
|
451
|
-
logManagementStrategy: old.logManagementStrategy,
|
|
452
|
-
logpush: old.logpush,
|
|
453
|
-
logpushPublicKey: old.logpushPublicKey,
|
|
454
|
-
otel: old.otel,
|
|
455
|
-
storeId: old.storeId,
|
|
456
|
-
stripe: old.stripe,
|
|
457
|
-
zdr: old.zdr,
|
|
458
|
-
})),
|
|
459
|
-
);
|
|
460
|
-
const nextMutable = {
|
|
461
|
-
cacheInvalidateOnUpdate: next.cacheInvalidateOnUpdate,
|
|
462
|
-
cacheTtl: next.cacheTtl,
|
|
463
|
-
collectLogs: next.collectLogs,
|
|
464
|
-
rateLimitingInterval: next.rateLimitingInterval,
|
|
465
|
-
rateLimitingLimit: next.rateLimitingLimit,
|
|
466
|
-
rateLimitingTechnique: next.rateLimitingTechnique,
|
|
467
|
-
authentication: next.authentication,
|
|
468
|
-
dlp: next.dlp,
|
|
469
|
-
isDefault: next.isDefault,
|
|
470
|
-
logManagement: next.logManagement,
|
|
471
|
-
logManagementStrategy: next.logManagementStrategy,
|
|
472
|
-
logpush: next.logpush,
|
|
473
|
-
logpushPublicKey: next.logpushPublicKey,
|
|
474
|
-
otel: next.otel,
|
|
475
|
-
storeId: next.storeId,
|
|
476
|
-
stripe: next.stripe,
|
|
477
|
-
zdr: next.zdr,
|
|
478
|
-
};
|
|
442
|
+
const oldMutable = mutable(
|
|
443
|
+
output ?? ((yield* desired(id, olds)) as AiGateway["Attributes"]),
|
|
444
|
+
);
|
|
445
|
+
const nextMutable = mutable(next as AiGateway["Attributes"]);
|
|
479
446
|
if (!deepEqual(oldMutable, nextMutable)) {
|
|
480
447
|
return { action: "update" } as const;
|
|
481
448
|
}
|
|
@@ -540,7 +540,7 @@ import * as Logger from "effect/Logger";
|
|
|
540
540
|
import * as Context from "effect/Context";
|
|
541
541
|
import { MinimumLogLevel } from "effect/References";
|
|
542
542
|
|
|
543
|
-
import ${handler === "default" ? "entrypoint" : `{ ${handler} as entrypoint }`} from
|
|
543
|
+
import ${handler === "default" ? "entrypoint" : `{ ${handler} as entrypoint }`} from ${JSON.stringify(importPath)};
|
|
544
544
|
|
|
545
545
|
const tag = Context.Service("${Self.key}")
|
|
546
546
|
const layer = makeEntrypointLayer(tag, entrypoint);
|
|
@@ -7,7 +7,11 @@ import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
|
|
|
7
7
|
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
|
|
8
8
|
import { type Fetcher } from "../Fetcher.ts";
|
|
9
9
|
import { DurableObjectState } from "../Workers/DurableObjectState.ts";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
type Container,
|
|
12
|
+
type ContainerStartupOptions,
|
|
13
|
+
ContainerError,
|
|
14
|
+
} from "./Container.ts";
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
17
|
* Runs the Container in a Durable Object and monitors it, providing a durable fetch and RPC interface to it.
|
|
@@ -15,13 +19,16 @@ import { type Container, ContainerError } from "./Container.ts";
|
|
|
15
19
|
export const start = Effect.fnUntraced(function* <
|
|
16
20
|
Shape extends Container,
|
|
17
21
|
Req = never,
|
|
18
|
-
>(
|
|
22
|
+
>(
|
|
23
|
+
containerEff: Effect.Effect<Shape, never, Req | DurableObjectState>,
|
|
24
|
+
options?: ContainerStartupOptions,
|
|
25
|
+
) {
|
|
19
26
|
const container = yield* containerEff;
|
|
20
27
|
|
|
21
28
|
const ensureRunning = Effect.gen(function* () {
|
|
22
29
|
if (yield* container.running) return;
|
|
23
30
|
yield* Effect.logInfo("Container not running, starting...");
|
|
24
|
-
yield* container.start();
|
|
31
|
+
yield* container.start(options);
|
|
25
32
|
yield* Effect.logInfo("Container started, launching monitor");
|
|
26
33
|
yield* Effect.forkDetach(
|
|
27
34
|
container.monitor().pipe(
|
|
@@ -1,48 +1,77 @@
|
|
|
1
1
|
import { RuntimeError } from "@distilled.cloud/cloudflare-runtime/RuntimeError";
|
|
2
|
-
import * as Worker from "@distilled.cloud/cloudflare-runtime/Worker";
|
|
3
2
|
import * as Effect from "effect/Effect";
|
|
4
3
|
import * as Schema from "effect/Schema";
|
|
5
4
|
import { BundleError } from "../../Bundle/Bundle.ts";
|
|
5
|
+
import type { ResourceBinding } from "../../Resource.ts";
|
|
6
6
|
import * as RpcClient from "../../Sidecar/RpcClient.ts";
|
|
7
7
|
import { defineSchema } from "../../Sidecar/RpcHandler.ts";
|
|
8
|
-
import type {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
bindings:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* Forwarded to the runtime as the worker's `hyperdrives` field.
|
|
17
|
-
*/
|
|
18
|
-
hyperdrives?: Record<string, Worker.HyperdriveOrigin>;
|
|
19
|
-
durableObjectNamespaces: Worker.DurableObjectNamespace[];
|
|
8
|
+
import type { Worker, WorkerProps } from "../Workers/Worker.ts";
|
|
9
|
+
|
|
10
|
+
export interface ReconcileOptions {
|
|
11
|
+
id: string;
|
|
12
|
+
props: WorkerProps;
|
|
13
|
+
bindings: ResourceBinding<Worker["Binding"]>[];
|
|
14
|
+
stack: { name: string; stage: string };
|
|
15
|
+
instanceId: string;
|
|
20
16
|
}
|
|
21
17
|
|
|
18
|
+
export class ValidationError extends Schema.TaggedErrorClass<ValidationError>()(
|
|
19
|
+
"ValidationError",
|
|
20
|
+
{
|
|
21
|
+
message: Schema.String,
|
|
22
|
+
hint: Schema.optional(Schema.String),
|
|
23
|
+
value: Schema.Unknown,
|
|
24
|
+
},
|
|
25
|
+
) {}
|
|
26
|
+
|
|
22
27
|
export const ServeResult = Schema.Struct({
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
workerId: Schema.String,
|
|
29
|
+
workerName: Schema.String,
|
|
30
|
+
logpush: Schema.UndefinedOr(Schema.Boolean),
|
|
31
|
+
url: Schema.String,
|
|
32
|
+
tags: Schema.Array(Schema.String).pipe(Schema.mutable),
|
|
33
|
+
durableObjectNamespaces: Schema.Record(Schema.String, Schema.String),
|
|
34
|
+
domains: Schema.Array(
|
|
35
|
+
Schema.Struct({
|
|
36
|
+
hostname: Schema.String,
|
|
37
|
+
id: Schema.String,
|
|
38
|
+
zoneId: Schema.String,
|
|
39
|
+
}),
|
|
40
|
+
).pipe(Schema.mutable),
|
|
41
|
+
crons: Schema.Array(Schema.String).pipe(Schema.mutable),
|
|
42
|
+
accountId: Schema.String,
|
|
25
43
|
});
|
|
26
44
|
export type ServeResult = typeof ServeResult.Type;
|
|
27
45
|
|
|
28
|
-
export const ServeError = Schema.Union([
|
|
46
|
+
export const ServeError = Schema.Union([
|
|
47
|
+
RuntimeError,
|
|
48
|
+
BundleError,
|
|
49
|
+
ValidationError,
|
|
50
|
+
]);
|
|
29
51
|
export type ServeError = typeof ServeError.Type;
|
|
30
52
|
|
|
53
|
+
export const DiffResult = Schema.Struct({
|
|
54
|
+
action: Schema.Literals(["update", "noop"]),
|
|
55
|
+
});
|
|
56
|
+
export type DiffResult = typeof DiffResult.Type;
|
|
57
|
+
|
|
31
58
|
export const SidecarSchema = defineSchema<Sidecar["Service"]>({
|
|
32
|
-
|
|
59
|
+
diff: { success: DiffResult, error: Schema.Never },
|
|
60
|
+
reconcile: {
|
|
33
61
|
success: ServeResult,
|
|
34
62
|
error: ServeError,
|
|
35
63
|
},
|
|
36
|
-
|
|
64
|
+
delete: { success: Schema.Void, error: Schema.Never },
|
|
37
65
|
});
|
|
38
66
|
|
|
39
67
|
export class Sidecar extends RpcClient.RpcClientService<
|
|
40
68
|
Sidecar,
|
|
41
69
|
{
|
|
42
|
-
readonly
|
|
43
|
-
|
|
70
|
+
readonly diff: (options: ReconcileOptions) => Effect.Effect<DiffResult>;
|
|
71
|
+
readonly reconcile: (
|
|
72
|
+
options: ReconcileOptions,
|
|
44
73
|
) => Effect.Effect<ServeResult, ServeError>;
|
|
45
|
-
readonly
|
|
74
|
+
readonly delete: (id: string) => Effect.Effect<void>;
|
|
46
75
|
}
|
|
47
76
|
>()("Sidecar") {}
|
|
48
77
|
|