alchemy 2.0.0-beta.78 → 2.0.0-beta.79

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 (106) hide show
  1. package/bin/cli.js +25 -65
  2. package/bin/exec.js +1 -1
  3. package/bin/tsconfig.json +5 -0
  4. package/lib/Cloudflare/Workers/InferEnv.d.ts +3 -1
  5. package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
  6. package/lib/Cloudflare/Workers/Worker.d.ts +5 -2
  7. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  8. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  9. package/lib/Prisma/Providers.d.ts +4 -1
  10. package/lib/Prisma/Providers.d.ts.map +1 -1
  11. package/lib/Prisma/Providers.js +7 -2
  12. package/lib/Prisma/Providers.js.map +1 -1
  13. package/lib/Prisma/Website/Artifact.d.ts +52 -0
  14. package/lib/Prisma/Website/Artifact.d.ts.map +1 -0
  15. package/lib/Prisma/Website/Artifact.js +285 -0
  16. package/lib/Prisma/Website/Artifact.js.map +1 -0
  17. package/lib/Prisma/Website/Astro.d.ts +62 -0
  18. package/lib/Prisma/Website/Astro.d.ts.map +1 -0
  19. package/lib/Prisma/Website/Astro.js +50 -0
  20. package/lib/Prisma/Website/Astro.js.map +1 -0
  21. package/lib/Prisma/Website/Foldkit.d.ts +30 -0
  22. package/lib/Prisma/Website/Foldkit.d.ts.map +1 -0
  23. package/lib/Prisma/Website/Foldkit.js +30 -0
  24. package/lib/Prisma/Website/Foldkit.js.map +1 -0
  25. package/lib/Prisma/Website/FrameworkSite.d.ts +82 -0
  26. package/lib/Prisma/Website/FrameworkSite.d.ts.map +1 -0
  27. package/lib/Prisma/Website/FrameworkSite.js +96 -0
  28. package/lib/Prisma/Website/FrameworkSite.js.map +1 -0
  29. package/lib/Prisma/Website/Nextjs.d.ts +35 -0
  30. package/lib/Prisma/Website/Nextjs.d.ts.map +1 -0
  31. package/lib/Prisma/Website/Nextjs.js +37 -0
  32. package/lib/Prisma/Website/Nextjs.js.map +1 -0
  33. package/lib/Prisma/Website/Nuxt.d.ts +37 -0
  34. package/lib/Prisma/Website/Nuxt.d.ts.map +1 -0
  35. package/lib/Prisma/Website/Nuxt.js +37 -0
  36. package/lib/Prisma/Website/Nuxt.js.map +1 -0
  37. package/lib/Prisma/Website/Octane.d.ts +35 -0
  38. package/lib/Prisma/Website/Octane.d.ts.map +1 -0
  39. package/lib/Prisma/Website/Octane.js +36 -0
  40. package/lib/Prisma/Website/Octane.js.map +1 -0
  41. package/lib/Prisma/Website/ReactRouter.d.ts +35 -0
  42. package/lib/Prisma/Website/ReactRouter.d.ts.map +1 -0
  43. package/lib/Prisma/Website/ReactRouter.js +36 -0
  44. package/lib/Prisma/Website/ReactRouter.js.map +1 -0
  45. package/lib/Prisma/Website/SolidStart.d.ts +37 -0
  46. package/lib/Prisma/Website/SolidStart.d.ts.map +1 -0
  47. package/lib/Prisma/Website/SolidStart.js +37 -0
  48. package/lib/Prisma/Website/SolidStart.js.map +1 -0
  49. package/lib/Prisma/Website/StaticSite.d.ts +57 -0
  50. package/lib/Prisma/Website/StaticSite.d.ts.map +1 -0
  51. package/lib/Prisma/Website/StaticSite.js +118 -0
  52. package/lib/Prisma/Website/StaticSite.js.map +1 -0
  53. package/lib/Prisma/Website/SvelteKit.d.ts +37 -0
  54. package/lib/Prisma/Website/SvelteKit.d.ts.map +1 -0
  55. package/lib/Prisma/Website/SvelteKit.js +37 -0
  56. package/lib/Prisma/Website/SvelteKit.js.map +1 -0
  57. package/lib/Prisma/Website/TanStackStart.d.ts +35 -0
  58. package/lib/Prisma/Website/TanStackStart.d.ts.map +1 -0
  59. package/lib/Prisma/Website/TanStackStart.js +36 -0
  60. package/lib/Prisma/Website/TanStackStart.js.map +1 -0
  61. package/lib/Prisma/Website/Vite.d.ts +42 -0
  62. package/lib/Prisma/Website/Vite.d.ts.map +1 -0
  63. package/lib/Prisma/Website/Vite.js +38 -0
  64. package/lib/Prisma/Website/Vite.js.map +1 -0
  65. package/lib/Prisma/Website/Vocs.d.ts +37 -0
  66. package/lib/Prisma/Website/Vocs.d.ts.map +1 -0
  67. package/lib/Prisma/Website/Vocs.js +38 -0
  68. package/lib/Prisma/Website/Vocs.js.map +1 -0
  69. package/lib/Prisma/Website/Waku.d.ts +44 -0
  70. package/lib/Prisma/Website/Waku.d.ts.map +1 -0
  71. package/lib/Prisma/Website/Waku.js +38 -0
  72. package/lib/Prisma/Website/Waku.js.map +1 -0
  73. package/lib/Prisma/Website/index.d.ts +15 -0
  74. package/lib/Prisma/Website/index.d.ts.map +1 -0
  75. package/lib/Prisma/Website/index.js +14 -0
  76. package/lib/Prisma/Website/index.js.map +1 -0
  77. package/lib/Prisma/index.d.ts +1 -0
  78. package/lib/Prisma/index.d.ts.map +1 -1
  79. package/lib/Prisma/index.js +1 -0
  80. package/lib/Prisma/index.js.map +1 -1
  81. package/lib/State/HttpStateApi.d.ts +11 -11
  82. package/lib/Website/Server.d.ts.map +1 -1
  83. package/lib/Website/Server.js +18 -8
  84. package/lib/Website/Server.js.map +1 -1
  85. package/package.json +6 -6
  86. package/src/Cloudflare/Workers/InferEnv.ts +5 -3
  87. package/src/Cloudflare/Workers/Worker.ts +25 -5
  88. package/src/Prisma/Providers.ts +11 -0
  89. package/src/Prisma/Website/Artifact.ts +429 -0
  90. package/src/Prisma/Website/Astro.ts +72 -0
  91. package/src/Prisma/Website/Foldkit.ts +34 -0
  92. package/src/Prisma/Website/FrameworkSite.ts +204 -0
  93. package/src/Prisma/Website/Nextjs.ts +41 -0
  94. package/src/Prisma/Website/Nuxt.ts +44 -0
  95. package/src/Prisma/Website/Octane.ts +40 -0
  96. package/src/Prisma/Website/ReactRouter.ts +40 -0
  97. package/src/Prisma/Website/SolidStart.ts +44 -0
  98. package/src/Prisma/Website/StaticSite.ts +149 -0
  99. package/src/Prisma/Website/SvelteKit.ts +44 -0
  100. package/src/Prisma/Website/TanStackStart.ts +40 -0
  101. package/src/Prisma/Website/Vite.ts +50 -0
  102. package/src/Prisma/Website/Vocs.ts +45 -0
  103. package/src/Prisma/Website/Waku.ts +52 -0
  104. package/src/Prisma/Website/index.ts +19 -0
  105. package/src/Prisma/index.ts +1 -0
  106. package/src/Website/Server.ts +21 -8
@@ -0,0 +1,204 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Output from "../../Output.ts";
3
+ import * as Redacted from "effect/Redacted";
4
+ import { AlchemyContext } from "../../AlchemyContext.ts";
5
+ import type { MemoOptions } from "../../Command/Memo.ts";
6
+ import { ProviderModePolicy } from "../../ProviderMode.ts";
7
+ import type { WebsiteAssetsProps } from "../../Website/assets.ts";
8
+ import { Server, type ServerDevProps } from "../../Website/Server.ts";
9
+ import { Compute, type ComputeProps } from "../Compute.ts";
10
+ import { CustomDomain } from "../CustomDomain.ts";
11
+ import { Project } from "../Project.ts";
12
+ import type { Providers } from "../Providers.ts";
13
+ import type { PrismaRegionId } from "../Types.ts";
14
+ import { WebsiteArtifact } from "./Artifact.ts";
15
+
16
+ /** A Prisma Project resource, ID, or lightweight ID reference. */
17
+ export type WebsiteProjectReference =
18
+ | Project
19
+ | string
20
+ | {
21
+ /** Existing Prisma project ID; no project is created or owned by the site. */
22
+ readonly projectId: string | Output.Output<string>;
23
+ };
24
+
25
+ /** Deployment controls that do not replace the framework build or artifact. */
26
+ export type WebsiteComputeOptions = Pick<
27
+ ComputeProps,
28
+ | "appName"
29
+ | "port"
30
+ | "envClass"
31
+ | "start"
32
+ | "skipPromote"
33
+ | "destroyOldDeployment"
34
+ | "timeoutSeconds"
35
+ | "pollIntervalMs"
36
+ | "verifyUrl"
37
+ | "healthCheck"
38
+ | "urlReadinessTimeoutSeconds"
39
+ >;
40
+
41
+ /** Shared contract for Prisma's framework website composites. */
42
+ export interface FrameworkSiteProps {
43
+ /** Existing Project or ID reference, optionally produced by an Effect. Omission creates a project without a database, only on live deployments. */
44
+ project?:
45
+ | WebsiteProjectReference
46
+ | Effect.Effect<WebsiteProjectReference, never, Providers>;
47
+ /** Application directory containing package.json and framework configuration. @default "." */
48
+ rootDir?: string;
49
+ /** Build input hashing options. Set false to rebuild on every deployment. @default true */
50
+ memo?: MemoOptions | boolean;
51
+ /** Build, development, and runtime environment. Wrap secrets in Redacted; public framework variables can be compiled into browser assets. */
52
+ env?: Record<
53
+ string,
54
+ string | Redacted.Redacted<string> | Output.Output<string | undefined>
55
+ >;
56
+ /** Origin static-file routing, using the same vocabulary as Fly and Railway websites. */
57
+ assets?: WebsiteAssetsProps;
58
+ /** Native framework development server options, including external-server mode. */
59
+ dev?: ServerDevProps;
60
+ /** Custom hostname attached using Prisma.CustomDomain. Only apps on the default branch support custom domains; configure the returned DNS records before routing traffic. */
61
+ domain?: string;
62
+ /** Compute region. Defaults to the project's default region, then us-east-1. */
63
+ regionId?: PrismaRegionId;
64
+ /** Existing branch ID. Mutually exclusive with branchGitName. */
65
+ branchId?: string;
66
+ /** Existing branch git name. Defaults to the project's default branch. */
67
+ branchGitName?: string;
68
+ /** Compute deployment, readiness, and rollout options. The website owns its build, artifact, and runtime environment. */
69
+ compute?: WebsiteComputeOptions;
70
+ /** Accepted for website API parity; Prisma Compute does not persist resource tags. */
71
+ tags?: Record<string, string>;
72
+ }
73
+
74
+ /** Outputs of a Prisma framework or static website. */
75
+ export interface Website {
76
+ /** Native dev-server URL locally; Compute URL or configured custom-domain URL on live deployments. */
77
+ url: string | Output.Output<string | undefined> | undefined;
78
+ /** Compute app serving the artifact. Undefined during native development. */
79
+ compute: Compute | undefined;
80
+ /** Project resource or existing project reference. Undefined during native development. */
81
+ project: WebsiteProjectReference | undefined;
82
+ /** Custom-domain resource, including DNS records and certificate status. Undefined without domain or during native development. */
83
+ domain: CustomDomain | undefined;
84
+ }
85
+
86
+ /** Internal framework-to-Node-target wiring. */
87
+ export interface FrameworkSiteConfig {
88
+ /** Framework integration module. */
89
+ framework: string;
90
+ /** Existing Node deploy-target module. */
91
+ target: string;
92
+ /** Serializable framework-specific overrides. */
93
+ options?: Record<string, unknown>;
94
+ /** Artifact layout; Next.js serves from the application root. */
95
+ layout?: "output" | "next";
96
+ /** Default not-found behavior, overridden by assets.notFoundHandling. */
97
+ notFoundHandling?: "none" | "spa" | "404-page";
98
+ /** Default extensionless HTML behavior, overridden by assets.htmlHandling. */
99
+ htmlHandling?: "none" | "drop-trailing-slash";
100
+ }
101
+
102
+ /** Resolve build-time secrets without changing the redacted runtime env props. */
103
+ export const websiteBuildEnv = (env: FrameworkSiteProps["env"]) =>
104
+ env === undefined
105
+ ? undefined
106
+ : Object.fromEntries(
107
+ Object.entries(env).map(([key, value]) => [
108
+ key,
109
+ Redacted.isRedacted(value) ? Redacted.value(value) : value,
110
+ ]),
111
+ );
112
+
113
+ /** Shared live half, called only after a build resource has been declared. */
114
+ export const deployWebsite = Effect.fn(function* (
115
+ props: Omit<FrameworkSiteProps, "dev">,
116
+ artifact: WebsiteArtifact,
117
+ ): Effect.fn.Return<Website, never, Providers> {
118
+ const project = Effect.isEffect(props.project)
119
+ ? yield* props.project
120
+ : (props.project ??
121
+ (yield* Project("Project", {
122
+ createDatabase: false,
123
+ region: props.regionId,
124
+ })));
125
+ const port = props.compute?.port ?? 3000;
126
+ const compute = yield* Compute("Compute", {
127
+ ...props.compute,
128
+ project: typeof project === "string" ? project : project.projectId,
129
+ artifactPath: artifact.artifactPath,
130
+ isExternal: true,
131
+ port,
132
+ regionId: props.regionId,
133
+ branchId: props.branchId,
134
+ branchGitName: props.branchGitName,
135
+ env: {
136
+ ...props.env,
137
+ PORT: String(port),
138
+ HOST: "0.0.0.0",
139
+ NODE_ENV: "production",
140
+ },
141
+ });
142
+ const domain = props.domain
143
+ ? yield* CustomDomain("Domain", { app: compute, hostname: props.domain })
144
+ : undefined;
145
+ return {
146
+ url: domain
147
+ ? Output.map(domain.hostname, (hostname) => `https://${hostname}`)
148
+ : compute.url,
149
+ compute,
150
+ project,
151
+ domain,
152
+ };
153
+ });
154
+
155
+ /** Compose a real framework build/dev server with a traced Prisma artifact. */
156
+ export const makeFrameworkSite = Effect.fn(function* (
157
+ _id: string,
158
+ props: FrameworkSiteProps,
159
+ config: FrameworkSiteConfig,
160
+ ) {
161
+ const context = yield* AlchemyContext;
162
+ const remote = yield* ProviderModePolicy;
163
+ const handling = props.assets?.notFoundHandling;
164
+ const targetConfig = {
165
+ notFoundHandling:
166
+ handling === "single-page-application"
167
+ ? "spa"
168
+ : (handling ?? config.notFoundHandling),
169
+ htmlHandling: props.assets?.htmlHandling ?? config.htmlHandling,
170
+ };
171
+ const build = yield* Server("Build", {
172
+ framework: config.framework,
173
+ target: config.target,
174
+ root: props.rootDir,
175
+ env: websiteBuildEnv(props.env),
176
+ options: { ...config.options, ...targetConfig, targetConfig },
177
+ memo: props.memo,
178
+ dev: props.dev,
179
+ });
180
+ if (context.dev && remote !== true) {
181
+ return {
182
+ url: build.url,
183
+ compute: undefined,
184
+ project: undefined,
185
+ domain: undefined,
186
+ } satisfies Website;
187
+ }
188
+ const requiredPath = (value: string | undefined) =>
189
+ value === undefined
190
+ ? Effect.die(
191
+ new Error(
192
+ `The ${config.framework} Node build produced no deployable server output.`,
193
+ ),
194
+ )
195
+ : Effect.succeed(value);
196
+ const artifact = yield* WebsiteArtifact("Artifact", {
197
+ root: props.rootDir ?? ".",
198
+ distDir: Output.mapEffect(requiredPath)(build.distDir),
199
+ serverEntry: Output.mapEffect(requiredPath)(build.serverEntry),
200
+ layout: config.layout,
201
+ buildHash: build.hash.output,
202
+ });
203
+ return yield* deployWebsite(props, artifact);
204
+ });
@@ -0,0 +1,41 @@
1
+ import * as Namespace from "../../Namespace.ts";
2
+ import { makeFrameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
3
+
4
+ /** Configuration for a Prisma Nextjs website. */
5
+ export interface NextjsProps extends FrameworkSiteProps {}
6
+
7
+ /**
8
+ * Next.js on Prisma Compute using next build and the existing Node custom-server target, not OpenNext. The artifact contains .next, public, configuration, and traced runtime dependencies, preserving installed package versions.
9
+ *
10
+ * Native framework development and HMR run without Prisma cloud resources.
11
+ * Apply `Alchemy.remote()` to use the live Compute deployment during dev.
12
+ * Packaging requires the optional `@vercel/nft` peer dependency.
13
+ *
14
+ * ### Creating a Website
15
+ * **Example:** Nextjs application
16
+ * ```typescript
17
+ * const site = yield* Prisma.Website.Nextjs("Web", {
18
+ * rootDir: "./app",
19
+ * });
20
+ * ```
21
+ *
22
+ * ### Deployment Configuration
23
+ * **Example:** Existing project and custom hostname
24
+ * ```typescript
25
+ * const site = yield* Prisma.Website.Nextjs("Web", {
26
+ * project,
27
+ * domain: "www.example.com",
28
+ * env: { API_BASE: "https://api.example.com" },
29
+ * compute: { destroyOldDeployment: true },
30
+ * });
31
+ * ```
32
+ *
33
+ * @resource
34
+ * @product Website
35
+ */
36
+ export const Nextjs = (id: string, props: NextjsProps = {}) =>
37
+ makeFrameworkSite(id, props, {
38
+ framework: "@alchemy.run/frontend-frameworks/nextjs/node",
39
+ target: "@alchemy.run/frontend-frameworks/nextjs/node",
40
+ layout: "next",
41
+ }).pipe(Namespace.push(id));
@@ -0,0 +1,44 @@
1
+ import * as Namespace from "../../Namespace.ts";
2
+ import { makeFrameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
3
+
4
+ /** Configuration for a Prisma Nuxt website. */
5
+ export interface NuxtProps extends FrameworkSiteProps {
6
+ /** Serializable overrides merged over nuxt.config.*; nitro.preset is owned by the Node target. */
7
+ nuxt?: Record<string, unknown>;
8
+ }
9
+
10
+ /**
11
+ * Nuxt SSR and prerendered assets on Prisma Compute. The Node target owns Nitro’s node preset; do not override nitro.preset.
12
+ *
13
+ * Native framework development and HMR run without Prisma cloud resources.
14
+ * Apply `Alchemy.remote()` to use the live Compute deployment during dev.
15
+ * Packaging requires the optional `@vercel/nft` peer dependency.
16
+ *
17
+ * ### Creating a Website
18
+ * **Example:** Nuxt application
19
+ * ```typescript
20
+ * const site = yield* Prisma.Website.Nuxt("Web", {
21
+ * rootDir: "./app",
22
+ * });
23
+ * ```
24
+ *
25
+ * ### Deployment Configuration
26
+ * **Example:** Existing project and custom hostname
27
+ * ```typescript
28
+ * const site = yield* Prisma.Website.Nuxt("Web", {
29
+ * project,
30
+ * domain: "www.example.com",
31
+ * env: { API_BASE: "https://api.example.com" },
32
+ * compute: { destroyOldDeployment: true },
33
+ * });
34
+ * ```
35
+ *
36
+ * @resource
37
+ * @product Website
38
+ */
39
+ export const Nuxt = (id: string, props: NuxtProps = {}) =>
40
+ makeFrameworkSite(id, props, {
41
+ framework: "@alchemy.run/frontend-frameworks/nuxt",
42
+ target: "@alchemy.run/frontend-frameworks/nuxt/node",
43
+ options: { nuxt: props.nuxt },
44
+ }).pipe(Namespace.push(id));
@@ -0,0 +1,40 @@
1
+ import * as Namespace from "../../Namespace.ts";
2
+ import { makeFrameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
3
+
4
+ /** Configuration for a Prisma Octane website. */
5
+ export interface OctaneProps extends FrameworkSiteProps {}
6
+
7
+ /**
8
+ * Octane SSR and client assets on Prisma Compute. Select node() from @alchemy.run/frontend-frameworks/octane/node-adapter in the project’s octane.config.ts.
9
+ *
10
+ * Native framework development and HMR run without Prisma cloud resources.
11
+ * Apply `Alchemy.remote()` to use the live Compute deployment during dev.
12
+ * Packaging requires the optional `@vercel/nft` peer dependency.
13
+ *
14
+ * ### Creating a Website
15
+ * **Example:** Octane application
16
+ * ```typescript
17
+ * const site = yield* Prisma.Website.Octane("Web", {
18
+ * rootDir: "./app",
19
+ * });
20
+ * ```
21
+ *
22
+ * ### Deployment Configuration
23
+ * **Example:** Existing project and custom hostname
24
+ * ```typescript
25
+ * const site = yield* Prisma.Website.Octane("Web", {
26
+ * project,
27
+ * domain: "www.example.com",
28
+ * env: { API_BASE: "https://api.example.com" },
29
+ * compute: { destroyOldDeployment: true },
30
+ * });
31
+ * ```
32
+ *
33
+ * @resource
34
+ * @product Website
35
+ */
36
+ export const Octane = (id: string, props: OctaneProps = {}) =>
37
+ makeFrameworkSite(id, props, {
38
+ framework: "@alchemy.run/frontend-frameworks/octane",
39
+ target: "@alchemy.run/frontend-frameworks/octane/node",
40
+ }).pipe(Namespace.push(id));
@@ -0,0 +1,40 @@
1
+ import * as Namespace from "../../Namespace.ts";
2
+ import { makeFrameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
3
+
4
+ /** Configuration for a Prisma ReactRouter website. */
5
+ export interface ReactRouterProps extends FrameworkSiteProps {}
6
+
7
+ /**
8
+ * React Router SSR and browser assets on Prisma Compute using the existing Node framework target.
9
+ *
10
+ * Native framework development and HMR run without Prisma cloud resources.
11
+ * Apply `Alchemy.remote()` to use the live Compute deployment during dev.
12
+ * Packaging requires the optional `@vercel/nft` peer dependency.
13
+ *
14
+ * ### Creating a Website
15
+ * **Example:** ReactRouter application
16
+ * ```typescript
17
+ * const site = yield* Prisma.Website.ReactRouter("Web", {
18
+ * rootDir: "./app",
19
+ * });
20
+ * ```
21
+ *
22
+ * ### Deployment Configuration
23
+ * **Example:** Existing project and custom hostname
24
+ * ```typescript
25
+ * const site = yield* Prisma.Website.ReactRouter("Web", {
26
+ * project,
27
+ * domain: "www.example.com",
28
+ * env: { API_BASE: "https://api.example.com" },
29
+ * compute: { destroyOldDeployment: true },
30
+ * });
31
+ * ```
32
+ *
33
+ * @resource
34
+ * @product Website
35
+ */
36
+ export const ReactRouter = (id: string, props: ReactRouterProps = {}) =>
37
+ makeFrameworkSite(id, props, {
38
+ framework: "@alchemy.run/frontend-frameworks/react-router",
39
+ target: "@alchemy.run/frontend-frameworks/react-router/node",
40
+ }).pipe(Namespace.push(id));
@@ -0,0 +1,44 @@
1
+ import * as Namespace from "../../Namespace.ts";
2
+ import { makeFrameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
3
+
4
+ /** Configuration for a Prisma SolidStart website. */
5
+ export interface SolidStartProps extends FrameworkSiteProps {
6
+ /** Serializable Nitro plugin options, including prerender and routeRules. The Node target owns preset. */
7
+ nitro?: Record<string, unknown>;
8
+ }
9
+
10
+ /**
11
+ * SolidStart SSR and prerendered assets on Prisma Compute. The integration owns the Nitro plugin; omit nitroV2Plugin() from vite.config.* and configure prerendering through nitro.
12
+ *
13
+ * Native framework development and HMR run without Prisma cloud resources.
14
+ * Apply `Alchemy.remote()` to use the live Compute deployment during dev.
15
+ * Packaging requires the optional `@vercel/nft` peer dependency.
16
+ *
17
+ * ### Creating a Website
18
+ * **Example:** SolidStart application
19
+ * ```typescript
20
+ * const site = yield* Prisma.Website.SolidStart("Web", {
21
+ * rootDir: "./app",
22
+ * });
23
+ * ```
24
+ *
25
+ * ### Deployment Configuration
26
+ * **Example:** Existing project and custom hostname
27
+ * ```typescript
28
+ * const site = yield* Prisma.Website.SolidStart("Web", {
29
+ * project,
30
+ * domain: "www.example.com",
31
+ * env: { API_BASE: "https://api.example.com" },
32
+ * compute: { destroyOldDeployment: true },
33
+ * });
34
+ * ```
35
+ *
36
+ * @resource
37
+ * @product Website
38
+ */
39
+ export const SolidStart = (id: string, props: SolidStartProps = {}) =>
40
+ makeFrameworkSite(id, props, {
41
+ framework: "@alchemy.run/frontend-frameworks/solidstart",
42
+ target: "@alchemy.run/frontend-frameworks/solidstart/node",
43
+ options: { nitro: props.nitro },
44
+ }).pipe(Namespace.push(id));
@@ -0,0 +1,149 @@
1
+ import { makeNodeServeEntrySource } from "@alchemy.run/frontend-frameworks/core";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Path from "effect/Path";
4
+ import * as Redacted from "effect/Redacted";
5
+ import { AlchemyContext } from "../../AlchemyContext.ts";
6
+ import * as Command from "../../Command/index.ts";
7
+ import * as Namespace from "../../Namespace.ts";
8
+ import * as Output from "../../Output.ts";
9
+ import { ProviderModePolicy } from "../../ProviderMode.ts";
10
+ import { initialCwd } from "../../Util/Node.ts";
11
+ import { WebsiteArtifact } from "./Artifact.ts";
12
+ import {
13
+ deployWebsite,
14
+ type FrameworkSiteProps,
15
+ type Website,
16
+ } from "./FrameworkSite.ts";
17
+
18
+ /** A command-built website with the same build vocabulary as Fly and Railway. */
19
+ export interface StaticSiteProps
20
+ extends
21
+ Omit<Command.BuildProps, "env">,
22
+ Omit<FrameworkSiteProps, "dev" | "memo"> {
23
+ /** Local command; skips the production build. Without a command, a local static server serves the built output. */
24
+ dev?: {
25
+ /** Shell command that starts the native dev server. */
26
+ command: string;
27
+ /** Dev command directory; defaults to cwd or rootDir. */
28
+ cwd?: string;
29
+ /** Additional development environment variables. */
30
+ env?: Record<string, string | Redacted.Redacted<string>>;
31
+ /** Explicit dev URL when the command does not print one. */
32
+ url?: string;
33
+ };
34
+ /** Return index.html on unmatched paths. Mutually exclusive with errorPage. */
35
+ spa?: boolean;
36
+ /** HTML file returned with HTTP 404; relative to outdir. Mutually exclusive with spa. */
37
+ errorPage?: string;
38
+ }
39
+
40
+ const quote = (value: string) => `'${value.replaceAll("'", "'\\''")}'`;
41
+
42
+ /**
43
+ * Build a static website with a shell command and serve it on Prisma Compute.
44
+ * Only the output directory is packaged; the repository is never uploaded.
45
+ * Native development declares no Prisma Project, Compute, or custom domain.
46
+ * `Alchemy.remote()` opts into the live deployment during development.
47
+ *
48
+ * ### Creating a Static Website
49
+ * **Example:** Hugo website
50
+ * ```typescript
51
+ * const site = yield* Prisma.Website.StaticSite("Blog", {
52
+ * command: "hugo --minify",
53
+ * outdir: "public",
54
+ * });
55
+ * ```
56
+ *
57
+ * ### Monorepos and Development
58
+ * **Example:** A custom frontend build
59
+ * ```typescript
60
+ * const site = yield* Prisma.Website.StaticSite("Web", {
61
+ * cwd: "apps/web",
62
+ * command: "npm run build",
63
+ * outdir: "dist",
64
+ * spa: true,
65
+ * dev: { command: "npm run dev" },
66
+ * });
67
+ * ```
68
+ *
69
+ * @resource
70
+ * @product Website
71
+ */
72
+ export const StaticSite = (id: string, props: StaticSiteProps) =>
73
+ Effect.gen(function* () {
74
+ const context = yield* AlchemyContext;
75
+ const remote = yield* ProviderModePolicy;
76
+ const local = context.dev && remote !== true;
77
+ const cwd = props.cwd ?? props.rootDir;
78
+ if (local && props.dev !== undefined) {
79
+ const dev = yield* Command.Dev("Dev", {
80
+ command: props.dev.command,
81
+ cwd: props.dev.cwd ?? cwd,
82
+ env: { ...props.env, ...props.dev.env },
83
+ });
84
+ return {
85
+ url: props.dev.url ?? dev.url,
86
+ compute: undefined,
87
+ project: undefined,
88
+ domain: undefined,
89
+ } satisfies Website;
90
+ }
91
+ if (props.spa && props.errorPage !== undefined) {
92
+ return yield* Effect.die(
93
+ new Error("StaticSite spa and errorPage are mutually exclusive."),
94
+ );
95
+ }
96
+ const build = yield* Command.Build("Build", {
97
+ command: props.command,
98
+ cwd,
99
+ env: props.env,
100
+ outdir: props.outdir,
101
+ memo: props.memo,
102
+ shell: props.shell,
103
+ timeout: props.timeout,
104
+ });
105
+ const handling = props.assets?.notFoundHandling;
106
+ const options = {
107
+ notFoundHandling:
108
+ props.errorPage !== undefined
109
+ ? ("404-page" as const)
110
+ : props.spa
111
+ ? ("spa" as const)
112
+ : handling === "single-page-application"
113
+ ? ("spa" as const)
114
+ : (handling ?? ("none" as const)),
115
+ htmlHandling: props.assets?.htmlHandling,
116
+ errorPage: props.errorPage,
117
+ };
118
+ if (local) {
119
+ const path = yield* Path.Path;
120
+ const runtime = yield* Effect.sync(() => process.execPath);
121
+ const command = Output.map(build.outdir, (outdir) => {
122
+ const source = makeNodeServeEntrySource({
123
+ ...options,
124
+ clientDirExpression: JSON.stringify(path.resolve(initialCwd, outdir)),
125
+ printUrl: true,
126
+ });
127
+ return `${quote(runtime)} --eval ${quote(source)}`;
128
+ });
129
+ const dev = yield* Command.Dev("Dev", {
130
+ command,
131
+ cwd,
132
+ shell: true,
133
+ env: { ...props.env, HOST: "127.0.0.1", PORT: "0" },
134
+ });
135
+ return {
136
+ url: dev.url,
137
+ compute: undefined,
138
+ project: undefined,
139
+ domain: undefined,
140
+ } satisfies Website;
141
+ }
142
+ const artifact = yield* WebsiteArtifact("Artifact", {
143
+ root: cwd ?? ".",
144
+ distDir: build.outdir,
145
+ buildHash: build.hash.output,
146
+ static: options,
147
+ });
148
+ return yield* deployWebsite(props, artifact);
149
+ }).pipe(Namespace.push(id));
@@ -0,0 +1,44 @@
1
+ import * as Namespace from "../../Namespace.ts";
2
+ import { makeFrameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
3
+
4
+ /** Configuration for a Prisma SvelteKit website. */
5
+ export interface SvelteKitProps extends FrameworkSiteProps {
6
+ /** Serializable SvelteKit v3 plugin configuration. The Node target owns adapter. */
7
+ kit?: Record<string, unknown>;
8
+ }
9
+
10
+ /**
11
+ * SvelteKit SSR and prerendered assets on Prisma Compute. The Node target injects the adapter. For Kit v3, pass configuration through kit rather than a svelte.config.js file.
12
+ *
13
+ * Native framework development and HMR run without Prisma cloud resources.
14
+ * Apply `Alchemy.remote()` to use the live Compute deployment during dev.
15
+ * Packaging requires the optional `@vercel/nft` peer dependency.
16
+ *
17
+ * ### Creating a Website
18
+ * **Example:** SvelteKit application
19
+ * ```typescript
20
+ * const site = yield* Prisma.Website.SvelteKit("Web", {
21
+ * rootDir: "./app",
22
+ * });
23
+ * ```
24
+ *
25
+ * ### Deployment Configuration
26
+ * **Example:** Existing project and custom hostname
27
+ * ```typescript
28
+ * const site = yield* Prisma.Website.SvelteKit("Web", {
29
+ * project,
30
+ * domain: "www.example.com",
31
+ * env: { API_BASE: "https://api.example.com" },
32
+ * compute: { destroyOldDeployment: true },
33
+ * });
34
+ * ```
35
+ *
36
+ * @resource
37
+ * @product Website
38
+ */
39
+ export const SvelteKit = (id: string, props: SvelteKitProps = {}) =>
40
+ makeFrameworkSite(id, props, {
41
+ framework: "@alchemy.run/frontend-frameworks/sveltekit",
42
+ target: "@alchemy.run/frontend-frameworks/sveltekit/node",
43
+ options: { kit: props.kit },
44
+ }).pipe(Namespace.push(id));
@@ -0,0 +1,40 @@
1
+ import * as Namespace from "../../Namespace.ts";
2
+ import { makeFrameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
3
+
4
+ /** Configuration for a Prisma TanStackStart website. */
5
+ export interface TanStackStartProps extends FrameworkSiteProps {}
6
+
7
+ /**
8
+ * TanStack Start SSR and browser assets on Prisma Compute using the existing Node framework target.
9
+ *
10
+ * Native framework development and HMR run without Prisma cloud resources.
11
+ * Apply `Alchemy.remote()` to use the live Compute deployment during dev.
12
+ * Packaging requires the optional `@vercel/nft` peer dependency.
13
+ *
14
+ * ### Creating a Website
15
+ * **Example:** TanStackStart application
16
+ * ```typescript
17
+ * const site = yield* Prisma.Website.TanStackStart("Web", {
18
+ * rootDir: "./app",
19
+ * });
20
+ * ```
21
+ *
22
+ * ### Deployment Configuration
23
+ * **Example:** Existing project and custom hostname
24
+ * ```typescript
25
+ * const site = yield* Prisma.Website.TanStackStart("Web", {
26
+ * project,
27
+ * domain: "www.example.com",
28
+ * env: { API_BASE: "https://api.example.com" },
29
+ * compute: { destroyOldDeployment: true },
30
+ * });
31
+ * ```
32
+ *
33
+ * @resource
34
+ * @product Website
35
+ */
36
+ export const TanStackStart = (id: string, props: TanStackStartProps = {}) =>
37
+ makeFrameworkSite(id, props, {
38
+ framework: "@alchemy.run/frontend-frameworks/tanstack-start",
39
+ target: "@alchemy.run/frontend-frameworks/tanstack-start/node",
40
+ }).pipe(Namespace.push(id));