alchemy 0.41.1 → 0.42.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.
Files changed (48) hide show
  1. package/README.md +2 -0
  2. package/bin/alchemy.mjs +99 -44
  3. package/lib/build-date.d.ts +1 -1
  4. package/lib/build-date.js +1 -1
  5. package/lib/cloudflare/certificate-pack.d.ts +216 -0
  6. package/lib/cloudflare/certificate-pack.d.ts.map +1 -0
  7. package/lib/cloudflare/certificate-pack.js +350 -0
  8. package/lib/cloudflare/certificate-pack.js.map +1 -0
  9. package/lib/cloudflare/container.d.ts +6 -0
  10. package/lib/cloudflare/container.d.ts.map +1 -1
  11. package/lib/cloudflare/container.js +32 -25
  12. package/lib/cloudflare/container.js.map +1 -1
  13. package/lib/cloudflare/index.d.ts +3 -0
  14. package/lib/cloudflare/index.d.ts.map +1 -1
  15. package/lib/cloudflare/index.js +3 -0
  16. package/lib/cloudflare/index.js.map +1 -1
  17. package/lib/cloudflare/orange.d.ts +37 -0
  18. package/lib/cloudflare/orange.d.ts.map +1 -0
  19. package/lib/cloudflare/orange.js +48 -0
  20. package/lib/cloudflare/orange.js.map +1 -0
  21. package/lib/cloudflare/redirect-rule.d.ts +168 -0
  22. package/lib/cloudflare/redirect-rule.d.ts.map +1 -0
  23. package/lib/cloudflare/redirect-rule.js +380 -0
  24. package/lib/cloudflare/redirect-rule.js.map +1 -0
  25. package/lib/cloudflare/worker/miniflare-worker-options.d.ts.map +1 -1
  26. package/lib/cloudflare/worker/miniflare-worker-options.js +11 -12
  27. package/lib/cloudflare/worker/miniflare-worker-options.js.map +1 -1
  28. package/lib/cloudflare/worker.d.ts +1 -1
  29. package/lib/fs/file-system-state-store.d.ts.map +1 -1
  30. package/lib/fs/file-system-state-store.js +8 -1
  31. package/lib/fs/file-system-state-store.js.map +1 -1
  32. package/package.json +1 -1
  33. package/src/build-date.ts +1 -1
  34. package/src/cloudflare/certificate-pack.ts +698 -0
  35. package/src/cloudflare/container.ts +44 -30
  36. package/src/cloudflare/index.ts +3 -0
  37. package/src/cloudflare/orange.ts +61 -0
  38. package/src/cloudflare/redirect-rule.ts +642 -0
  39. package/src/cloudflare/worker/miniflare-worker-options.ts +14 -12
  40. package/src/fs/file-system-state-store.ts +8 -1
  41. package/templates/astro/package.json +1 -1
  42. package/templates/nuxt/package.json +1 -1
  43. package/templates/react-router/package.json +1 -1
  44. package/templates/rwsdk/package.json +1 -1
  45. package/templates/sveltekit/package.json +1 -1
  46. package/templates/tanstack-start/package.json +1 -1
  47. package/templates/typescript/package.json +1 -1
  48. package/templates/vite/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import type { Context } from "../context.ts";
2
- import { Image, type ImageProps, type ImageRegistry } from "../docker/image.ts";
2
+ import { Image, type ImageProps } from "../docker/image.ts";
3
3
  import { Resource } from "../resource.ts";
4
+ import { Scope } from "../scope.ts";
4
5
  import { secret } from "../secret.ts";
5
6
  import {
6
7
  type CloudflareApi,
@@ -17,6 +18,9 @@ export interface ContainerProps
17
18
  instanceType?: InstanceType;
18
19
  observability?: DeploymentObservability;
19
20
  schedulingPolicy?: SchedulingPolicy;
21
+ dev?: {
22
+ remote?: boolean;
23
+ };
20
24
  }
21
25
 
22
26
  /**
@@ -40,6 +44,9 @@ export type Container<T = any> = {
40
44
  instanceType?: InstanceType;
41
45
  observability?: DeploymentObservability;
42
46
  schedulingPolicy?: SchedulingPolicy;
47
+ dev?: {
48
+ remote?: boolean;
49
+ };
43
50
  /**
44
51
  * @internal
45
52
  */
@@ -50,48 +57,55 @@ export async function Container<T>(
50
57
  id: string,
51
58
  props: ContainerProps,
52
59
  ): Promise<Container<T>> {
53
- // Otherwise, obtain Cloudflare registry credentials automatically
54
- const api = await createCloudflareApi(props);
55
- const creds = await getContainerCredentials(api);
56
-
57
- const registry: ImageRegistry = {
58
- server: "registry.cloudflare.com",
59
- username: creds.username || creds.user!,
60
- password: secret(creds.password),
61
- };
62
-
63
- // Ensure repository name is namespaced with accountId
64
- const repoBase = props.name ?? id;
65
- const repoName = repoBase.includes("/")
66
- ? repoBase
67
- : `${api.accountId}/${repoBase}`;
68
-
69
- // Replace disallowed "latest" tag with timestamp
70
- const finalTag =
60
+ const name = props.name ?? id;
61
+ const tag =
71
62
  props.tag === undefined || props.tag === "latest"
72
63
  ? `latest-${Date.now()}`
73
64
  : props.tag;
74
65
 
75
- const image = await Image(id, {
76
- build: props.build,
77
- name: repoName,
78
- tag: finalTag,
79
- skipPush: false,
80
- registry,
81
- });
82
-
83
- return {
66
+ const output: Omit<Container<T>, "image"> = {
84
67
  type: "container",
85
68
  id,
86
- name: props.name ?? id,
69
+ name,
87
70
  className: props.className,
88
- image,
89
71
  maxInstances: props.maxInstances,
90
72
  scriptName: props.scriptName,
91
73
  instanceType: props.instanceType,
92
74
  observability: props.observability,
93
75
  schedulingPolicy: props.schedulingPolicy,
94
76
  sqlite: true,
77
+ dev: props.dev,
78
+ };
79
+
80
+ if (Scope.current.dev && !props.dev?.remote) {
81
+ const image = await Image(id, {
82
+ name: `cloudflare-dev/${name}`, // prefix used by Miniflare
83
+ tag,
84
+ build: props.build,
85
+ });
86
+
87
+ return {
88
+ ...output,
89
+ image,
90
+ };
91
+ }
92
+
93
+ const api = await createCloudflareApi(props);
94
+ const credentials = await getContainerCredentials(api);
95
+
96
+ const image = await Image(id, {
97
+ name: `${api.accountId}/${name}`,
98
+ tag,
99
+ registry: {
100
+ server: "registry.cloudflare.com",
101
+ username: credentials.username || credentials.user!,
102
+ password: secret(credentials.password),
103
+ },
104
+ });
105
+
106
+ return {
107
+ ...output,
108
+ image,
95
109
  };
96
110
  }
97
111
 
@@ -13,6 +13,7 @@ export * from "./browser-rendering.ts";
13
13
  export * from "./bucket.ts";
14
14
  export * from "./bundle/external.ts";
15
15
  export * from "./bundle/local-dev-cloudflare-shim.ts";
16
+ export * from "./certificate-pack.ts";
16
17
  export * from "./container.ts";
17
18
  export * from "./custom-domain.ts";
18
19
  export * from "./d1-clone.ts";
@@ -31,12 +32,14 @@ export * from "./hyperdrive.ts";
31
32
  export * from "./images.ts";
32
33
  export * from "./kv-namespace.ts";
33
34
  export * from "./nuxt.ts";
35
+ export * from "./orange.ts";
34
36
  export * from "./permission-groups.ts";
35
37
  export * from "./pipeline.ts";
36
38
  export * from "./queue-consumer.ts";
37
39
  export * from "./queue.ts";
38
40
  export * from "./r2-rest-state-store.ts";
39
41
  export * from "./react-router.ts";
42
+ export * from "./redirect-rule.ts";
40
43
  export * from "./redwood.ts";
41
44
  export * from "./route.ts";
42
45
  export * from "./secret-key.ts";
@@ -0,0 +1,61 @@
1
+ import type { Assets } from "./assets.js";
2
+ import type { Bindings } from "./bindings.js";
3
+ import { Website, type WebsiteProps } from "./website.js";
4
+ import type { Worker } from "./worker.js";
5
+
6
+ export interface OrangeProps<B extends Bindings> extends WebsiteProps<B> {}
7
+
8
+ // don't allow the ASSETS to be overriden
9
+ export type Orange<B extends Bindings> = B extends { ASSETS: any }
10
+ ? never
11
+ : Worker<B & { ASSETS: Assets }>;
12
+
13
+ /**
14
+ * Deploys an Orange application to Cloudflare Workers.
15
+ *
16
+ * This resource simplifies deploying Orange applications by assuming the build
17
+ * command, main entrypoint, and assets directory based on the `create-orange`
18
+ * template CLI.
19
+ *
20
+ * It wraps the underlying `Website` resource.
21
+ *
22
+ * @example
23
+ * // Deploy a basic Orange application with default settings
24
+ * const orangeApp = await Orange("my-orange-app");
25
+ *
26
+ * @example
27
+ * // Deploy with a database binding
28
+ * const database = await D1Database("orange-db");
29
+ * const orangeApp = await Orange("orange-with-db", {
30
+ * bindings: { DB: database }
31
+ * });
32
+ *
33
+ * @param id - Unique identifier for the Orange resource
34
+ * @param props - Configuration properties for the Orange resource
35
+ * @returns A Cloudflare Worker resource representing the deployed Orange application
36
+ */
37
+ export async function Orange<B extends Bindings>(
38
+ id: string,
39
+ props?: Partial<OrangeProps<B>>,
40
+ ): Promise<Orange<B>> {
41
+ return Website(id, {
42
+ ...props,
43
+ command: props?.command ?? "bun run build",
44
+ // The entrypoint and the Wrangler main must differ for the Cloudflare vite plugin
45
+ // to bundle the application correctly, and alchemy must run our bundler on the Vite
46
+ // output since we don't resolve vite imports.
47
+ wrangler: props?.wrangler ?? {
48
+ main: "app/entry.server.ts",
49
+ },
50
+ // Since we've already bundled the application with the build command, we can just
51
+ // upload the modules in the `dist/srr` directory. With `noBundle: true`, any files
52
+ // that match `**/*.js`, `**/*.mjs`, and `**/*.wasm` under the entrypoint's directory
53
+ // (which is `dist/ssr`) will be uploaded to the worker so we don't need any explicit
54
+ // module rules.
55
+ noBundle: true,
56
+ // `main` is used as the entrypoint in the Worker resource.
57
+ main: props?.main ?? "dist/ssr/entry.server.js",
58
+ assets: props?.assets ?? "dist/client",
59
+ compatibilityFlags: ["nodejs_compat", ...(props?.compatibilityFlags ?? [])],
60
+ });
61
+ }