alchemy 0.93.12 → 0.94.0
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 +1 -1
- package/bin/alchemy.js +4 -4
- package/lib/aws/control/client.d.ts.map +1 -1
- package/lib/aws/control/client.js +2 -1
- package/lib/aws/control/client.js.map +1 -1
- package/lib/aws/control/resource.d.ts.map +1 -1
- package/lib/aws/control/resource.js +46 -5
- package/lib/aws/control/resource.js.map +1 -1
- package/lib/aws/ec2/utils.d.ts.map +1 -1
- package/lib/aws/ec2/utils.js +5 -3
- package/lib/aws/ec2/utils.js.map +1 -1
- package/lib/aws/utils.d.ts +8 -1
- package/lib/aws/utils.d.ts.map +1 -1
- package/lib/aws/utils.js +14 -1
- package/lib/aws/utils.js.map +1 -1
- package/lib/cloudflare/artifacts.d.ts +54 -0
- package/lib/cloudflare/artifacts.d.ts.map +1 -0
- package/lib/cloudflare/artifacts.js +14 -0
- package/lib/cloudflare/artifacts.js.map +1 -0
- package/lib/cloudflare/bindings.d.ts +16 -4
- package/lib/cloudflare/bindings.d.ts.map +1 -1
- package/lib/cloudflare/bindings.js.map +1 -1
- package/lib/cloudflare/bound.d.ts +2 -1
- package/lib/cloudflare/bound.d.ts.map +1 -1
- package/lib/cloudflare/d1-database.d.ts.map +1 -1
- package/lib/cloudflare/d1-database.js +8 -2
- package/lib/cloudflare/d1-database.js.map +1 -1
- package/lib/cloudflare/hyperdrive.d.ts +8 -0
- package/lib/cloudflare/hyperdrive.d.ts.map +1 -1
- package/lib/cloudflare/hyperdrive.js +3 -1
- package/lib/cloudflare/hyperdrive.js.map +1 -1
- package/lib/cloudflare/index.d.ts +1 -0
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +1 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.js +3 -0
- package/lib/cloudflare/miniflare/build-worker-options.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +3 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts +11 -0
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +20 -1
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +37 -0
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +1 -1
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.js +11 -0
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/cloudflare/zone.js +1 -1
- package/lib/cloudflare/zone.js.map +1 -1
- package/lib/scope.js +2 -2
- package/lib/scope.js.map +1 -1
- package/package.json +4 -4
- package/src/aws/control/client.ts +2 -1
- package/src/aws/control/resource.ts +67 -8
- package/src/aws/ec2/utils.ts +5 -3
- package/src/aws/utils.ts +20 -2
- package/src/cloudflare/artifacts.ts +69 -0
- package/src/cloudflare/bindings.ts +17 -2
- package/src/cloudflare/bound.ts +68 -65
- package/src/cloudflare/d1-database.ts +12 -2
- package/src/cloudflare/hyperdrive.ts +13 -1
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/miniflare/build-worker-options.ts +5 -0
- package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +3 -1
- package/src/cloudflare/worker-metadata.ts +33 -1
- package/src/cloudflare/worker.ts +41 -1
- package/src/cloudflare/wrangler.json.ts +19 -0
- package/src/cloudflare/zone.ts +1 -1
- package/src/scope.ts +2 -2
- package/workers/cloudflare-state-store.js +57 -57
- package/workers/tunnel-proxy.js +1 -1
package/src/aws/ec2/utils.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { logger } from "../../util/logger.ts";
|
|
|
6
6
|
import { flattenParams } from "../../util/params.ts";
|
|
7
7
|
import type { AwsClientProps } from "../client-props.ts";
|
|
8
8
|
import { resolveAwsCredentials } from "../credentials.ts";
|
|
9
|
-
import { getRegion } from "../utils.ts";
|
|
9
|
+
import { awsEndpoint, getRegion } from "../utils.ts";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Shared EC2 utilities for all EC2 resources
|
|
@@ -100,8 +100,10 @@ export async function callEC2Api<T>(
|
|
|
100
100
|
// Try the API call, and retry once with fresh credentials on auth failure
|
|
101
101
|
for (let attempt = 1; attempt <= 2; attempt++) {
|
|
102
102
|
try {
|
|
103
|
-
// Use the client's region instead of the global region
|
|
104
|
-
|
|
103
|
+
// Use the client's region instead of the global region.
|
|
104
|
+
// Honour AWS_ENDPOINT_URL / AWS_ENDPOINT_URL_EC2 for emulators
|
|
105
|
+
// (LocalStack, moto, etc.) — matches AWS SDK v3 behaviour.
|
|
106
|
+
const url = `${awsEndpoint("ec2", client.region ?? "us-east-1")}/`;
|
|
105
107
|
|
|
106
108
|
const body = new URLSearchParams({
|
|
107
109
|
Action: action,
|
package/src/aws/utils.ts
CHANGED
|
@@ -14,13 +14,29 @@ export const getRegion: Provider<string> = loadConfig({
|
|
|
14
14
|
default: "us-east-1",
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the endpoint URL for an aws4fetch service request, honouring the
|
|
19
|
+
* same `AWS_ENDPOINT_URL_<SERVICE>` / `AWS_ENDPOINT_URL` env vars as the AWS
|
|
20
|
+
* SDK / CLI so aws4fetch-based resources can be pointed at LocalStack, moto,
|
|
21
|
+
* or any other emulator.
|
|
22
|
+
*/
|
|
23
|
+
export function awsEndpoint(service: string, region: string): string {
|
|
24
|
+
return (
|
|
25
|
+
process.env[
|
|
26
|
+
`AWS_ENDPOINT_URL_${service.toUpperCase().replace(/-/g, "_")}`
|
|
27
|
+
] ??
|
|
28
|
+
process.env.AWS_ENDPOINT_URL ??
|
|
29
|
+
`https://${service}.${region}.amazonaws.com`
|
|
30
|
+
).replace(/\/+$/, "");
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
/**
|
|
18
34
|
* AWS Service Configuration
|
|
19
35
|
*/
|
|
20
36
|
export interface AwsServiceConfig {
|
|
21
37
|
service: string;
|
|
22
38
|
version: string;
|
|
23
|
-
endpoint
|
|
39
|
+
endpoint?: (region: string) => string;
|
|
24
40
|
}
|
|
25
41
|
|
|
26
42
|
/**
|
|
@@ -63,7 +79,9 @@ export function getAwsApiCaller<T = any>(
|
|
|
63
79
|
for (let attempt = 1; attempt <= 2; attempt++) {
|
|
64
80
|
try {
|
|
65
81
|
const region = await getRegion();
|
|
66
|
-
const url = config.endpoint
|
|
82
|
+
const url = config.endpoint
|
|
83
|
+
? config.endpoint(region)
|
|
84
|
+
: `${awsEndpoint(config.service, region)}/`;
|
|
67
85
|
|
|
68
86
|
const body = new URLSearchParams({
|
|
69
87
|
Action: action,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Properties for creating an Artifacts binding.
|
|
3
|
+
*
|
|
4
|
+
* Artifacts namespaces are created implicitly by Cloudflare when the first
|
|
5
|
+
* repository is created in the namespace, so this binding does not provision
|
|
6
|
+
* or delete a namespace resource.
|
|
7
|
+
*/
|
|
8
|
+
export interface ArtifactsProps {
|
|
9
|
+
/**
|
|
10
|
+
* Artifacts namespace name.
|
|
11
|
+
*/
|
|
12
|
+
namespace: string;
|
|
13
|
+
|
|
14
|
+
dev?: {
|
|
15
|
+
/**
|
|
16
|
+
* Whether to run the Artifacts binding remotely in local development.
|
|
17
|
+
*
|
|
18
|
+
* Artifacts do not have a local emulator, so generated Wrangler config
|
|
19
|
+
* defaults this binding to remote mode.
|
|
20
|
+
*
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
remote?: boolean;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Cloudflare Artifacts binding.
|
|
29
|
+
*
|
|
30
|
+
* Artifacts namespaces are implicit containers for repositories. Use this
|
|
31
|
+
* helper to bind a Worker to a namespace; repository lifecycle should be
|
|
32
|
+
* managed through the Artifacts runtime API, REST API, or Git endpoint.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { Artifacts, Worker } from "alchemy/cloudflare";
|
|
37
|
+
*
|
|
38
|
+
* await Worker("site-editor", {
|
|
39
|
+
* entrypoint: "./src/worker.ts",
|
|
40
|
+
* bindings: {
|
|
41
|
+
* SITE_ARTIFACTS: Artifacts({ namespace: "my-sites" }),
|
|
42
|
+
* },
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @see https://developers.cloudflare.com/artifacts/
|
|
47
|
+
*/
|
|
48
|
+
export interface Artifacts {
|
|
49
|
+
type: "artifacts";
|
|
50
|
+
namespace: string;
|
|
51
|
+
dev?: {
|
|
52
|
+
remote?: boolean;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function Artifacts(props: string | ArtifactsProps): Artifacts {
|
|
57
|
+
if (typeof props === "string") {
|
|
58
|
+
return {
|
|
59
|
+
type: "artifacts",
|
|
60
|
+
namespace: props,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
type: "artifacts",
|
|
66
|
+
namespace: props.namespace,
|
|
67
|
+
dev: props.dev,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -8,6 +8,7 @@ import type { Ai } from "./ai.ts";
|
|
|
8
8
|
import type { AiSearchNamespace } from "./ai-search-namespace.ts";
|
|
9
9
|
import type { AiSearch } from "./ai-search.ts";
|
|
10
10
|
import type { AnalyticsEngineDataset } from "./analytics-engine.ts";
|
|
11
|
+
import type { Artifacts } from "./artifacts.ts";
|
|
11
12
|
import type { Assets } from "./assets.ts";
|
|
12
13
|
import type { Bound } from "./bound.ts";
|
|
13
14
|
import type { BrowserRendering } from "./browser-rendering.ts";
|
|
@@ -54,6 +55,7 @@ export type Binding =
|
|
|
54
55
|
| AiSearch
|
|
55
56
|
| AiSearchNamespace
|
|
56
57
|
| Assets
|
|
58
|
+
| Artifacts
|
|
57
59
|
| Container
|
|
58
60
|
| CloudflareSecret
|
|
59
61
|
| CloudflareSecretRef
|
|
@@ -127,6 +129,7 @@ export type WorkerBindingSpec =
|
|
|
127
129
|
| WorkerBindingAiSearch
|
|
128
130
|
| WorkerBindingAiSearchNamespace
|
|
129
131
|
| WorkerBindingAnalyticsEngine
|
|
132
|
+
| WorkerBindingArtifacts
|
|
130
133
|
| WorkerBindingAssets
|
|
131
134
|
| WorkerBindingBrowserRendering
|
|
132
135
|
| WorkerBindingD1
|
|
@@ -206,6 +209,18 @@ export interface WorkerBindingAnalyticsEngine {
|
|
|
206
209
|
dataset: string;
|
|
207
210
|
}
|
|
208
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Artifacts binding type
|
|
214
|
+
*/
|
|
215
|
+
export interface WorkerBindingArtifacts {
|
|
216
|
+
/** The name of the binding */
|
|
217
|
+
name: string;
|
|
218
|
+
/** Type identifier for Artifacts binding */
|
|
219
|
+
type: "artifacts";
|
|
220
|
+
/** Artifacts namespace name */
|
|
221
|
+
namespace: string;
|
|
222
|
+
}
|
|
223
|
+
|
|
209
224
|
/**
|
|
210
225
|
* Assets binding type
|
|
211
226
|
*/
|
|
@@ -295,8 +310,8 @@ export interface WorkerBindingJson {
|
|
|
295
310
|
name: string;
|
|
296
311
|
/** Type identifier for JSON binding */
|
|
297
312
|
type: "json";
|
|
298
|
-
/** JSON value */
|
|
299
|
-
json:
|
|
313
|
+
/** JSON value, sent raw (not stringified) so the runtime injects native types */
|
|
314
|
+
json: unknown;
|
|
300
315
|
}
|
|
301
316
|
|
|
302
317
|
/**
|
package/src/cloudflare/bound.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { Ai as _Ai } from "./ai.ts";
|
|
|
5
5
|
import type { AiSearchNamespace as _AiSearchNamespace } from "./ai-search-namespace.ts";
|
|
6
6
|
import type { AiSearch as _AiSearch } from "./ai-search.ts";
|
|
7
7
|
import type { AnalyticsEngineDataset as _AnalyticsEngineDataset } from "./analytics-engine.ts";
|
|
8
|
+
import type { Artifacts as _Artifacts } from "./artifacts.ts";
|
|
8
9
|
import type { Assets } from "./assets.ts";
|
|
9
10
|
import type { Binding, Json, Self } from "./bindings.ts";
|
|
10
11
|
import type { BrowserRendering } from "./browser-rendering.ts";
|
|
@@ -61,69 +62,71 @@ export type Bound<T extends Binding> = T extends _AiSearch
|
|
|
61
62
|
? BoundWorker<RPC>
|
|
62
63
|
: T extends _Worker<any, infer RPC> | WorkerRef<infer RPC>
|
|
63
64
|
? BoundWorker<RPC>
|
|
64
|
-
: T extends
|
|
65
|
-
?
|
|
66
|
-
: T extends
|
|
67
|
-
?
|
|
68
|
-
: T extends
|
|
69
|
-
?
|
|
70
|
-
: T extends
|
|
71
|
-
?
|
|
72
|
-
: T extends
|
|
73
|
-
?
|
|
74
|
-
: T extends
|
|
75
|
-
?
|
|
76
|
-
: T extends
|
|
77
|
-
?
|
|
78
|
-
: T extends
|
|
79
|
-
?
|
|
80
|
-
: T extends
|
|
81
|
-
?
|
|
82
|
-
: T extends
|
|
83
|
-
?
|
|
84
|
-
: T extends
|
|
85
|
-
?
|
|
86
|
-
: T extends
|
|
87
|
-
?
|
|
88
|
-
: T extends
|
|
89
|
-
?
|
|
90
|
-
: T extends
|
|
91
|
-
?
|
|
92
|
-
: T extends
|
|
93
|
-
?
|
|
94
|
-
: T extends
|
|
95
|
-
?
|
|
96
|
-
: T extends
|
|
97
|
-
?
|
|
98
|
-
: T extends
|
|
99
|
-
?
|
|
100
|
-
: T extends
|
|
101
|
-
?
|
|
102
|
-
: T extends
|
|
103
|
-
?
|
|
104
|
-
: T extends
|
|
105
|
-
?
|
|
106
|
-
: T extends
|
|
107
|
-
?
|
|
108
|
-
: T extends
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
?
|
|
114
|
-
: T extends
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
: T extends _Container<
|
|
119
|
-
infer Obj
|
|
65
|
+
: T extends _Artifacts
|
|
66
|
+
? Artifacts
|
|
67
|
+
: T extends { type: "service" }
|
|
68
|
+
? Service
|
|
69
|
+
: T extends _R2Bucket
|
|
70
|
+
? R2Bucket
|
|
71
|
+
: T extends _Hyperdrive | HyperdriveRef
|
|
72
|
+
? Hyperdrive
|
|
73
|
+
: T extends Secret
|
|
74
|
+
? string
|
|
75
|
+
: T extends CloudflareSecret | CloudflareSecretRef
|
|
76
|
+
? SecretsStoreSecret
|
|
77
|
+
: T extends _EmailSender
|
|
78
|
+
? SendEmail
|
|
79
|
+
: T extends SecretKey
|
|
80
|
+
? CryptoKey
|
|
81
|
+
: T extends Assets
|
|
82
|
+
? Service
|
|
83
|
+
: T extends _Workflow<infer P>
|
|
84
|
+
? Workflow<P>
|
|
85
|
+
: T extends _D1Database
|
|
86
|
+
? D1Database
|
|
87
|
+
: T extends DispatchNamespace
|
|
88
|
+
? DispatchNamespace
|
|
89
|
+
: T extends _WorkerLoader
|
|
90
|
+
? WorkerLoader
|
|
91
|
+
: T extends _VectorizeIndex
|
|
92
|
+
? VectorizeIndex
|
|
93
|
+
: T extends _Queue<infer Body>
|
|
94
|
+
? Queue<Body>
|
|
95
|
+
: T extends _AnalyticsEngineDataset
|
|
96
|
+
? AnalyticsEngineDataset
|
|
97
|
+
: T extends _Pipeline<infer R>
|
|
98
|
+
? Pipeline<R>
|
|
99
|
+
: T extends _RateLimit
|
|
100
|
+
? RateLimit
|
|
101
|
+
: T extends string
|
|
102
|
+
? T
|
|
103
|
+
: T extends BrowserRendering
|
|
104
|
+
? BrowserRun
|
|
105
|
+
: T extends _Ai<infer M>
|
|
106
|
+
? Ai<M>
|
|
107
|
+
: T extends _Images
|
|
108
|
+
? ImagesBinding
|
|
109
|
+
: T extends _VersionMetadata
|
|
110
|
+
? WorkerVersionMetadata
|
|
111
|
+
: T extends
|
|
112
|
+
| _Worker.DevDomain
|
|
113
|
+
| _Worker.DevUrl
|
|
114
|
+
? string
|
|
115
|
+
: T extends Self
|
|
116
|
+
? Service
|
|
117
|
+
: T extends Json<
|
|
118
|
+
infer T
|
|
120
119
|
>
|
|
121
|
-
?
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
? T
|
|
121
|
+
: T extends _Container<
|
|
122
|
+
infer Obj
|
|
123
|
+
>
|
|
124
|
+
? DurableObjectNamespace<
|
|
125
|
+
Obj &
|
|
126
|
+
Rpc.DurableObjectBranded
|
|
127
|
+
>
|
|
128
|
+
: T extends _VpcService
|
|
129
|
+
? Fetcher
|
|
130
|
+
: T extends undefined
|
|
131
|
+
? undefined
|
|
132
|
+
: Service;
|
|
@@ -307,11 +307,21 @@ const _D1Database = Resource(
|
|
|
307
307
|
|
|
308
308
|
if (local) {
|
|
309
309
|
if (props.migrationsFiles?.length || props.importFiles?.length) {
|
|
310
|
+
const localMigrationsFiles = props.migrationsDir
|
|
311
|
+
? await listSqlFiles(props.migrationsDir)
|
|
312
|
+
: [];
|
|
313
|
+
const localImportFiles = props.importFiles?.length
|
|
314
|
+
? await Promise.all(
|
|
315
|
+
props.importFiles.map((file) =>
|
|
316
|
+
readSqlFile(this.scope.rootDir, file.id),
|
|
317
|
+
),
|
|
318
|
+
)
|
|
319
|
+
: [];
|
|
310
320
|
await applyLocalD1Migrations({
|
|
311
321
|
databaseId: dev.id,
|
|
312
322
|
migrationsTable: props.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE,
|
|
313
|
-
migrations:
|
|
314
|
-
imports:
|
|
323
|
+
migrations: localMigrationsFiles,
|
|
324
|
+
imports: localImportFiles,
|
|
315
325
|
rootDir: this.scope.rootDir,
|
|
316
326
|
});
|
|
317
327
|
}
|
|
@@ -47,6 +47,11 @@ export interface HyperdrivePublicOrigin {
|
|
|
47
47
|
*/
|
|
48
48
|
scheme?: "postgres" | "mysql";
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Connection query string, without the leading "?"
|
|
52
|
+
*/
|
|
53
|
+
query?: string;
|
|
54
|
+
|
|
50
55
|
/**
|
|
51
56
|
* Database user
|
|
52
57
|
*/
|
|
@@ -90,6 +95,11 @@ export interface HyperdriveOriginWithAccess {
|
|
|
90
95
|
*/
|
|
91
96
|
scheme?: "postgres" | "mysql";
|
|
92
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Connection query string, without the leading "?"
|
|
100
|
+
*/
|
|
101
|
+
query?: string;
|
|
102
|
+
|
|
93
103
|
/**
|
|
94
104
|
* Database user
|
|
95
105
|
*/
|
|
@@ -610,6 +620,7 @@ export const normalizeHyperdriveOrigin = (
|
|
|
610
620
|
host: url.hostname,
|
|
611
621
|
port: normalizePort(scheme, url.port),
|
|
612
622
|
database: url.pathname.slice(1),
|
|
623
|
+
query: url.search?.slice(1) ?? "",
|
|
613
624
|
};
|
|
614
625
|
}
|
|
615
626
|
const scheme = normalizeScheme(origin.scheme);
|
|
@@ -623,6 +634,7 @@ export const normalizeHyperdriveOrigin = (
|
|
|
623
634
|
}),
|
|
624
635
|
scheme,
|
|
625
636
|
port: normalizePort(scheme, origin.port),
|
|
637
|
+
query: origin.query ?? "",
|
|
626
638
|
};
|
|
627
639
|
};
|
|
628
640
|
|
|
@@ -660,6 +672,6 @@ const toConnectionString = (
|
|
|
660
672
|
"password" in origin ? origin.password : origin.access_client_secret,
|
|
661
673
|
);
|
|
662
674
|
return new Secret(
|
|
663
|
-
`${origin.scheme}://${origin.user}:${password}@${origin.host}:${origin.port}/${origin.database}`,
|
|
675
|
+
`${origin.scheme}://${origin.user}:${password}@${origin.host}:${origin.port}/${origin.database}${origin.query ? `?${origin.query}` : ""}`,
|
|
664
676
|
);
|
|
665
677
|
};
|
package/src/cloudflare/index.ts
CHANGED
|
@@ -20,6 +20,7 @@ export * from "./api-gateway-operation.ts";
|
|
|
20
20
|
export * from "./api-schema.ts";
|
|
21
21
|
export * from "./api-shield.ts";
|
|
22
22
|
export * from "./api.ts";
|
|
23
|
+
export * from "./artifacts.ts";
|
|
23
24
|
export * from "./assets.ts";
|
|
24
25
|
export * from "./astro/astro.ts";
|
|
25
26
|
export * from "./bindings.ts";
|
|
@@ -167,6 +167,11 @@ export const buildWorkerOptions = async (
|
|
|
167
167
|
};
|
|
168
168
|
break;
|
|
169
169
|
}
|
|
170
|
+
case "artifacts": {
|
|
171
|
+
throw new Error(
|
|
172
|
+
"Artifacts bindings are not supported in Alchemy local dev yet. Deploy the Worker or use generated Wrangler config with remote Artifacts bindings.",
|
|
173
|
+
);
|
|
174
|
+
}
|
|
170
175
|
case "assets": {
|
|
171
176
|
options.assets = {
|
|
172
177
|
binding: key,
|
|
@@ -249,7 +249,9 @@ const writeMiniflareResponseToNode = (
|
|
|
249
249
|
});
|
|
250
250
|
|
|
251
251
|
if (res.body) {
|
|
252
|
-
Readable.fromWeb(res.body)
|
|
252
|
+
const body = Readable.fromWeb(res.body);
|
|
253
|
+
body.on("error", () => out.destroy());
|
|
254
|
+
body.pipe(out, { end: true });
|
|
253
255
|
} else {
|
|
254
256
|
out.end();
|
|
255
257
|
}
|
|
@@ -206,6 +206,17 @@ export interface WorkerMetadata {
|
|
|
206
206
|
};
|
|
207
207
|
};
|
|
208
208
|
logpush?: boolean;
|
|
209
|
+
/**
|
|
210
|
+
* Workers Cache configuration.
|
|
211
|
+
*
|
|
212
|
+
* The wire shape matches what wrangler (>= 4.69) uploads.
|
|
213
|
+
*
|
|
214
|
+
* @see https://developers.cloudflare.com/workers/cache/configuration/
|
|
215
|
+
*/
|
|
216
|
+
cache_options?: {
|
|
217
|
+
enabled: boolean;
|
|
218
|
+
cross_version_cache?: boolean;
|
|
219
|
+
};
|
|
209
220
|
migrations?: SingleStepMigration;
|
|
210
221
|
main_module?: string;
|
|
211
222
|
body_part?: string;
|
|
@@ -355,6 +366,19 @@ export async function prepareWorkerMetadata(
|
|
|
355
366
|
enabled: observability?.enabled !== false,
|
|
356
367
|
},
|
|
357
368
|
logpush: props.logpush ?? false,
|
|
369
|
+
cache_options:
|
|
370
|
+
props.cache != null
|
|
371
|
+
? {
|
|
372
|
+
enabled:
|
|
373
|
+
typeof props.cache === "boolean"
|
|
374
|
+
? props.cache
|
|
375
|
+
: (props.cache.enabled ?? true),
|
|
376
|
+
cross_version_cache:
|
|
377
|
+
typeof props.cache === "object"
|
|
378
|
+
? props.cache.crossVersionCache
|
|
379
|
+
: undefined,
|
|
380
|
+
}
|
|
381
|
+
: undefined,
|
|
358
382
|
// TODO(sam): base64 encode instead? 0 collision risk vs readability.
|
|
359
383
|
tags: [
|
|
360
384
|
// encode a mapping table of Durable Object stable ID -> binding name
|
|
@@ -516,6 +540,12 @@ export async function prepareWorkerMetadata(
|
|
|
516
540
|
jurisdiction:
|
|
517
541
|
binding.jurisdiction === "default" ? undefined : binding.jurisdiction,
|
|
518
542
|
});
|
|
543
|
+
} else if (binding.type === "artifacts") {
|
|
544
|
+
meta.bindings.push({
|
|
545
|
+
type: "artifacts",
|
|
546
|
+
name: bindingName,
|
|
547
|
+
namespace: binding.namespace,
|
|
548
|
+
});
|
|
519
549
|
} else if (binding.type === "send_email") {
|
|
520
550
|
meta.bindings.push({
|
|
521
551
|
type: "send_email",
|
|
@@ -597,7 +627,9 @@ export async function prepareWorkerMetadata(
|
|
|
597
627
|
meta.bindings.push({
|
|
598
628
|
type: "json",
|
|
599
629
|
name: bindingName,
|
|
600
|
-
|
|
630
|
+
// send the raw value (like wrangler does) so the runtime injects the
|
|
631
|
+
// native type; stringifying here would inject a string instead
|
|
632
|
+
json: binding.json,
|
|
601
633
|
});
|
|
602
634
|
} else if (binding.type === "analytics_engine") {
|
|
603
635
|
meta.bindings.push({
|
package/src/cloudflare/worker.ts
CHANGED
|
@@ -249,6 +249,21 @@ export interface BaseWorkerProps<
|
|
|
249
249
|
*/
|
|
250
250
|
assets?: AssetsConfig;
|
|
251
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Enable Workers Cache — a Worker-owned edge cache in front of this Worker.
|
|
254
|
+
*
|
|
255
|
+
* When enabled, Cloudflare checks the cache before invoking the Worker and
|
|
256
|
+
* serves matching responses directly from the edge. Caching is controlled
|
|
257
|
+
* with standard response headers (`Cache-Control`, `Cache-Tag`, `Vary`) and
|
|
258
|
+
* entries can be purged at runtime with `ctx.cache.purge()`.
|
|
259
|
+
*
|
|
260
|
+
* Pass `true` as shorthand for `{ enabled: true }`.
|
|
261
|
+
*
|
|
262
|
+
* @see https://developers.cloudflare.com/workers/cache/
|
|
263
|
+
* @default undefined - Workers Cache is disabled
|
|
264
|
+
*/
|
|
265
|
+
cache?: boolean | WorkerCacheOptions;
|
|
266
|
+
|
|
252
267
|
/**
|
|
253
268
|
* Cron expressions for the trigger.
|
|
254
269
|
*
|
|
@@ -431,6 +446,31 @@ export interface BaseWorkerProps<
|
|
|
431
446
|
tailConsumers?: Array<Worker | { service: string }>;
|
|
432
447
|
}
|
|
433
448
|
|
|
449
|
+
/**
|
|
450
|
+
* Configuration for Workers Cache — the edge cache that sits in front of a
|
|
451
|
+
* Worker's `fetch()` invocations.
|
|
452
|
+
*
|
|
453
|
+
* @see https://developers.cloudflare.com/workers/cache/configuration/
|
|
454
|
+
*/
|
|
455
|
+
export interface WorkerCacheOptions {
|
|
456
|
+
/**
|
|
457
|
+
* If Workers Cache is enabled for this Worker
|
|
458
|
+
*
|
|
459
|
+
* @default true
|
|
460
|
+
*/
|
|
461
|
+
enabled?: boolean;
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Whether cached responses may be reused across Worker versions.
|
|
465
|
+
*
|
|
466
|
+
* By default the cache is scoped to a single Worker version, so every
|
|
467
|
+
* deployment starts cold. Enable this when responses are version-agnostic.
|
|
468
|
+
*
|
|
469
|
+
* @default false
|
|
470
|
+
*/
|
|
471
|
+
crossVersionCache?: boolean;
|
|
472
|
+
}
|
|
473
|
+
|
|
434
474
|
export interface WorkerObservability {
|
|
435
475
|
/**
|
|
436
476
|
* If observability is enabled for this Worker
|
|
@@ -1601,7 +1641,7 @@ async function provisionResources<B extends Bindings>(
|
|
|
1601
1641
|
// In local dev mode, queue.id is "" (no Cloudflare API call).
|
|
1602
1642
|
// Use queue.dev.id (resource ID, e.g. "email-queue") to avoid
|
|
1603
1643
|
// all consumers colliding on the same "-consumer" resource ID.
|
|
1604
|
-
// See: https://github.com/alchemy-run/alchemy/issues/1363
|
|
1644
|
+
// See: https://github.com/alchemy-run/alchemy-async/issues/1363
|
|
1605
1645
|
const queueConsumerId = options.local
|
|
1606
1646
|
? eventSource.queue.dev?.id || eventSource.queue.id
|
|
1607
1647
|
: eventSource.queue.id;
|
|
@@ -264,6 +264,11 @@ async function processBindings(
|
|
|
264
264
|
const kvNamespaces: WranglerJsonConfig["kv_namespaces"] = [];
|
|
265
265
|
const durableObjects: WranglerJsonConfig["durable_objects"]["bindings"] = [];
|
|
266
266
|
const r2Buckets: WranglerJsonConfig["r2_buckets"] = [];
|
|
267
|
+
const artifacts: {
|
|
268
|
+
binding: string;
|
|
269
|
+
namespace: string;
|
|
270
|
+
remote?: boolean;
|
|
271
|
+
}[] = [];
|
|
267
272
|
const services: WranglerJsonConfig["services"] = [];
|
|
268
273
|
const sendEmailBindings: WranglerJsonConfig["send_email"] = [];
|
|
269
274
|
const secrets: string[] = [];
|
|
@@ -422,6 +427,12 @@ async function processBindings(
|
|
|
422
427
|
allowed_sender_addresses: binding.allowedSenderAddresses,
|
|
423
428
|
...(binding.dev?.remote ? { remote: true } : {}),
|
|
424
429
|
});
|
|
430
|
+
} else if (binding.type === "artifacts") {
|
|
431
|
+
artifacts.push({
|
|
432
|
+
binding: bindingName,
|
|
433
|
+
namespace: binding.namespace,
|
|
434
|
+
remote: binding.dev?.remote ?? true,
|
|
435
|
+
});
|
|
425
436
|
} else if (binding.type === "secret") {
|
|
426
437
|
// Secret binding
|
|
427
438
|
secrets.push(bindingName);
|
|
@@ -598,6 +609,14 @@ async function processBindings(
|
|
|
598
609
|
spec.r2_buckets = r2Buckets;
|
|
599
610
|
}
|
|
600
611
|
|
|
612
|
+
if (artifacts.length > 0) {
|
|
613
|
+
(
|
|
614
|
+
spec as WranglerJsonSpec & {
|
|
615
|
+
artifacts?: typeof artifacts;
|
|
616
|
+
}
|
|
617
|
+
).artifacts = artifacts;
|
|
618
|
+
}
|
|
619
|
+
|
|
601
620
|
if (services.length > 0) {
|
|
602
621
|
spec.services = services;
|
|
603
622
|
}
|
package/src/cloudflare/zone.ts
CHANGED
|
@@ -415,7 +415,7 @@ export const Zone = Resource(
|
|
|
415
415
|
|
|
416
416
|
// Add a small delay to ensure settings are propagated
|
|
417
417
|
// TODO(michael): do we need this?
|
|
418
|
-
// https://github.com/alchemy-run/alchemy/issues/681
|
|
418
|
+
// https://github.com/alchemy-run/alchemy-async/issues/681
|
|
419
419
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
420
420
|
|
|
421
421
|
// Update Bot Management configuration if provided
|
package/src/scope.ts
CHANGED
|
@@ -324,7 +324,7 @@ export class Scope {
|
|
|
324
324
|
destroyStrategy ?? this.parent?.destroyStrategy ?? "sequential";
|
|
325
325
|
if (this.local) {
|
|
326
326
|
this.logger.warnOnce(
|
|
327
|
-
"Development mode is in beta. Please report any issues to https://github.com/alchemy-run/alchemy/issues.",
|
|
327
|
+
"Development mode is in beta. Please report any issues to https://github.com/alchemy-run/alchemy-async/issues.",
|
|
328
328
|
);
|
|
329
329
|
}
|
|
330
330
|
|
|
@@ -652,7 +652,7 @@ export class Scope {
|
|
|
652
652
|
throw e;
|
|
653
653
|
})) ?? [];
|
|
654
654
|
|
|
655
|
-
//todo(michael): remove once we deprecate doss; see: https://github.com/alchemy-run/alchemy/issues/585
|
|
655
|
+
//todo(michael): remove once we deprecate doss; see: https://github.com/alchemy-run/alchemy-async/issues/585
|
|
656
656
|
let hasCorruptedResources = false;
|
|
657
657
|
if (pendingDeletions) {
|
|
658
658
|
for (const { resource, oldProps } of pendingDeletions) {
|