alchemy 0.93.0 → 0.93.2
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 +2 -2
- package/lib/cloudflare/ai-search-namespace.d.ts.map +1 -1
- package/lib/cloudflare/ai-search-namespace.js +7 -10
- package/lib/cloudflare/ai-search-namespace.js.map +1 -1
- package/lib/cloudflare/ai-search.d.ts.map +1 -1
- package/lib/cloudflare/ai-search.js +7 -24
- package/lib/cloudflare/ai-search.js.map +1 -1
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js +14 -8
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/custom-domain.d.ts +14 -0
- package/lib/cloudflare/custom-domain.d.ts.map +1 -1
- package/lib/cloudflare/custom-domain.js +3 -0
- package/lib/cloudflare/custom-domain.js.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.js +12 -6
- package/lib/cloudflare/miniflare/build-worker-options.js.map +1 -1
- package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/remote-binding-proxy.js +31 -13
- package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -1
- package/lib/cloudflare/vite/plugin.d.ts.map +1 -1
- package/lib/cloudflare/vite/plugin.js +7 -1
- package/lib/cloudflare/vite/plugin.js.map +1 -1
- package/lib/cloudflare/website.d.ts +4 -0
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +17 -1
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +6 -0
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +3 -0
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/docker/image.d.ts +1 -1
- package/lib/docker/image.d.ts.map +1 -1
- package/lib/docker/image.js +4 -44
- package/lib/docker/image.js.map +1 -1
- package/lib/docker/registry.d.ts +11 -0
- package/lib/docker/registry.d.ts.map +1 -0
- package/lib/docker/registry.js +41 -0
- package/lib/docker/registry.js.map +1 -0
- package/package.json +2 -2
- package/src/cloudflare/ai-search-namespace.ts +7 -11
- package/src/cloudflare/ai-search.ts +7 -26
- package/src/cloudflare/container.ts +15 -8
- package/src/cloudflare/custom-domain.ts +25 -1
- package/src/cloudflare/miniflare/build-worker-options.ts +19 -9
- package/src/cloudflare/miniflare/remote-binding-proxy.ts +58 -34
- package/src/cloudflare/vite/plugin.ts +7 -1
- package/src/cloudflare/website.ts +22 -1
- package/src/cloudflare/worker.ts +9 -0
- package/src/docker/image.ts +5 -56
- package/src/docker/registry.ts +62 -0
- package/workers/tunnel-proxy.js +1 -1
package/src/docker/image.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
import path from "pathe";
|
|
4
3
|
import type { Context } from "../context.ts";
|
|
5
4
|
import { Resource } from "../resource.ts";
|
|
6
5
|
import type { Secret } from "../secret.ts";
|
|
7
6
|
import { DockerApi } from "./api.ts";
|
|
7
|
+
import { pushImageToRegistry } from "./registry.ts";
|
|
8
8
|
import type { RemoteImage } from "./remote-image.ts";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -66,9 +66,9 @@ export interface DockerBuildOptions {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
export interface ImageRegistry {
|
|
69
|
+
server: string;
|
|
69
70
|
username: string;
|
|
70
71
|
password: Secret;
|
|
71
|
-
server: string;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/**
|
|
@@ -285,63 +285,12 @@ export const Image = Resource(
|
|
|
285
285
|
let repoDigest: string | undefined;
|
|
286
286
|
let finalImageRef = imageRef;
|
|
287
287
|
if (props.registry && !props.skipPush) {
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const registryHost = server.replace(/\/$/, "");
|
|
292
|
-
|
|
293
|
-
// Determine if the built image already includes a registry host (e.g. ghcr.io/user/repo)
|
|
294
|
-
const firstSegment = imageRef.split("/")[0];
|
|
295
|
-
const hasRegistryPrefix = firstSegment.includes(".");
|
|
296
|
-
|
|
297
|
-
// Compose the target image reference that will be pushed
|
|
298
|
-
const targetImage = hasRegistryPrefix
|
|
299
|
-
? imageRef // already fully-qualified
|
|
300
|
-
: `${registryHost}/${imageRef}`;
|
|
301
|
-
|
|
302
|
-
try {
|
|
303
|
-
// Create a temporary directory that will act as an isolated Docker config
|
|
304
|
-
// (credentials) directory. This prevents race-conditions when multiple
|
|
305
|
-
// concurrent tests perform `docker login` / `logout` by ensuring each
|
|
306
|
-
// Image operation has its own credential store.
|
|
307
|
-
const tempConfigDir = await fs.mkdtemp(
|
|
308
|
-
path.join(os.tmpdir(), "docker-config-"),
|
|
309
|
-
);
|
|
310
|
-
const api = new DockerApi({ configDir: tempConfigDir });
|
|
311
|
-
|
|
312
|
-
// Authenticate to registry using the isolated config directory
|
|
313
|
-
await api.login(registryHost, username, password.unencrypted);
|
|
314
|
-
|
|
315
|
-
// Tag local image with fully qualified name if necessary
|
|
316
|
-
if (targetImage !== imageRef) {
|
|
317
|
-
await api.exec(["tag", imageRef, targetImage]);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Push the image
|
|
321
|
-
const { stdout: pushOut } = await api.exec(["push", targetImage]);
|
|
322
|
-
|
|
323
|
-
// Attempt to extract the repo digest from push output
|
|
324
|
-
const digestMatch = /digest:\s+([a-z0-9]+:[a-f0-9]{64})/.exec(pushOut);
|
|
325
|
-
if (digestMatch) {
|
|
326
|
-
const digestHash = digestMatch[1];
|
|
327
|
-
// Strip tag (anything after last :) to build image@digest reference
|
|
328
|
-
const [repoWithoutTag] =
|
|
329
|
-
targetImage.split(":").length > 2
|
|
330
|
-
? [targetImage] // unlikely but safety
|
|
331
|
-
: [targetImage.substring(0, targetImage.lastIndexOf(":"))];
|
|
332
|
-
repoDigest = `${repoWithoutTag}@${digestHash}`;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Update the final image reference to point at the pushed image
|
|
336
|
-
finalImageRef = targetImage;
|
|
337
|
-
} finally {
|
|
338
|
-
// Clean up credentials from the isolated config
|
|
339
|
-
await api.logout(registryHost);
|
|
340
|
-
}
|
|
288
|
+
const pushedImage = await pushImageToRegistry(imageRef, props.registry);
|
|
289
|
+
finalImageRef = pushedImage.imageRef;
|
|
290
|
+
repoDigest = pushedImage.repoDigest;
|
|
341
291
|
}
|
|
342
292
|
return {
|
|
343
293
|
kind: "Image",
|
|
344
|
-
...props,
|
|
345
294
|
tag,
|
|
346
295
|
name,
|
|
347
296
|
imageRef: finalImageRef,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "pathe";
|
|
4
|
+
import { Secret, type Secret as SecretValue } from "../secret.ts";
|
|
5
|
+
import { DockerApi } from "./api.ts";
|
|
6
|
+
|
|
7
|
+
export interface RegistryPushCredentials {
|
|
8
|
+
server: string;
|
|
9
|
+
username: string;
|
|
10
|
+
password: string | SecretValue;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function pushImageToRegistry(
|
|
14
|
+
imageRef: string,
|
|
15
|
+
registry: RegistryPushCredentials,
|
|
16
|
+
): Promise<{
|
|
17
|
+
imageRef: string;
|
|
18
|
+
repoDigest?: string;
|
|
19
|
+
}> {
|
|
20
|
+
const registryHost = registry.server.replace(/\/$/, "");
|
|
21
|
+
const password = Secret.unwrap(registry.password);
|
|
22
|
+
|
|
23
|
+
const firstSegment = imageRef.split("/")[0];
|
|
24
|
+
const hasRegistryPrefix = firstSegment.includes(".");
|
|
25
|
+
const targetImage = hasRegistryPrefix
|
|
26
|
+
? imageRef
|
|
27
|
+
: `${registryHost}/${imageRef}`;
|
|
28
|
+
|
|
29
|
+
let repoDigest: string | undefined;
|
|
30
|
+
let api: DockerApi | undefined;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const tempConfigDir = await fs.mkdtemp(
|
|
34
|
+
path.join(os.tmpdir(), "docker-config-"),
|
|
35
|
+
);
|
|
36
|
+
api = new DockerApi({ configDir: tempConfigDir });
|
|
37
|
+
|
|
38
|
+
await api.login(registryHost, registry.username, password);
|
|
39
|
+
|
|
40
|
+
if (targetImage !== imageRef) {
|
|
41
|
+
await api.exec(["tag", imageRef, targetImage]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const { stdout } = await api.exec(["push", targetImage]);
|
|
45
|
+
const digestMatch = /digest:\s+([a-z0-9]+:[a-f0-9]{64})/.exec(stdout);
|
|
46
|
+
if (digestMatch) {
|
|
47
|
+
const digestHash = digestMatch[1];
|
|
48
|
+
const [repoWithoutTag] =
|
|
49
|
+
targetImage.split(":").length > 2
|
|
50
|
+
? [targetImage]
|
|
51
|
+
: [targetImage.substring(0, targetImage.lastIndexOf(":"))];
|
|
52
|
+
repoDigest = `${repoWithoutTag}@${digestHash}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
imageRef: targetImage,
|
|
57
|
+
repoDigest,
|
|
58
|
+
};
|
|
59
|
+
} finally {
|
|
60
|
+
await api?.logout(registryHost);
|
|
61
|
+
}
|
|
62
|
+
}
|
package/workers/tunnel-proxy.js
CHANGED
|
@@ -83,7 +83,7 @@ const renderErrorHtml = (props) => `
|
|
|
83
83
|
Alchemy</a>.</p>
|
|
84
84
|
</div>
|
|
85
85
|
<div class="bg-slate-200 px-5 py-3 flex flex-col w-full max-w-lg">
|
|
86
|
-
<p class="text-sm text-slate-500">Alchemy 0.93.
|
|
86
|
+
<p class="text-sm text-slate-500">Alchemy 0.93.2</p>
|
|
87
87
|
</div>
|
|
88
88
|
</div>
|
|
89
89
|
</body>
|