alchemy 0.77.0 → 0.77.1
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/alchemy.js +1 -1
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js +8 -5
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/d1-database.d.ts +13 -3
- package/lib/cloudflare/d1-database.d.ts.map +1 -1
- package/lib/cloudflare/d1-database.js +31 -15
- package/lib/cloudflare/d1-database.js.map +1 -1
- package/lib/docker/api.d.ts +4 -0
- package/lib/docker/api.d.ts.map +1 -1
- package/lib/docker/api.js +3 -0
- package/lib/docker/api.js.map +1 -1
- package/lib/docker/image.d.ts +50 -12
- package/lib/docker/image.d.ts.map +1 -1
- package/lib/docker/image.js +86 -58
- package/lib/docker/image.js.map +1 -1
- package/lib/docker/remote-image.d.ts +1 -0
- package/lib/docker/remote-image.d.ts.map +1 -1
- package/lib/docker/remote-image.js +2 -0
- package/lib/docker/remote-image.js.map +1 -1
- package/package.json +1 -1
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/container.ts +10 -7
- package/src/cloudflare/d1-database.ts +44 -6
- package/src/docker/api.ts +7 -0
- package/src/docker/image.ts +164 -89
- package/src/docker/remote-image.ts +3 -0
- package/workers/cloudflare-state-store.js +57 -57
- package/workers/tunnel-proxy.js +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/docker/image.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/docker/image.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE9B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,CACA;IACE;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC;CACd,GACD;IACE;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,EAAE,kBAAkB,CAAC;IAE1B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,CACJ,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,OAAO,CAAC;IACd;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,KAAK,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,KAAK,yFAGR,OAAO,CAAC,KAAK,CAAC,MAChB,MAAM,SACH,UAAU,KAChB,OAAO,CAAC,KAAK,CAAC,CA8KlB,CAAC"}
|
package/lib/docker/image.js
CHANGED
|
@@ -28,11 +28,26 @@ export const Image = Resource("docker::Image", async function (id, props) {
|
|
|
28
28
|
// This is intentional as other resources might depend on the same image
|
|
29
29
|
return this.destroy();
|
|
30
30
|
}
|
|
31
|
+
const tag = props.tag || "latest";
|
|
32
|
+
const name = props.name ||
|
|
33
|
+
(typeof props.image === "string"
|
|
34
|
+
? props.image
|
|
35
|
+
: props.image?.name)?.split(":")[0] ||
|
|
36
|
+
id;
|
|
37
|
+
const imageRef = `${name}:${tag}`;
|
|
38
|
+
let imageId;
|
|
39
|
+
if (props.image) {
|
|
40
|
+
const image = typeof props.image === "string" ? props.image : props.image.imageRef;
|
|
41
|
+
const kind = typeof props.image === "object" && props.image.kind === "Image"
|
|
42
|
+
? "local"
|
|
43
|
+
: "remote";
|
|
44
|
+
if (kind === "remote") {
|
|
45
|
+
await api.pullImage(image);
|
|
46
|
+
}
|
|
47
|
+
await api.tagImage(image, imageRef);
|
|
48
|
+
// TODO: Extract image ID from pull output if available
|
|
49
|
+
}
|
|
31
50
|
else {
|
|
32
|
-
// Normalize properties
|
|
33
|
-
const tag = props.tag || "latest";
|
|
34
|
-
const name = props.name || id;
|
|
35
|
-
const imageRef = `${name}:${tag}`;
|
|
36
51
|
let context;
|
|
37
52
|
let dockerfile;
|
|
38
53
|
if (props.build?.dockerfile && props.build?.context) {
|
|
@@ -56,7 +71,7 @@ export const Image = Resource("docker::Image", async function (id, props) {
|
|
|
56
71
|
// Prepare build options
|
|
57
72
|
const buildOptions = props.build?.args || {};
|
|
58
73
|
// Add platform if specified
|
|
59
|
-
|
|
74
|
+
const buildArgs = ["build", "-t", imageRef];
|
|
60
75
|
if (props.build?.platform) {
|
|
61
76
|
buildArgs.push("--platform", props.build.platform);
|
|
62
77
|
}
|
|
@@ -70,10 +85,20 @@ export const Image = Resource("docker::Image", async function (id, props) {
|
|
|
70
85
|
buildArgs.push("--cache-from", cacheSource);
|
|
71
86
|
}
|
|
72
87
|
}
|
|
88
|
+
// Add cache destinations if specified
|
|
89
|
+
if (props.build?.cacheTo && props.build.cacheTo.length > 0) {
|
|
90
|
+
for (const cacheTarget of props.build.cacheTo) {
|
|
91
|
+
buildArgs.push("--cache-to", cacheTarget);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
73
94
|
// Add build arguments
|
|
74
95
|
for (const [key, value] of Object.entries(buildOptions)) {
|
|
75
96
|
buildArgs.push("--build-arg", `${key}=${value}`);
|
|
76
97
|
}
|
|
98
|
+
// Add build options if specified
|
|
99
|
+
if (props.build?.options && props.build.options.length > 0) {
|
|
100
|
+
buildArgs.push(...props.build.options);
|
|
101
|
+
}
|
|
77
102
|
buildArgs.push("-f", dockerfile);
|
|
78
103
|
// Add context path
|
|
79
104
|
buildArgs.push(context);
|
|
@@ -81,62 +106,65 @@ export const Image = Resource("docker::Image", async function (id, props) {
|
|
|
81
106
|
const { stdout } = await api.exec(buildArgs);
|
|
82
107
|
// Extract image ID from build output if available
|
|
83
108
|
const imageIdMatch = /Successfully built ([a-f0-9]+)/.exec(stdout);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// Push the image
|
|
113
|
-
const { stdout: pushOut } = await api.exec(["push", targetImage]);
|
|
114
|
-
// Attempt to extract the repo digest from push output
|
|
115
|
-
const digestMatch = /digest:\s+([a-z0-9]+:[a-f0-9]{64})/.exec(pushOut);
|
|
116
|
-
if (digestMatch) {
|
|
117
|
-
const digestHash = digestMatch[1];
|
|
118
|
-
// Strip tag (anything after last :) to build image@digest reference
|
|
119
|
-
const [repoWithoutTag] = targetImage.split(":").length > 2
|
|
120
|
-
? [targetImage] // unlikely but safety
|
|
121
|
-
: [targetImage.substring(0, targetImage.lastIndexOf(":"))];
|
|
122
|
-
repoDigest = `${repoWithoutTag}@${digestHash}`;
|
|
123
|
-
}
|
|
124
|
-
// Update the final image reference to point at the pushed image
|
|
125
|
-
finalImageRef = targetImage;
|
|
109
|
+
imageId = imageIdMatch ? imageIdMatch[1] : undefined;
|
|
110
|
+
}
|
|
111
|
+
// Handle push if required
|
|
112
|
+
let repoDigest;
|
|
113
|
+
let finalImageRef = imageRef;
|
|
114
|
+
if (props.registry && !props.skipPush) {
|
|
115
|
+
const { server, username, password } = props.registry;
|
|
116
|
+
// Ensure the registry server does not have trailing slash
|
|
117
|
+
const registryHost = server.replace(/\/$/, "");
|
|
118
|
+
// Determine if the built image already includes a registry host (e.g. ghcr.io/user/repo)
|
|
119
|
+
const firstSegment = imageRef.split("/")[0];
|
|
120
|
+
const hasRegistryPrefix = firstSegment.includes(".");
|
|
121
|
+
// Compose the target image reference that will be pushed
|
|
122
|
+
const targetImage = hasRegistryPrefix
|
|
123
|
+
? imageRef // already fully-qualified
|
|
124
|
+
: `${registryHost}/${imageRef}`;
|
|
125
|
+
try {
|
|
126
|
+
// Create a temporary directory that will act as an isolated Docker config
|
|
127
|
+
// (credentials) directory. This prevents race-conditions when multiple
|
|
128
|
+
// concurrent tests perform `docker login` / `logout` by ensuring each
|
|
129
|
+
// Image operation has its own credential store.
|
|
130
|
+
const tempConfigDir = await fs.mkdtemp(path.join(os.tmpdir(), "docker-config-"));
|
|
131
|
+
const api = new DockerApi({ configDir: tempConfigDir });
|
|
132
|
+
// Authenticate to registry using the isolated config directory
|
|
133
|
+
await api.login(registryHost, username, password.unencrypted);
|
|
134
|
+
// Tag local image with fully qualified name if necessary
|
|
135
|
+
if (targetImage !== imageRef) {
|
|
136
|
+
await api.exec(["tag", imageRef, targetImage]);
|
|
126
137
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
138
|
+
// Push the image
|
|
139
|
+
const { stdout: pushOut } = await api.exec(["push", targetImage]);
|
|
140
|
+
// Attempt to extract the repo digest from push output
|
|
141
|
+
const digestMatch = /digest:\s+([a-z0-9]+:[a-f0-9]{64})/.exec(pushOut);
|
|
142
|
+
if (digestMatch) {
|
|
143
|
+
const digestHash = digestMatch[1];
|
|
144
|
+
// Strip tag (anything after last :) to build image@digest reference
|
|
145
|
+
const [repoWithoutTag] = targetImage.split(":").length > 2
|
|
146
|
+
? [targetImage] // unlikely but safety
|
|
147
|
+
: [targetImage.substring(0, targetImage.lastIndexOf(":"))];
|
|
148
|
+
repoDigest = `${repoWithoutTag}@${digestHash}`;
|
|
130
149
|
}
|
|
150
|
+
// Update the final image reference to point at the pushed image
|
|
151
|
+
finalImageRef = targetImage;
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
// Clean up credentials from the isolated config
|
|
155
|
+
await api.logout(registryHost);
|
|
131
156
|
}
|
|
132
|
-
return {
|
|
133
|
-
...props,
|
|
134
|
-
name,
|
|
135
|
-
imageRef: finalImageRef,
|
|
136
|
-
imageId,
|
|
137
|
-
repoDigest,
|
|
138
|
-
builtAt: Date.now(),
|
|
139
|
-
};
|
|
140
157
|
}
|
|
158
|
+
return {
|
|
159
|
+
kind: "Image",
|
|
160
|
+
...props,
|
|
161
|
+
tag,
|
|
162
|
+
name,
|
|
163
|
+
imageRef: finalImageRef,
|
|
164
|
+
imageId,
|
|
165
|
+
repoDigest,
|
|
166
|
+
builtAt: Date.now(),
|
|
167
|
+
build: props.build,
|
|
168
|
+
};
|
|
141
169
|
});
|
|
142
170
|
//# sourceMappingURL=image.js.map
|
package/lib/docker/image.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/docker/image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,OAAO,CAAC;AAEzB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/docker/image.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-image.d.ts","sourceRoot":"","sources":["../../src/docker/remote-image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACnD;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,yFAGd,OAAO,CAAC,WAAW,CAAC,OACrB,MAAM,SACJ,gBAAgB,KACtB,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"remote-image.d.ts","sourceRoot":"","sources":["../../src/docker/remote-image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACnD,IAAI,EAAE,aAAa,CAAC;IACpB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,yFAGd,OAAO,CAAC,WAAW,CAAC,OACrB,MAAM,SACJ,gBAAgB,KACtB,OAAO,CAAC,WAAW,CAAC,CAyBxB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-image.js","sourceRoot":"","sources":["../../src/docker/remote-image.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"remote-image.js","sourceRoot":"","sources":["../../src/docker/remote-image.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAsCrC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CACjC,qBAAqB,EACrB,KAAK,WAEH,GAAW,EACX,KAAuB;IAEvB,+BAA+B;IAC/B,MAAM,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC;IAE5B,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,4EAA4E;QAC5E,wEAAwE;QACxE,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;SAAM,CAAC;QACN,uBAAuB;QACvB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,QAAQ,CAAC;QAClC,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;QAExC,aAAa;QACb,MAAM,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAE9B,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,GAAG,KAAK;YACR,QAAQ;YACR,GAAG;YACH,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -218,10 +218,10 @@ export async function Container<T>(
|
|
|
218
218
|
const isDev = scope.local && !props.dev?.remote;
|
|
219
219
|
if (isDev) {
|
|
220
220
|
const image = await Image(id, {
|
|
221
|
+
...props,
|
|
221
222
|
name: `cloudflare-dev/${name}`, // prefix used by Miniflare
|
|
222
223
|
tag,
|
|
223
|
-
|
|
224
|
-
});
|
|
224
|
+
} as ImageProps);
|
|
225
225
|
|
|
226
226
|
return {
|
|
227
227
|
...output,
|
|
@@ -235,16 +235,19 @@ export async function Container<T>(
|
|
|
235
235
|
const image = await Image(id, {
|
|
236
236
|
name: `${api.accountId}/${name}`,
|
|
237
237
|
tag,
|
|
238
|
-
build:
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
build: props.build
|
|
239
|
+
? {
|
|
240
|
+
platform: props.build?.platform ?? "linux/amd64",
|
|
241
|
+
...props.build,
|
|
242
|
+
}
|
|
243
|
+
: undefined,
|
|
244
|
+
image: props.image,
|
|
242
245
|
registry: {
|
|
243
246
|
server: "registry.cloudflare.com",
|
|
244
247
|
username: credentials.username || credentials.user!,
|
|
245
248
|
password: secret(credentials.password),
|
|
246
249
|
},
|
|
247
|
-
});
|
|
250
|
+
} as ImageProps);
|
|
248
251
|
|
|
249
252
|
return {
|
|
250
253
|
...output,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type CloudflareApi,
|
|
9
9
|
type CloudflareApiOptions,
|
|
10
10
|
} from "./api.ts";
|
|
11
|
+
import { withJurisdiction } from "./bucket.ts";
|
|
11
12
|
import { cloneD1Database } from "./d1-clone.ts";
|
|
12
13
|
import { applyLocalD1Migrations } from "./d1-local-migrations.ts";
|
|
13
14
|
import { applyMigrations, listMigrationsFiles } from "./d1-migrations.ts";
|
|
@@ -15,6 +16,8 @@ import { deleteMiniflareBinding } from "./miniflare/delete.ts";
|
|
|
15
16
|
|
|
16
17
|
const DEFAULT_MIGRATIONS_TABLE = "d1_migrations";
|
|
17
18
|
|
|
19
|
+
export type D1DatabaseJurisdiction = "default" | "eu" | "fedramp";
|
|
20
|
+
|
|
18
21
|
type PrimaryLocationHint =
|
|
19
22
|
| "wnam"
|
|
20
23
|
| "enam"
|
|
@@ -115,6 +118,12 @@ export interface D1DatabaseProps extends CloudflareApiOptions {
|
|
|
115
118
|
*/
|
|
116
119
|
force?: boolean;
|
|
117
120
|
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Optional jurisdiction for the bucket
|
|
124
|
+
* Determines the regulatory jurisdiction the bucket data falls under
|
|
125
|
+
*/
|
|
126
|
+
jurisdiction?: D1DatabaseJurisdiction;
|
|
118
127
|
}
|
|
119
128
|
|
|
120
129
|
export function isD1Database(resource: any): resource is D1Database {
|
|
@@ -157,6 +166,11 @@ export type D1Database = Pick<
|
|
|
157
166
|
*/
|
|
158
167
|
remote: boolean;
|
|
159
168
|
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The jurisdiction of the database
|
|
172
|
+
*/
|
|
173
|
+
jurisdiction: D1DatabaseJurisdiction;
|
|
160
174
|
};
|
|
161
175
|
|
|
162
176
|
/**
|
|
@@ -260,10 +274,11 @@ const _D1Database = Resource(
|
|
|
260
274
|
async function (
|
|
261
275
|
this: Context<D1Database>,
|
|
262
276
|
id: string,
|
|
263
|
-
props: D1DatabaseProps
|
|
277
|
+
props: D1DatabaseProps,
|
|
264
278
|
): Promise<D1Database> {
|
|
265
279
|
const databaseName =
|
|
266
280
|
props.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
|
|
281
|
+
const jurisdiction = props.jurisdiction ?? "default";
|
|
267
282
|
|
|
268
283
|
if (this.phase === "update" && this.output?.name !== databaseName) {
|
|
269
284
|
this.replace();
|
|
@@ -294,6 +309,7 @@ const _D1Database = Resource(
|
|
|
294
309
|
migrationsDir: props.migrationsDir,
|
|
295
310
|
migrationsTable: props.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE,
|
|
296
311
|
dev,
|
|
312
|
+
jurisdiction,
|
|
297
313
|
};
|
|
298
314
|
}
|
|
299
315
|
|
|
@@ -304,7 +320,7 @@ const _D1Database = Resource(
|
|
|
304
320
|
await deleteMiniflareBinding(this.scope, "d1", this.output.dev.id);
|
|
305
321
|
}
|
|
306
322
|
if (props.delete !== false && this.output?.id) {
|
|
307
|
-
await deleteDatabase(api, this.output.id);
|
|
323
|
+
await deleteDatabase(api, this.output.id, props);
|
|
308
324
|
}
|
|
309
325
|
// Return void (a deleted database has no content)
|
|
310
326
|
return this.destroy();
|
|
@@ -328,7 +344,7 @@ const _D1Database = Resource(
|
|
|
328
344
|
|
|
329
345
|
// If clone property is provided, perform cloning after database creation
|
|
330
346
|
if (props.clone && dbData.result.uuid) {
|
|
331
|
-
await cloneDb(api, props.clone, dbData.result.uuid);
|
|
347
|
+
await cloneDb(api, props.clone, dbData.result.uuid, jurisdiction);
|
|
332
348
|
}
|
|
333
349
|
} catch (error) {
|
|
334
350
|
// Check if this is a "database already exists" error and adopt is enabled
|
|
@@ -339,7 +355,7 @@ const _D1Database = Resource(
|
|
|
339
355
|
) {
|
|
340
356
|
logger.log(`Database ${databaseName} already exists, adopting it`);
|
|
341
357
|
// Find the existing database by name
|
|
342
|
-
const databases = await listDatabases(api, databaseName);
|
|
358
|
+
const databases = await listDatabases(api, databaseName, props);
|
|
343
359
|
const existingDb = databases.find((db) => db.name === databaseName);
|
|
344
360
|
|
|
345
361
|
if (!existingDb) {
|
|
@@ -349,7 +365,7 @@ const _D1Database = Resource(
|
|
|
349
365
|
}
|
|
350
366
|
|
|
351
367
|
// Get the database details using its ID
|
|
352
|
-
dbData = await getDatabase(api, existingDb.id);
|
|
368
|
+
dbData = await getDatabase(api, existingDb.id, props);
|
|
353
369
|
|
|
354
370
|
// Update the database with the provided properties
|
|
355
371
|
if (props.readReplication) {
|
|
@@ -413,6 +429,7 @@ const _D1Database = Resource(
|
|
|
413
429
|
dev,
|
|
414
430
|
migrationsDir: props.migrationsDir,
|
|
415
431
|
migrationsTable: props.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE,
|
|
432
|
+
jurisdiction,
|
|
416
433
|
};
|
|
417
434
|
},
|
|
418
435
|
);
|
|
@@ -454,6 +471,9 @@ export async function createDatabase(
|
|
|
454
471
|
const createResponse = await api.post(
|
|
455
472
|
`/accounts/${api.accountId}/d1/database`,
|
|
456
473
|
createPayload,
|
|
474
|
+
{
|
|
475
|
+
headers: withJurisdiction(props),
|
|
476
|
+
},
|
|
457
477
|
);
|
|
458
478
|
|
|
459
479
|
if (!createResponse.ok) {
|
|
@@ -474,6 +494,7 @@ export async function createDatabase(
|
|
|
474
494
|
export async function getDatabase(
|
|
475
495
|
api: CloudflareApi,
|
|
476
496
|
databaseId?: string,
|
|
497
|
+
props: D1DatabaseProps = {},
|
|
477
498
|
): Promise<CloudflareD1Response> {
|
|
478
499
|
if (!databaseId) {
|
|
479
500
|
throw new Error("Database ID is required");
|
|
@@ -481,6 +502,9 @@ export async function getDatabase(
|
|
|
481
502
|
|
|
482
503
|
const response = await api.get(
|
|
483
504
|
`/accounts/${api.accountId}/d1/database/${databaseId}`,
|
|
505
|
+
{
|
|
506
|
+
headers: withJurisdiction(props),
|
|
507
|
+
},
|
|
484
508
|
);
|
|
485
509
|
|
|
486
510
|
if (!response.ok) {
|
|
@@ -496,6 +520,7 @@ export async function getDatabase(
|
|
|
496
520
|
export async function deleteDatabase(
|
|
497
521
|
api: CloudflareApi,
|
|
498
522
|
databaseId?: string,
|
|
523
|
+
props: D1DatabaseProps = {},
|
|
499
524
|
): Promise<void> {
|
|
500
525
|
if (!databaseId) {
|
|
501
526
|
logger.log("No database ID provided, skipping delete");
|
|
@@ -505,6 +530,9 @@ export async function deleteDatabase(
|
|
|
505
530
|
// Delete D1 database
|
|
506
531
|
const deleteResponse = await api.delete(
|
|
507
532
|
`/accounts/${api.accountId}/d1/database/${databaseId}`,
|
|
533
|
+
{
|
|
534
|
+
headers: withJurisdiction(props),
|
|
535
|
+
},
|
|
508
536
|
);
|
|
509
537
|
|
|
510
538
|
if (!deleteResponse.ok && deleteResponse.status !== 404) {
|
|
@@ -524,12 +552,16 @@ export async function deleteDatabase(
|
|
|
524
552
|
export async function listDatabases(
|
|
525
553
|
api: CloudflareApi,
|
|
526
554
|
name?: string,
|
|
555
|
+
props: D1DatabaseProps = {},
|
|
527
556
|
): Promise<{ name: string; id: string }[]> {
|
|
528
557
|
// Construct query string if name is provided
|
|
529
558
|
const queryParams = name ? `?name=${encodeURIComponent(name)}` : "";
|
|
530
559
|
|
|
531
560
|
const response = await api.get(
|
|
532
561
|
`/accounts/${api.accountId}/d1/database${queryParams}`,
|
|
562
|
+
{
|
|
563
|
+
headers: withJurisdiction(props),
|
|
564
|
+
},
|
|
533
565
|
);
|
|
534
566
|
|
|
535
567
|
if (!response.ok) {
|
|
@@ -582,6 +614,9 @@ export async function updateDatabase(
|
|
|
582
614
|
const updateResponse = await api.patch(
|
|
583
615
|
`/accounts/${api.accountId}/d1/database/${databaseId}`,
|
|
584
616
|
updatePayload,
|
|
617
|
+
{
|
|
618
|
+
headers: withJurisdiction(props),
|
|
619
|
+
},
|
|
585
620
|
);
|
|
586
621
|
|
|
587
622
|
if (!updateResponse.ok) {
|
|
@@ -608,6 +643,7 @@ async function cloneDb(
|
|
|
608
643
|
api: CloudflareApi,
|
|
609
644
|
sourceDb: D1Database | { id: string } | { name: string },
|
|
610
645
|
targetDbId: string,
|
|
646
|
+
jurisdiction: D1DatabaseJurisdiction,
|
|
611
647
|
): Promise<void> {
|
|
612
648
|
let sourceId: string;
|
|
613
649
|
|
|
@@ -617,7 +653,9 @@ async function cloneDb(
|
|
|
617
653
|
sourceId = sourceDb.id;
|
|
618
654
|
} else if ("name" in sourceDb && sourceDb.name) {
|
|
619
655
|
// Look up ID by name
|
|
620
|
-
const databases = await listDatabases(api, sourceDb.name
|
|
656
|
+
const databases = await listDatabases(api, sourceDb.name, {
|
|
657
|
+
jurisdiction,
|
|
658
|
+
});
|
|
621
659
|
const foundDb = databases.find((db) => db.name === sourceDb.name);
|
|
622
660
|
|
|
623
661
|
if (!foundDb) {
|
package/src/docker/api.ts
CHANGED
|
@@ -177,6 +177,13 @@ export class DockerApi {
|
|
|
177
177
|
return this.exec(["pull", image]);
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
async tagImage(
|
|
181
|
+
source: string,
|
|
182
|
+
target: string,
|
|
183
|
+
): Promise<{ stdout: string; stderr: string }> {
|
|
184
|
+
return this.exec(["tag", source, target]);
|
|
185
|
+
}
|
|
186
|
+
|
|
180
187
|
/**
|
|
181
188
|
* Build Docker image
|
|
182
189
|
*
|