create-basalt 1.10.0 → 1.12.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.
- package/README.md +64 -26
- package/dist/args.d.ts +1 -1
- package/dist/args.js +5 -2
- package/dist/bin-template.d.ts +13 -8
- package/dist/bin-template.js +178 -13
- package/dist/cli.js +6 -2
- package/dist/dev-entry.d.ts +23 -0
- package/dist/dev-entry.js +49 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +23 -2
- package/dist/latest-versions.js +1 -0
- package/dist/project/doctor.d.ts +11 -1
- package/dist/project/doctor.js +176 -14
- package/dist/project/production.d.ts +32 -0
- package/dist/project/production.js +74 -0
- package/dist/project/run.js +8 -4
- package/dist/project/seed-script.d.ts +18 -0
- package/dist/project/seed-script.js +32 -0
- package/dist/project/update.js +53 -11
- package/dist/stubs.d.ts +30 -0
- package/dist/stubs.js +123 -0
- package/dist/templates.d.ts +53 -7
- package/dist/templates.js +183 -55
- package/dist/versions.js +13 -13
- package/dist/wizard.js +3 -3
- package/package.json +20 -17
package/dist/project/update.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { binStatus,
|
|
3
|
+
import { binStatus, hasProjectCommands, manualBinSnippet, patchBasaltBin } from '../bin-template.js';
|
|
4
|
+
import { devEntryStatus, MANUAL_DEV_SNIPPET, patchDevEntry, patchEnvExample } from '../dev-entry.js';
|
|
4
5
|
import { alwaysLatest, lookupLatestVersions, minimumReleaseAgeMinutes, } from '../latest-versions.js';
|
|
5
6
|
import { BASALT_PROJECT_SCRIPT } from '../templates.js';
|
|
7
|
+
import { planProductionPath } from './production.js';
|
|
8
|
+
import { legacySeedScriptFix } from './seed-script.js';
|
|
6
9
|
import { extendManifest, MANIFEST_PATH, serializeManifest } from './manifest.js';
|
|
7
10
|
import { DEPENDENCY_SECTIONS, mergePackageJson, setDependencyRange, } from './package-json.js';
|
|
8
11
|
import { table } from './term.js';
|
|
@@ -194,22 +197,61 @@ export async function planUpdate(ctx, options = {}) {
|
|
|
194
197
|
}
|
|
195
198
|
}
|
|
196
199
|
}
|
|
197
|
-
//
|
|
200
|
+
// Template files from an earlier release: bring them to the current
|
|
201
|
+
// templates when untouched (known hash or the manifest's), else print the
|
|
202
|
+
// snippet. Patched files get their manifest hash refreshed.
|
|
203
|
+
const patched = {};
|
|
198
204
|
const bin = await readOptional(join(ctx.dir, 'bin', 'basalt.ts'));
|
|
199
205
|
const status = binStatus(bin, ctx.manifest?.files['bin/basalt.ts']);
|
|
200
206
|
if (status === 'patchable' && bin !== undefined) {
|
|
201
207
|
const after = patchBasaltBin(bin);
|
|
202
208
|
files['bin/basalt.ts'] = { before: bin, after };
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
patched['bin/basalt.ts'] = after;
|
|
210
|
+
toolingNotes.push(`bin/basalt.ts: unmodified template from an earlier release — ${hasProjectCommands(bin) ? '' : 'gains update/add/doctor/info; '}loads .env for development, runs \`upgrade\` without booting the app, explains env errors`);
|
|
211
|
+
}
|
|
212
|
+
else if (status === 'modified' && bin !== undefined) {
|
|
213
|
+
manual.push(`bin/basalt.ts was customised, so it was not patched. To bring it up to date:\n${manualBinSnippet(bin)}`);
|
|
214
|
+
}
|
|
215
|
+
const dev = await readOptional(join(ctx.dir, 'src', 'dev.ts'));
|
|
216
|
+
const devStatus = devEntryStatus(dev, ctx.manifest?.files['src/dev.ts']);
|
|
217
|
+
if (devStatus === 'patchable' && dev !== undefined) {
|
|
218
|
+
const after = patchDevEntry();
|
|
219
|
+
files['src/dev.ts'] = { before: dev, after };
|
|
220
|
+
patched['src/dev.ts'] = after;
|
|
221
|
+
toolingNotes.push('src/dev.ts: unmodified template from an earlier release — `dev` loads .env (exported variables still win)');
|
|
222
|
+
}
|
|
223
|
+
else if (devStatus === 'modified') {
|
|
224
|
+
manual.push(`src/dev.ts was customised, so it was not patched. To load .env in development:\n${MANUAL_DEV_SNIPPET}`);
|
|
225
|
+
}
|
|
226
|
+
const example = await readOptional(join(ctx.dir, '.env.example'));
|
|
227
|
+
const exampleAfter = example === undefined ? undefined : patchEnvExample(example);
|
|
228
|
+
if (example !== undefined && exampleAfter !== undefined) {
|
|
229
|
+
files['.env.example'] = { before: example, after: exampleAfter };
|
|
230
|
+
patched['.env.example'] = exampleAfter;
|
|
231
|
+
toolingNotes.push('.env.example: header now says dev/CLI load .env automatically and `start` does not');
|
|
232
|
+
}
|
|
233
|
+
// The production path (BK-026): tsconfig.build.json, a `build` script, the
|
|
234
|
+
// Dockerfile — offered when missing, never overwriting what the app has.
|
|
235
|
+
const production = await planProductionPath(ctx.dir, files['package.json']?.after ?? ctx.packageJsonText, ctx.pm);
|
|
236
|
+
if (production.packageJsonText !== (files['package.json']?.after ?? ctx.packageJsonText)) {
|
|
237
|
+
files['package.json'] = { before: ctx.packageJsonText, after: production.packageJsonText };
|
|
238
|
+
}
|
|
239
|
+
for (const [path, content] of Object.entries(production.files)) {
|
|
240
|
+
files[path] = { before: undefined, after: content };
|
|
241
|
+
patched[path] = content;
|
|
210
242
|
}
|
|
211
|
-
|
|
212
|
-
|
|
243
|
+
toolingNotes.push(...production.notes);
|
|
244
|
+
manual.push(...production.manual);
|
|
245
|
+
// db:seed from create-basalt 1.8–1.11 does not load .env: printed, never
|
|
246
|
+
// rewritten — package.json scripts are the app's.
|
|
247
|
+
const seedFix = legacySeedScriptFix(ctx.packageJson, await readOptional(join(ctx.dir, 'prisma.config.ts')));
|
|
248
|
+
if (seedFix !== undefined)
|
|
249
|
+
manual.push(seedFix);
|
|
250
|
+
if (ctx.manifest && Object.keys(patched).length > 0) {
|
|
251
|
+
files[MANIFEST_PATH] = {
|
|
252
|
+
before: serializeManifest(ctx.manifest),
|
|
253
|
+
after: serializeManifest(extendManifest(ctx.manifest, ctx.options, patched)),
|
|
254
|
+
};
|
|
213
255
|
}
|
|
214
256
|
}
|
|
215
257
|
// Peer ranges of the framework versions we end up on vs the app's resulting ranges.
|
package/dist/stubs.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The production stubs `basalt publish` copies into an app — the SINGLE source
|
|
3
|
+
* of truth. create-basalt ships the same files in every new scaffold and offers
|
|
4
|
+
* them from `create-basalt update`: its build copies this file verbatim to
|
|
5
|
+
* `packages/create-app/src/stubs.ts` (scripts/sync-stubs.mjs), and a test there
|
|
6
|
+
* fails if the copy drifts. Keep this module free of imports for that reason.
|
|
7
|
+
*
|
|
8
|
+
* The layout these stubs assume is the create-basalt scaffold's (BK-026):
|
|
9
|
+
* `pnpm build` runs `tsc -p tsconfig.build.json` (rootDir `.`, outDir `dist`),
|
|
10
|
+
* so `src/server.ts` compiles to {@link PRODUCTION_ENTRY}; `pnpm start` runs it
|
|
11
|
+
* with plain `node` — no tsx, no TypeScript at runtime. A Prisma client, when
|
|
12
|
+
* there is one, is generated OUTSIDE `src/` (`generated/prisma`) and imported
|
|
13
|
+
* through the package.json `imports` alias `#db/*`, so it resolves the same
|
|
14
|
+
* from `src/` (tsx) and from `dist/src/` (node).
|
|
15
|
+
*/
|
|
16
|
+
/** The compiled server entry the Dockerfile runs and the scaffold's `start` script points at. */
|
|
17
|
+
export declare const PRODUCTION_ENTRY = "dist/src/server.js";
|
|
18
|
+
/** Multi-stage production image: build with the dev toolchain, run on plain node as a non-root user. */
|
|
19
|
+
export declare const DOCKERFILE = "# syntax=docker/dockerfile:1\n# Production image for a Basalt app (the create-basalt layout): `pnpm build`\n# compiles src/ to dist/ and the image runs dist/src/server.js on plain\n# node \u2014 no tsx, no TypeScript at runtime.\n#\n# docker build -t my-app .\n# docker run -p 3000:3000 -e APP_SECRET=\u2026 -e DATABASE_URL=\u2026 my-app\n#\n# Configuration comes from the environment (nothing loads .env here, and\n# .dockerignore keeps it out of the image). Database migrations are NOT run\n# by the image: apply them before rolling out (`pnpm db:deploy` in CI).\n#\n# Installs with pnpm from pnpm-lock.yaml. An app on npm/yarn/bun replaces the\n# pnpm install / exec / run / prune lines with its own package manager's.\nARG NODE_VERSION=22\nARG PNPM_VERSION=11\n\nFROM node:${NODE_VERSION}-slim AS build\nARG PNPM_VERSION\n# Non-interactive pnpm: without it `pnpm prune` in a workspace (a --ui app's\n# web/) aborts with ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY.\nENV CI=true\nWORKDIR /app\nRUN npm install -g pnpm@${PNPM_VERSION}\nCOPY . .\n# Full install: the build needs the devDependencies (typescript, prisma).\nRUN pnpm install --frozen-lockfile\n# The Prisma client (when the app has a schema) is generated into ./generated.\nRUN if [ -f prisma/schema.prisma ]; then pnpm exec prisma generate; fi && mkdir -p generated\nRUN pnpm run build\n# Drop the devDependencies (tsx, typescript, prisma CLI, generators, the AI\n# bridge): none of them may ship. --ignore-scripts keeps the app's postinstall\n# (`prisma generate`, a dev tool) from running again.\nRUN pnpm prune --prod --ignore-scripts\n\nFROM node:${NODE_VERSION}-slim AS run\nENV NODE_ENV=production\nENV PORT=3000\n# Path the HEALTHCHECK probes: the scaffold's /health route by default; set\n# /readyz when the app registers healthPlugin().\nENV HEALTHCHECK_PATH=/health\nWORKDIR /app\nCOPY --from=build --chown=node:node /app/package.json ./package.json\nCOPY --from=build --chown=node:node /app/node_modules ./node_modules\nCOPY --from=build --chown=node:node /app/generated ./generated\nCOPY --from=build --chown=node:node /app/dist ./dist\nUSER node\nEXPOSE 3000\nHEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \\\n CMD node -e \"fetch('http://127.0.0.1:' + (process.env.PORT || 3000) + process.env.HEALTHCHECK_PATH).then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1))\"\nCMD [\"node\", \"--enable-source-maps\", \"dist/src/server.js\"]\n";
|
|
20
|
+
/**
|
|
21
|
+
* Published with the Dockerfile: its \`COPY . .\` would otherwise bake \`.env\`,
|
|
22
|
+
* private keys and VCS metadata into an image layer. Every secret rule is
|
|
23
|
+
* \`**\/\`-prefixed: .dockerignore patterns are anchored at the context root, so
|
|
24
|
+
* a bare \`.env\` or \`*.pem\` would still let \`prisma/.env\` or
|
|
25
|
+
* \`certs/server.key\` through. \`dist\` is rebuilt inside the image.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DOCKERIGNORE = "**/.env\n**/.env.*\n!**/.env.example\n**/.npmrc\n**/.git\n**/node_modules\n**/coverage\n**/*.log\n**/*.pem\n**/*.key\n**/*.p12\n**/*.pfx\n**/.DS_Store\ndist\n";
|
|
28
|
+
/** GitHub Actions CI: install, typecheck, build (the production path), test. */
|
|
29
|
+
export declare const CI_WORKFLOW = "name: ci\non:\n push: { branches: [main] }\n pull_request:\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n # Drop `with: version` if package.json declares a packageManager.\n - uses: pnpm/action-setup@v4\n with: { version: 11 }\n - uses: actions/setup-node@v4\n with: { node-version: 22, cache: pnpm }\n - run: pnpm install --frozen-lockfile\n - run: pnpm run typecheck\n - run: pnpm run build\n - run: pnpm run test\n";
|
|
30
|
+
export declare const EDITORCONFIG = "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\n";
|
package/dist/stubs.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// GENERATED by scripts/sync-stubs.mjs from packages/cli/src/stubs.ts (runs before every build) — do not edit.
|
|
2
|
+
/**
|
|
3
|
+
* The production stubs `basalt publish` copies into an app — the SINGLE source
|
|
4
|
+
* of truth. create-basalt ships the same files in every new scaffold and offers
|
|
5
|
+
* them from `create-basalt update`: its build copies this file verbatim to
|
|
6
|
+
* `packages/create-app/src/stubs.ts` (scripts/sync-stubs.mjs), and a test there
|
|
7
|
+
* fails if the copy drifts. Keep this module free of imports for that reason.
|
|
8
|
+
*
|
|
9
|
+
* The layout these stubs assume is the create-basalt scaffold's (BK-026):
|
|
10
|
+
* `pnpm build` runs `tsc -p tsconfig.build.json` (rootDir `.`, outDir `dist`),
|
|
11
|
+
* so `src/server.ts` compiles to {@link PRODUCTION_ENTRY}; `pnpm start` runs it
|
|
12
|
+
* with plain `node` — no tsx, no TypeScript at runtime. A Prisma client, when
|
|
13
|
+
* there is one, is generated OUTSIDE `src/` (`generated/prisma`) and imported
|
|
14
|
+
* through the package.json `imports` alias `#db/*`, so it resolves the same
|
|
15
|
+
* from `src/` (tsx) and from `dist/src/` (node).
|
|
16
|
+
*/
|
|
17
|
+
/** The compiled server entry the Dockerfile runs and the scaffold's `start` script points at. */
|
|
18
|
+
export const PRODUCTION_ENTRY = 'dist/src/server.js';
|
|
19
|
+
/** Multi-stage production image: build with the dev toolchain, run on plain node as a non-root user. */
|
|
20
|
+
export const DOCKERFILE = `# syntax=docker/dockerfile:1
|
|
21
|
+
# Production image for a Basalt app (the create-basalt layout): \`pnpm build\`
|
|
22
|
+
# compiles src/ to dist/ and the image runs ${PRODUCTION_ENTRY} on plain
|
|
23
|
+
# node — no tsx, no TypeScript at runtime.
|
|
24
|
+
#
|
|
25
|
+
# docker build -t my-app .
|
|
26
|
+
# docker run -p 3000:3000 -e APP_SECRET=… -e DATABASE_URL=… my-app
|
|
27
|
+
#
|
|
28
|
+
# Configuration comes from the environment (nothing loads .env here, and
|
|
29
|
+
# .dockerignore keeps it out of the image). Database migrations are NOT run
|
|
30
|
+
# by the image: apply them before rolling out (\`pnpm db:deploy\` in CI).
|
|
31
|
+
#
|
|
32
|
+
# Installs with pnpm from pnpm-lock.yaml. An app on npm/yarn/bun replaces the
|
|
33
|
+
# pnpm install / exec / run / prune lines with its own package manager's.
|
|
34
|
+
ARG NODE_VERSION=22
|
|
35
|
+
ARG PNPM_VERSION=11
|
|
36
|
+
|
|
37
|
+
FROM node:\${NODE_VERSION}-slim AS build
|
|
38
|
+
ARG PNPM_VERSION
|
|
39
|
+
# Non-interactive pnpm: without it \`pnpm prune\` in a workspace (a --ui app's
|
|
40
|
+
# web/) aborts with ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY.
|
|
41
|
+
ENV CI=true
|
|
42
|
+
WORKDIR /app
|
|
43
|
+
RUN npm install -g pnpm@\${PNPM_VERSION}
|
|
44
|
+
COPY . .
|
|
45
|
+
# Full install: the build needs the devDependencies (typescript, prisma).
|
|
46
|
+
RUN pnpm install --frozen-lockfile
|
|
47
|
+
# The Prisma client (when the app has a schema) is generated into ./generated.
|
|
48
|
+
RUN if [ -f prisma/schema.prisma ]; then pnpm exec prisma generate; fi && mkdir -p generated
|
|
49
|
+
RUN pnpm run build
|
|
50
|
+
# Drop the devDependencies (tsx, typescript, prisma CLI, generators, the AI
|
|
51
|
+
# bridge): none of them may ship. --ignore-scripts keeps the app's postinstall
|
|
52
|
+
# (\`prisma generate\`, a dev tool) from running again.
|
|
53
|
+
RUN pnpm prune --prod --ignore-scripts
|
|
54
|
+
|
|
55
|
+
FROM node:\${NODE_VERSION}-slim AS run
|
|
56
|
+
ENV NODE_ENV=production
|
|
57
|
+
ENV PORT=3000
|
|
58
|
+
# Path the HEALTHCHECK probes: the scaffold's /health route by default; set
|
|
59
|
+
# /readyz when the app registers healthPlugin().
|
|
60
|
+
ENV HEALTHCHECK_PATH=/health
|
|
61
|
+
WORKDIR /app
|
|
62
|
+
COPY --from=build --chown=node:node /app/package.json ./package.json
|
|
63
|
+
COPY --from=build --chown=node:node /app/node_modules ./node_modules
|
|
64
|
+
COPY --from=build --chown=node:node /app/generated ./generated
|
|
65
|
+
COPY --from=build --chown=node:node /app/dist ./dist
|
|
66
|
+
USER node
|
|
67
|
+
EXPOSE 3000
|
|
68
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \\
|
|
69
|
+
CMD node -e "fetch('http://127.0.0.1:' + (process.env.PORT || 3000) + process.env.HEALTHCHECK_PATH).then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1))"
|
|
70
|
+
CMD ["node", "--enable-source-maps", "${PRODUCTION_ENTRY}"]
|
|
71
|
+
`;
|
|
72
|
+
/**
|
|
73
|
+
* Published with the Dockerfile: its \`COPY . .\` would otherwise bake \`.env\`,
|
|
74
|
+
* private keys and VCS metadata into an image layer. Every secret rule is
|
|
75
|
+
* \`**\/\`-prefixed: .dockerignore patterns are anchored at the context root, so
|
|
76
|
+
* a bare \`.env\` or \`*.pem\` would still let \`prisma/.env\` or
|
|
77
|
+
* \`certs/server.key\` through. \`dist\` is rebuilt inside the image.
|
|
78
|
+
*/
|
|
79
|
+
export const DOCKERIGNORE = `**/.env
|
|
80
|
+
**/.env.*
|
|
81
|
+
!**/.env.example
|
|
82
|
+
**/.npmrc
|
|
83
|
+
**/.git
|
|
84
|
+
**/node_modules
|
|
85
|
+
**/coverage
|
|
86
|
+
**/*.log
|
|
87
|
+
**/*.pem
|
|
88
|
+
**/*.key
|
|
89
|
+
**/*.p12
|
|
90
|
+
**/*.pfx
|
|
91
|
+
**/.DS_Store
|
|
92
|
+
dist
|
|
93
|
+
`;
|
|
94
|
+
/** GitHub Actions CI: install, typecheck, build (the production path), test. */
|
|
95
|
+
export const CI_WORKFLOW = `name: ci
|
|
96
|
+
on:
|
|
97
|
+
push: { branches: [main] }
|
|
98
|
+
pull_request:
|
|
99
|
+
jobs:
|
|
100
|
+
build:
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
steps:
|
|
103
|
+
- uses: actions/checkout@v4
|
|
104
|
+
# Drop \`with: version\` if package.json declares a packageManager.
|
|
105
|
+
- uses: pnpm/action-setup@v4
|
|
106
|
+
with: { version: 11 }
|
|
107
|
+
- uses: actions/setup-node@v4
|
|
108
|
+
with: { node-version: 22, cache: pnpm }
|
|
109
|
+
- run: pnpm install --frozen-lockfile
|
|
110
|
+
- run: pnpm run typecheck
|
|
111
|
+
- run: pnpm run build
|
|
112
|
+
- run: pnpm run test
|
|
113
|
+
`;
|
|
114
|
+
export const EDITORCONFIG = `root = true
|
|
115
|
+
|
|
116
|
+
[*]
|
|
117
|
+
charset = utf-8
|
|
118
|
+
end_of_line = lf
|
|
119
|
+
insert_final_newline = true
|
|
120
|
+
indent_style = space
|
|
121
|
+
indent_size = 2
|
|
122
|
+
trim_trailing_whitespace = true
|
|
123
|
+
`;
|
package/dist/templates.d.ts
CHANGED
|
@@ -33,6 +33,24 @@ export declare const versionOf: (pkg: string) => string;
|
|
|
33
33
|
* unknown package so every emitted range lives in that single table.
|
|
34
34
|
*/
|
|
35
35
|
export declare const thirdPartyVersionOf: (pkg: string) => string;
|
|
36
|
+
/**
|
|
37
|
+
* The production path (BK-026): `build` compiles src/ with tsconfig.build.json
|
|
38
|
+
* (rootDir `.`, outDir `dist`) and `start` runs the result on plain node — the
|
|
39
|
+
* same entry the Dockerfile's CMD runs. `start:dev` keeps the old tsx start.
|
|
40
|
+
*/
|
|
41
|
+
export declare const BUILD_SCRIPT = "tsc -p tsconfig.build.json";
|
|
42
|
+
/** The `db:seed` script of a `--prisma` scaffold with tenancy (prisma.config.ts loads .env, then runs `migrations.seed`). */
|
|
43
|
+
export declare const DB_SEED_SCRIPT = "prisma db seed";
|
|
44
|
+
export declare const START_SCRIPT = "node --enable-source-maps dist/src/server.js";
|
|
45
|
+
export declare const START_DEV_SCRIPT = "tsx src/server.ts";
|
|
46
|
+
/** The `start` script every create-basalt release before the production path wrote. */
|
|
47
|
+
export declare const LEGACY_START_SCRIPT = "tsx src/server.ts";
|
|
48
|
+
/**
|
|
49
|
+
* package.json `imports` alias for the generated Prisma client. It lives in
|
|
50
|
+
* ./generated/prisma — outside src/, so tsc never has to copy its .js files —
|
|
51
|
+
* and `#db/*` resolves to it from src/ (tsx, vitest) and dist/src/ (node) alike.
|
|
52
|
+
*/
|
|
53
|
+
export declare const PRISMA_IMPORTS: Readonly<Record<string, string>>;
|
|
36
54
|
/** The root `basalt` script of an app without `--cli`: create-basalt's project commands. */
|
|
37
55
|
export declare const BASALT_PROJECT_SCRIPT = "create-basalt --project";
|
|
38
56
|
/** The root `dev:web` script of a `--ui` app (web/ is a pnpm workspace member). */
|
|
@@ -41,6 +59,15 @@ export declare const webDevScript: (options: Pick<ProjectOptions, 'name'>) => st
|
|
|
41
59
|
export declare const enforcesMembership: (options: ProjectOptions) => boolean;
|
|
42
60
|
export declare function packageJson(options: ProjectOptions): string;
|
|
43
61
|
export declare function tsconfigJson(options: ProjectOptions): string;
|
|
62
|
+
/**
|
|
63
|
+
* `tsconfig.build.json` — what `pnpm build` compiles: src/ only (tests and
|
|
64
|
+
* bin/ stay dev-only), emitted to dist/ with rootDir `.`, so src/server.ts
|
|
65
|
+
* becomes dist/src/server.js. Extends tsconfig.json, so the compiler options
|
|
66
|
+
* (and `pnpm typecheck`) never diverge.
|
|
67
|
+
*/
|
|
68
|
+
export declare function tsconfigBuildJson(): string;
|
|
69
|
+
/** The production Dockerfile — the same file `basalt publish dockerfile` writes. */
|
|
70
|
+
export declare function dockerfile(): string;
|
|
44
71
|
export declare function envTs(options: ProjectOptions): string;
|
|
45
72
|
/**
|
|
46
73
|
* An app-specific env-var prefix derived from the project name
|
|
@@ -48,17 +75,33 @@ export declare function envTs(options: ProjectOptions): string;
|
|
|
48
75
|
* (`DATABASE_URL`, …) other projects export too.
|
|
49
76
|
*/
|
|
50
77
|
export declare function envPrefix(name: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* The opening lines of `.env.example`. Up to create-basalt 1.10 they read
|
|
80
|
+
* {@link LEGACY_ENV_EXAMPLE_LEAD} ("nothing loads this file"); `update`
|
|
81
|
+
* swaps that for this one in existing apps.
|
|
82
|
+
*/
|
|
83
|
+
export declare const ENV_EXAMPLE_LEAD = "# Development: copy this file to .env \u2014 `pnpm dev` and `pnpm basalt` load it\n# automatically (a new app already has one). `pnpm start` (production) does\n# NOT: there the variables come from the environment (or `node --env-file`).";
|
|
84
|
+
export declare const LEGACY_ENV_EXAMPLE_LEAD = "# Nothing loads this file for you: copy it to .env and start with\n# `node --env-file=.env` / `tsx --env-file=.env`, or export the variables.";
|
|
51
85
|
export declare function envExample(options: ProjectOptions): string;
|
|
86
|
+
/**
|
|
87
|
+
* The `.env` a new app starts with (git-ignored, never in the manifest): the
|
|
88
|
+
* values of `.env.example` for local development plus — with auth — a freshly
|
|
89
|
+
* generated APP_SECRET, so `pnpm dev` works without a copy step.
|
|
90
|
+
*/
|
|
91
|
+
export declare function devEnvFile(options: ProjectOptions, appSecret: string): string;
|
|
52
92
|
/** A PostgreSQL-safe database name derived from the project name. */
|
|
53
93
|
export declare function databaseName(name: string): string;
|
|
54
94
|
export declare function appTs(options: ProjectOptions): string;
|
|
55
95
|
export declare function routesTs(options: ProjectOptions): string;
|
|
56
96
|
export declare function serverTs(): string;
|
|
57
97
|
/**
|
|
58
|
-
* `pnpm dev` entrypoint.
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* NODE_ENV
|
|
98
|
+
* `pnpm dev` entrypoint. Loads `.env` (when present) with `node --env-file`
|
|
99
|
+
* semantics — an exported variable wins, the file only fills in what is
|
|
100
|
+
* missing — and opts into NODE_ENV=development (dev secret defaults, pretty
|
|
101
|
+
* logs) unless NODE_ENV is already set, then starts the server. Kept out of
|
|
102
|
+
* server.ts on purpose: `pnpm start` runs server.ts directly, where nothing
|
|
103
|
+
* loads `.env` (production configuration comes from the real environment) and
|
|
104
|
+
* an unset NODE_ENV counts as production, so secrets are required (fail-closed).
|
|
62
105
|
*/
|
|
63
106
|
export declare function devTs(): string;
|
|
64
107
|
/**
|
|
@@ -85,8 +128,9 @@ export declare function prismaConfigTs(options: ProjectOptions): string;
|
|
|
85
128
|
export declare function dbTs(options: ProjectOptions): string;
|
|
86
129
|
/**
|
|
87
130
|
* `prisma/seed.ts` — creates the `demo` tenant the scaffolded resolvers expect
|
|
88
|
-
* (`x-tenant-id: demo`, `demo.localhost`). Runs from `pnpm db:seed`
|
|
89
|
-
* `prisma
|
|
131
|
+
* (`x-tenant-id: demo`, `demo.localhost`). Runs from `pnpm db:seed`
|
|
132
|
+
* (`prisma db seed`, the command prisma.config.ts declares) — Prisma 7's
|
|
133
|
+
* `migrate dev` does not run it.
|
|
90
134
|
*/
|
|
91
135
|
export declare function prismaSeedTs(options: ProjectOptions): string;
|
|
92
136
|
export declare function appTest(options: ProjectOptions): string;
|
|
@@ -113,7 +157,9 @@ export declare function mcpJson(_options: ProjectOptions): string;
|
|
|
113
157
|
export declare function dockerignore(): string;
|
|
114
158
|
export declare function gitignore(options: ProjectOptions): string;
|
|
115
159
|
/**
|
|
116
|
-
* pnpm settings: esbuild's build script is required by tsx;
|
|
160
|
+
* pnpm settings: esbuild's build script is required by tsx; with --prisma,
|
|
161
|
+
* the Prisma CLI's build scripts (prisma, @prisma/engines) are approved too — pnpm 11 fails
|
|
162
|
+
* the install on an unapproved build;
|
|
117
163
|
* msgpackr-extract (optional native accelerator via BullMQ) is declined —
|
|
118
164
|
* msgpackr falls back to pure JS. With --ui, `web` is a workspace member so
|
|
119
165
|
* its own dependencies resolve.
|