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.
- package/bin/cli.js +25 -65
- package/bin/exec.js +1 -1
- package/bin/tsconfig.json +5 -0
- package/lib/Cloudflare/Workers/InferEnv.d.ts +3 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +5 -2
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Prisma/Providers.d.ts +4 -1
- package/lib/Prisma/Providers.d.ts.map +1 -1
- package/lib/Prisma/Providers.js +7 -2
- package/lib/Prisma/Providers.js.map +1 -1
- package/lib/Prisma/Website/Artifact.d.ts +52 -0
- package/lib/Prisma/Website/Artifact.d.ts.map +1 -0
- package/lib/Prisma/Website/Artifact.js +285 -0
- package/lib/Prisma/Website/Artifact.js.map +1 -0
- package/lib/Prisma/Website/Astro.d.ts +62 -0
- package/lib/Prisma/Website/Astro.d.ts.map +1 -0
- package/lib/Prisma/Website/Astro.js +50 -0
- package/lib/Prisma/Website/Astro.js.map +1 -0
- package/lib/Prisma/Website/Foldkit.d.ts +30 -0
- package/lib/Prisma/Website/Foldkit.d.ts.map +1 -0
- package/lib/Prisma/Website/Foldkit.js +30 -0
- package/lib/Prisma/Website/Foldkit.js.map +1 -0
- package/lib/Prisma/Website/FrameworkSite.d.ts +82 -0
- package/lib/Prisma/Website/FrameworkSite.d.ts.map +1 -0
- package/lib/Prisma/Website/FrameworkSite.js +96 -0
- package/lib/Prisma/Website/FrameworkSite.js.map +1 -0
- package/lib/Prisma/Website/Nextjs.d.ts +35 -0
- package/lib/Prisma/Website/Nextjs.d.ts.map +1 -0
- package/lib/Prisma/Website/Nextjs.js +37 -0
- package/lib/Prisma/Website/Nextjs.js.map +1 -0
- package/lib/Prisma/Website/Nuxt.d.ts +37 -0
- package/lib/Prisma/Website/Nuxt.d.ts.map +1 -0
- package/lib/Prisma/Website/Nuxt.js +37 -0
- package/lib/Prisma/Website/Nuxt.js.map +1 -0
- package/lib/Prisma/Website/Octane.d.ts +35 -0
- package/lib/Prisma/Website/Octane.d.ts.map +1 -0
- package/lib/Prisma/Website/Octane.js +36 -0
- package/lib/Prisma/Website/Octane.js.map +1 -0
- package/lib/Prisma/Website/ReactRouter.d.ts +35 -0
- package/lib/Prisma/Website/ReactRouter.d.ts.map +1 -0
- package/lib/Prisma/Website/ReactRouter.js +36 -0
- package/lib/Prisma/Website/ReactRouter.js.map +1 -0
- package/lib/Prisma/Website/SolidStart.d.ts +37 -0
- package/lib/Prisma/Website/SolidStart.d.ts.map +1 -0
- package/lib/Prisma/Website/SolidStart.js +37 -0
- package/lib/Prisma/Website/SolidStart.js.map +1 -0
- package/lib/Prisma/Website/StaticSite.d.ts +57 -0
- package/lib/Prisma/Website/StaticSite.d.ts.map +1 -0
- package/lib/Prisma/Website/StaticSite.js +118 -0
- package/lib/Prisma/Website/StaticSite.js.map +1 -0
- package/lib/Prisma/Website/SvelteKit.d.ts +37 -0
- package/lib/Prisma/Website/SvelteKit.d.ts.map +1 -0
- package/lib/Prisma/Website/SvelteKit.js +37 -0
- package/lib/Prisma/Website/SvelteKit.js.map +1 -0
- package/lib/Prisma/Website/TanStackStart.d.ts +35 -0
- package/lib/Prisma/Website/TanStackStart.d.ts.map +1 -0
- package/lib/Prisma/Website/TanStackStart.js +36 -0
- package/lib/Prisma/Website/TanStackStart.js.map +1 -0
- package/lib/Prisma/Website/Vite.d.ts +42 -0
- package/lib/Prisma/Website/Vite.d.ts.map +1 -0
- package/lib/Prisma/Website/Vite.js +38 -0
- package/lib/Prisma/Website/Vite.js.map +1 -0
- package/lib/Prisma/Website/Vocs.d.ts +37 -0
- package/lib/Prisma/Website/Vocs.d.ts.map +1 -0
- package/lib/Prisma/Website/Vocs.js +38 -0
- package/lib/Prisma/Website/Vocs.js.map +1 -0
- package/lib/Prisma/Website/Waku.d.ts +44 -0
- package/lib/Prisma/Website/Waku.d.ts.map +1 -0
- package/lib/Prisma/Website/Waku.js +38 -0
- package/lib/Prisma/Website/Waku.js.map +1 -0
- package/lib/Prisma/Website/index.d.ts +15 -0
- package/lib/Prisma/Website/index.d.ts.map +1 -0
- package/lib/Prisma/Website/index.js +14 -0
- package/lib/Prisma/Website/index.js.map +1 -0
- package/lib/Prisma/index.d.ts +1 -0
- package/lib/Prisma/index.d.ts.map +1 -1
- package/lib/Prisma/index.js +1 -0
- package/lib/Prisma/index.js.map +1 -1
- package/lib/State/HttpStateApi.d.ts +11 -11
- package/lib/Website/Server.d.ts.map +1 -1
- package/lib/Website/Server.js +18 -8
- package/lib/Website/Server.js.map +1 -1
- package/package.json +6 -6
- package/src/Cloudflare/Workers/InferEnv.ts +5 -3
- package/src/Cloudflare/Workers/Worker.ts +25 -5
- package/src/Prisma/Providers.ts +11 -0
- package/src/Prisma/Website/Artifact.ts +429 -0
- package/src/Prisma/Website/Astro.ts +72 -0
- package/src/Prisma/Website/Foldkit.ts +34 -0
- package/src/Prisma/Website/FrameworkSite.ts +204 -0
- package/src/Prisma/Website/Nextjs.ts +41 -0
- package/src/Prisma/Website/Nuxt.ts +44 -0
- package/src/Prisma/Website/Octane.ts +40 -0
- package/src/Prisma/Website/ReactRouter.ts +40 -0
- package/src/Prisma/Website/SolidStart.ts +44 -0
- package/src/Prisma/Website/StaticSite.ts +149 -0
- package/src/Prisma/Website/SvelteKit.ts +44 -0
- package/src/Prisma/Website/TanStackStart.ts +40 -0
- package/src/Prisma/Website/Vite.ts +50 -0
- package/src/Prisma/Website/Vocs.ts +45 -0
- package/src/Prisma/Website/Waku.ts +52 -0
- package/src/Prisma/Website/index.ts +19 -0
- package/src/Prisma/index.ts +1 -0
- 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));
|