create-basalt 1.14.1 → 1.15.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 +1 -1
- package/dist/bin-template.d.ts +7 -2
- package/dist/bin-template.js +54 -3
- package/dist/dev-entry.d.ts +3 -2
- package/dist/dev-entry.js +7 -5
- package/dist/project/doctor.js +9 -3
- package/dist/project/production.d.ts +7 -3
- package/dist/project/production.js +14 -2
- package/dist/project/update.js +3 -3
- package/dist/templates.d.ts +16 -5
- package/dist/templates.js +40 -19
- package/dist/versions.js +4 -4
- package/package.json +18 -18
package/README.md
CHANGED
|
@@ -505,7 +505,7 @@ Outside an interactive terminal (no TTY) the questions are skipped. Always pass
|
|
|
505
505
|
Automatic installation failed (network, Node version, etc.). Go into the folder and run `pnpm install` (or the indicated manager) to see the real error.
|
|
506
506
|
|
|
507
507
|
**I started the app and `GET /auth/login` gives a secret error.**
|
|
508
|
-
With auth on, `src/env.ts` requires `APP_SECRET` — read as `MY_SAAS_APP_SECRET`, with at least 32 characters (`secret()` supplies a development default only when `NODE_ENV` is explicitly `development`/`test`). For development the scaffold's `.env` carries a generated one; in production export your own (`openssl rand -base64 48`) — `pnpm start`
|
|
508
|
+
With auth on, `src/env.ts` requires `APP_SECRET` — read as `MY_SAAS_APP_SECRET`, with at least 32 characters (`secret()` supplies a development default only when `NODE_ENV` is explicitly `development`/`test`). For development the scaffold's `.env` carries a generated one; in production export your own (`openssl rand -base64 48`) or put it in the server's `.env` — `pnpm start` loads `.env` (an exported variable wins) and, with `NODE_ENV` unset, runs as production.
|
|
509
509
|
|
|
510
510
|
**`The app cannot start — the database did not answer`.**
|
|
511
511
|
PostgreSQL is not running, or `MY_SAAS_DATABASE_URL` points at the wrong host/port (the message shows which, without credentials). Start it (`docker compose up -d`, or your local service) or fix the URL in `.env`; on a fresh database, `pnpm db:migrate`. `pnpm dev` still prints the raw error (the explainer lives in `bin/basalt.ts` only, so `src/dev.ts` stays a few lines); `pnpm basalt routes` gives the explained version.
|
package/dist/bin-template.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export declare const PROJECT_COMMANDS_MARKER = "['update', 'add', 'doctor', 'info'].includes(process.argv[2]";
|
|
3
3
|
/** Marker proving a bin/basalt.ts already has the dev prelude (.env loading, `upgrade`, env errors). */
|
|
4
4
|
export declare const DEV_PRELUDE_MARKER = "process.loadEnvFile(envFile)";
|
|
5
|
+
/** Marker proving a bin/basalt.ts already runs the generators without booting the app. */
|
|
6
|
+
export declare const GENERATORS_PRELUDE_MARKER = "process.argv[2]?.startsWith('make:')";
|
|
5
7
|
export declare function basaltBin(): string;
|
|
6
8
|
/**
|
|
7
9
|
* Hashes of every bin/basalt.ts an earlier create-basalt release generated
|
|
@@ -11,13 +13,16 @@ export declare function basaltBin(): string;
|
|
|
11
13
|
export declare const LEGACY_BIN_HASHES: ReadonlySet<string>;
|
|
12
14
|
export declare const hasProjectCommands: (content: string) => boolean;
|
|
13
15
|
export declare const hasDevPrelude: (content: string) => boolean;
|
|
16
|
+
export declare const hasGeneratorsPrelude: (content: string) => boolean;
|
|
14
17
|
/**
|
|
15
18
|
* Upgrades a template-generated bin/basalt.ts to the current template, step by
|
|
16
19
|
* step: (1) without the project commands, inserts their prelude after the
|
|
17
20
|
* shebang and turns the remaining static imports into dynamic ones (so they no
|
|
18
21
|
* longer run before it); (2) without the dev prelude, inserts it right after
|
|
19
|
-
* the project commands and routes the app import through `explainBootFailure
|
|
20
|
-
*
|
|
22
|
+
* the project commands and routes the app import through `explainBootFailure`;
|
|
23
|
+
* (3) without the generators prelude, inserts it right before the dev tools
|
|
24
|
+
* are imported for the booted CLI.
|
|
25
|
+
* Deterministic for the known templates — for the latest ones (1.9 to 1.14) the
|
|
21
26
|
* result is exactly {@link basaltBin}.
|
|
22
27
|
*/
|
|
23
28
|
export declare function patchBasaltBin(content: string): string;
|
package/dist/bin-template.js
CHANGED
|
@@ -174,10 +174,35 @@ async function databaseInUse(): Promise<{ name: string; target: string }> {
|
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
`;
|
|
177
|
+
/**
|
|
178
|
+
* The GENERATORS PRELUDE, after the dev prelude and still before anything of
|
|
179
|
+
* the app is imported: `make:*` only writes source files, so — like `upgrade` —
|
|
180
|
+
* it runs without booting the app. Booting it would run every boot check, and
|
|
181
|
+
* a generator would refuse to work until the database is up and migrated (or
|
|
182
|
+
* every environment variable is set), which is often exactly when the
|
|
183
|
+
* resource is being written. Any other command, and a `make:*` the generator
|
|
184
|
+
* does not know, falls through to the booted CLI below.
|
|
185
|
+
*/
|
|
186
|
+
const GENERATORS_PRELUDE = `// The generators (make:*) only write source files: like \`upgrade\`, they run
|
|
187
|
+
// without booting the app, so they work before the database is up or migrated.
|
|
188
|
+
if (process.argv[2]?.startsWith('make:')) {
|
|
189
|
+
const { consoleIo, parseArgv } = await import('@basaltkit/cli')
|
|
190
|
+
const { generatorCommands } = await import('@basaltkit/generator')
|
|
191
|
+
const { command, args, flags } = parseArgv(process.argv.slice(2))
|
|
192
|
+
const make = generatorCommands().find((candidate) => candidate.name === command)
|
|
193
|
+
if (make) {
|
|
194
|
+
// The generators read only io/args/flags — there is no app to hand them.
|
|
195
|
+
const context = { io: consoleIo(), args, flags } as unknown as Parameters<typeof make.handle>[0]
|
|
196
|
+
process.exit((await make.handle(context)) ?? 0)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
`;
|
|
177
200
|
/** Marker proving a bin/basalt.ts already delegates the project commands. */
|
|
178
201
|
export const PROJECT_COMMANDS_MARKER = "['update', 'add', 'doctor', 'info'].includes(process.argv[2]";
|
|
179
202
|
/** Marker proving a bin/basalt.ts already has the dev prelude (.env loading, `upgrade`, env errors). */
|
|
180
203
|
export const DEV_PRELUDE_MARKER = 'process.loadEnvFile(envFile)';
|
|
204
|
+
/** Marker proving a bin/basalt.ts already runs the generators without booting the app. */
|
|
205
|
+
export const GENERATORS_PRELUDE_MARKER = "process.argv[2]?.startsWith('make:')";
|
|
181
206
|
const APP_IMPORT = "await import('../src/app.js')";
|
|
182
207
|
const APP_IMPORT_EXPLAINED = `${APP_IMPORT}.catch(explainBootFailure)`;
|
|
183
208
|
const RUN_CLI = 'process.exit(await runCli({ app })';
|
|
@@ -185,6 +210,7 @@ export function basaltBin() {
|
|
|
185
210
|
return `#!/usr/bin/env node
|
|
186
211
|
${PRELUDE}
|
|
187
212
|
${DEV_PRELUDE}
|
|
213
|
+
${GENERATORS_PRELUDE}
|
|
188
214
|
// The dev tools are imported dynamically, after the project commands above.
|
|
189
215
|
const { runCli } = await import('@basaltkit/cli')
|
|
190
216
|
const { generatorCommands } = await import('@basaltkit/generator')
|
|
@@ -228,16 +254,24 @@ export const LEGACY_BIN_HASHES = new Set([
|
|
|
228
254
|
// 2026-10-01 (create-basalt 1.10): project commands (update/add/doctor/info)
|
|
229
255
|
// delegated before boot — but no .env loading and `upgrade` booted the app.
|
|
230
256
|
'sha256-9091e137a5de39929d0e70b2fd973386b9cc1c2f996e130989a22c795b9d0893',
|
|
257
|
+
// 2026-10-01 (create-basalt 1.11): the dev prelude — but make:* booted the
|
|
258
|
+
// app, so a generator needed a migrated database.
|
|
259
|
+
'sha256-bd0b6c9c40089a18c2c2f1a70953044d6a74a329d38a72903b494b1f2265a114',
|
|
260
|
+
// 2026-10-08: database diagnoses in explainBootFailure — make:* still booted.
|
|
261
|
+
'sha256-abea8cbfdb41a302cabad7929617f7fc2fe822345aa8db6ff777e923eb0fc96b',
|
|
231
262
|
]);
|
|
232
263
|
export const hasProjectCommands = (content) => content.includes(PROJECT_COMMANDS_MARKER);
|
|
233
264
|
export const hasDevPrelude = (content) => content.includes(DEV_PRELUDE_MARKER);
|
|
265
|
+
export const hasGeneratorsPrelude = (content) => content.includes(GENERATORS_PRELUDE_MARKER);
|
|
234
266
|
/**
|
|
235
267
|
* Upgrades a template-generated bin/basalt.ts to the current template, step by
|
|
236
268
|
* step: (1) without the project commands, inserts their prelude after the
|
|
237
269
|
* shebang and turns the remaining static imports into dynamic ones (so they no
|
|
238
270
|
* longer run before it); (2) without the dev prelude, inserts it right after
|
|
239
|
-
* the project commands and routes the app import through `explainBootFailure
|
|
240
|
-
*
|
|
271
|
+
* the project commands and routes the app import through `explainBootFailure`;
|
|
272
|
+
* (3) without the generators prelude, inserts it right before the dev tools
|
|
273
|
+
* are imported for the booted CLI.
|
|
274
|
+
* Deterministic for the known templates — for the latest ones (1.9 to 1.14) the
|
|
241
275
|
* result is exactly {@link basaltBin}.
|
|
242
276
|
*/
|
|
243
277
|
export function patchBasaltBin(content) {
|
|
@@ -246,6 +280,8 @@ export function patchBasaltBin(content) {
|
|
|
246
280
|
text = addProjectCommands(text);
|
|
247
281
|
if (!hasDevPrelude(text))
|
|
248
282
|
text = addDevPrelude(text);
|
|
283
|
+
if (!hasGeneratorsPrelude(text))
|
|
284
|
+
text = addGeneratorsPrelude(text);
|
|
249
285
|
return text;
|
|
250
286
|
}
|
|
251
287
|
function addProjectCommands(content) {
|
|
@@ -273,11 +309,19 @@ function addDevPrelude(content) {
|
|
|
273
309
|
.replace(`${RUN_CLI})\n`, `${RUN_CLI}.catch(explainBootFailure))\n`);
|
|
274
310
|
return `${content.slice(0, end)}${DEV_PRELUDE}\n${rest}`;
|
|
275
311
|
}
|
|
312
|
+
/** Inserts the generators prelude right before the dev tools are imported for the booted CLI. */
|
|
313
|
+
function addGeneratorsPrelude(content) {
|
|
314
|
+
const anchor = /^(?:\/\/ The dev tools are imported dynamically[^\n]*\n)?const \{ runCli \} = await import\('@basaltkit\/cli'\)$/m.exec(content);
|
|
315
|
+
// Without the template's dynamic CLI import, the file is not ours to rearrange.
|
|
316
|
+
if (!anchor || !hasDevPrelude(content))
|
|
317
|
+
return content;
|
|
318
|
+
return `${content.slice(0, anchor.index)}${GENERATORS_PRELUDE}\n${content.slice(anchor.index)}`;
|
|
319
|
+
}
|
|
276
320
|
/** Where a bin/basalt.ts stands: already current, an untouched old template, or user code. */
|
|
277
321
|
export function binStatus(content, manifestHash) {
|
|
278
322
|
if (content === undefined)
|
|
279
323
|
return 'absent';
|
|
280
|
-
if (hasProjectCommands(content) && hasDevPrelude(content))
|
|
324
|
+
if (hasProjectCommands(content) && hasDevPrelude(content) && hasGeneratorsPrelude(content))
|
|
281
325
|
return 'current';
|
|
282
326
|
const hash = hashContent(content);
|
|
283
327
|
return LEGACY_BIN_HASHES.has(hash) || hash === manifestHash ? 'patchable' : 'modified';
|
|
@@ -300,6 +344,13 @@ and explains env errors — and change the app import to
|
|
|
300
344
|
\`const { buildApp } = ${APP_IMPORT_EXPLAINED}\`:
|
|
301
345
|
|
|
302
346
|
${DEV_PRELUDE}`);
|
|
347
|
+
}
|
|
348
|
+
if (!hasGeneratorsPrelude(content)) {
|
|
349
|
+
steps.push(`${steps.length > 0 ? 'Then paste' : 'Paste'} this after the dev prelude (before the dev tools are imported for the
|
|
350
|
+
booted CLI) — it runs the make:* generators without booting the app, so they
|
|
351
|
+
work before the database is up or migrated:
|
|
352
|
+
|
|
353
|
+
${GENERATORS_PRELUDE}`);
|
|
303
354
|
}
|
|
304
355
|
return steps.join('\n');
|
|
305
356
|
}
|
package/dist/dev-entry.d.ts
CHANGED
|
@@ -16,8 +16,9 @@ export declare const patchDevEntry: () => string;
|
|
|
16
16
|
/** What to paste by hand into a customised src/dev.ts. */
|
|
17
17
|
export declare const MANUAL_DEV_SNIPPET = "Paste this at the top of src/dev.ts, BEFORE the server is imported (keep that\nimport dynamic \u2014 `await import('./server.js')` \u2014 so the variables are set first):\n\nimport { existsSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\n\n// Development loads .env (when present) like `node --env-file=.env`: a variable\n// already exported in your shell still wins, the file only fills in what is missing.\nconst envFile = fileURLToPath(new URL('../.env', import.meta.url))\nif (existsSync(envFile)) process.loadEnvFile(envFile)\n";
|
|
18
18
|
/**
|
|
19
|
-
* `.env.example` with
|
|
20
|
-
* current one; undefined when the file does
|
|
19
|
+
* `.env.example` with an earlier lead ("nothing loads this file", or "`pnpm
|
|
20
|
+
* start` does NOT") swapped for the current one; undefined when the file does
|
|
21
|
+
* not start with one of them (a
|
|
21
22
|
* newer or hand-written file is left alone — it is only comments).
|
|
22
23
|
*/
|
|
23
24
|
export declare function patchEnvExample(content: string): string | undefined;
|
package/dist/dev-entry.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hashContent } from './project/manifest.js';
|
|
2
|
-
import { devTs, ENV_EXAMPLE_LEAD, LEGACY_ENV_EXAMPLE_LEAD } from './templates.js';
|
|
2
|
+
import { devTs, ENV_EXAMPLE_LEAD, LEGACY_ENV_EXAMPLE_LEAD, PREVIOUS_ENV_EXAMPLE_LEAD } from './templates.js';
|
|
3
3
|
/**
|
|
4
4
|
* `src/dev.ts` (the `pnpm dev` entrypoint) and the `.env.example` header across
|
|
5
5
|
* create-basalt releases. Up to 1.10, nothing loaded `.env`: `pnpm dev` booted
|
|
@@ -37,13 +37,15 @@ const envFile = fileURLToPath(new URL('../.env', import.meta.url))
|
|
|
37
37
|
if (existsSync(envFile)) process.loadEnvFile(envFile)
|
|
38
38
|
`;
|
|
39
39
|
/**
|
|
40
|
-
* `.env.example` with
|
|
41
|
-
* current one; undefined when the file does
|
|
40
|
+
* `.env.example` with an earlier lead ("nothing loads this file", or "`pnpm
|
|
41
|
+
* start` does NOT") swapped for the current one; undefined when the file does
|
|
42
|
+
* not start with one of them (a
|
|
42
43
|
* newer or hand-written file is left alone — it is only comments).
|
|
43
44
|
*/
|
|
44
45
|
export function patchEnvExample(content) {
|
|
45
46
|
const normalized = content.replace(/\r\n/g, '\n');
|
|
46
|
-
|
|
47
|
+
const lead = [LEGACY_ENV_EXAMPLE_LEAD, PREVIOUS_ENV_EXAMPLE_LEAD].find((old) => normalized.startsWith(`${old}\n`));
|
|
48
|
+
if (lead === undefined)
|
|
47
49
|
return undefined;
|
|
48
|
-
return `${ENV_EXAMPLE_LEAD}${normalized.slice(
|
|
50
|
+
return `${ENV_EXAMPLE_LEAD}${normalized.slice(lead.length)}`;
|
|
49
51
|
}
|
package/dist/project/doctor.js
CHANGED
|
@@ -6,7 +6,7 @@ import { binStatus } from '../bin-template.js';
|
|
|
6
6
|
import { devEntryStatus } from '../dev-entry.js';
|
|
7
7
|
import { alwaysLatest, lookupLatestVersions } from '../latest-versions.js';
|
|
8
8
|
import { PRODUCTION_ENTRY } from '../stubs.js';
|
|
9
|
-
import { envPrefix } from '../templates.js';
|
|
9
|
+
import { envPrefix, PREVIOUS_START_SCRIPT, START_SCRIPT } from '../templates.js';
|
|
10
10
|
import { allDependencies } from './context.js';
|
|
11
11
|
import { ownVersion } from './manifest.js';
|
|
12
12
|
import { LEGACY_PRISMA_OUTPUT, RUNS_TSX } from './production.js';
|
|
@@ -382,10 +382,10 @@ export async function runDoctor(ctx, options = {}) {
|
|
|
382
382
|
const bin = await readText(join(dir, 'bin', 'basalt.ts'));
|
|
383
383
|
const status = binStatus(bin, ctx.manifest?.files['bin/basalt.ts']);
|
|
384
384
|
if (status === 'patchable') {
|
|
385
|
-
push('warn', 'tooling', 'bin/basalt.ts is an older template (
|
|
385
|
+
push('warn', 'tooling', 'bin/basalt.ts is an older template (it lacks some of: .env loading, pre-boot project commands, make:* without booting the app) — `npx create-basalt@latest update` patches it.');
|
|
386
386
|
}
|
|
387
387
|
if (status === 'modified') {
|
|
388
|
-
push('info', 'tooling', 'bin/basalt.ts is customised and lacks the current preludes (project commands, .env loading, pre-boot `upgrade`) — see `create-basalt update` for the snippet.');
|
|
388
|
+
push('info', 'tooling', 'bin/basalt.ts is customised and lacks the current preludes (project commands, .env loading, pre-boot `upgrade` and make:*) — see `create-basalt update` for the snippet.');
|
|
389
389
|
}
|
|
390
390
|
const dev = await readText(join(dir, 'src', 'dev.ts'));
|
|
391
391
|
const devStatus = devEntryStatus(dev, ctx.manifest?.files['src/dev.ts']);
|
|
@@ -403,6 +403,12 @@ export async function runDoctor(ctx, options = {}) {
|
|
|
403
403
|
if (start !== undefined && RUNS_TSX.test(start) && tsxIsDevOnly) {
|
|
404
404
|
push('warn', 'build', `\`start\` runs tsx ("${start}"), but tsx is only a devDependency — a production install (--prod) has no tsx. Build and run the compiled server: \`npx create-basalt@latest update\` prints the scripts.`);
|
|
405
405
|
}
|
|
406
|
+
if (start === PREVIOUS_START_SCRIPT) {
|
|
407
|
+
push('info', 'build', `\`start\` loads no .env ("${start}") — fine where the platform exports the environment; \`npx create-basalt@latest update\` switches it to \`${START_SCRIPT}\`.`);
|
|
408
|
+
}
|
|
409
|
+
if (start !== undefined && /--env-file/.test(start) && /^\s*NODE_ENV\s*=\s*["']?development["']?\s*$/m.test((await readText(join(dir, '.env'))) ?? '')) {
|
|
410
|
+
push('warn', 'build', '.env sets NODE_ENV=development and `start` loads .env: a production start boots in development, with the dev secret defaults. Remove the line — `dev` and `basalt` set it themselves.');
|
|
411
|
+
}
|
|
406
412
|
if (scripts['build'] === undefined) {
|
|
407
413
|
push('warn', 'build', `No \`build\` script — there is no tested way to run the app on plain node. \`npx create-basalt@latest update\` adds tsconfig.build.json and \`build\`.`);
|
|
408
414
|
}
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
* The production path (BK-026) for an app scaffolded before create-basalt
|
|
3
3
|
* shipped one: `create-basalt update` OFFERS what is missing — it is part of
|
|
4
4
|
* the printed plan, applied only on confirmation — and never rewrites what the
|
|
5
|
-
* app already has. In particular
|
|
5
|
+
* app already has. In particular a customised `start` script is never changed:
|
|
6
6
|
* switching it from tsx to the compiled server changes how the app is
|
|
7
|
-
* deployed, so that is printed as a manual step.
|
|
7
|
+
* deployed, so that is printed as a manual step. Only the exact `start` an
|
|
8
|
+
* earlier create-basalt wrote ({@link PREVIOUS_START_SCRIPT}) is offered the
|
|
9
|
+
* `.env` loading — under @basaltkit/deploy's pm2 runtime before 0.10 it booted
|
|
10
|
+
* without its secrets.
|
|
8
11
|
*/
|
|
9
12
|
export interface ProductionPathPlan {
|
|
10
13
|
/** New files: path → content (only files that do not exist yet). */
|
|
@@ -20,7 +23,8 @@ export interface ProductionPathPlan {
|
|
|
20
23
|
export declare const LEGACY_PRISMA_OUTPUT: RegExp;
|
|
21
24
|
/** `start` (or any script) that runs TypeScript through tsx. */
|
|
22
25
|
export declare const RUNS_TSX: RegExp;
|
|
23
|
-
export declare const MANUAL_START_SNIPPET = "In package.json, run the compiled server in production (build first: `pnpm build`):\n \"start\": \"node --enable-source-maps dist/src/server.js\",\n \"start:dev\": \"tsx src/server.ts\"";
|
|
26
|
+
export declare const MANUAL_START_SNIPPET = "In package.json, run the compiled server in production (build first: `pnpm build`):\n \"start\": \"node --env-file-if-exists=.env --enable-source-maps dist/src/server.js\",\n \"start:dev\": \"tsx src/server.ts\"";
|
|
27
|
+
export declare const MANUAL_NODE_ENV_SNIPPET = "Remove NODE_ENV=development from .env: `pnpm dev` and `pnpm basalt` already set it, and\n`pnpm start` now loads .env \u2014 with that line it would boot in development, accepting the dev secret\ndefaults instead of requiring the real ones.";
|
|
24
28
|
export declare const MANUAL_PRISMA_LAYOUT_SNIPPET: string;
|
|
25
29
|
/**
|
|
26
30
|
* What an existing app lacks of the production path: tsconfig.build.json, a
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { DOCKERFILE, DOCKERIGNORE, PRODUCTION_ENTRY } from '../stubs.js';
|
|
4
|
-
import { BUILD_SCRIPT, PRISMA_IMPORTS, START_DEV_SCRIPT, START_SCRIPT, tsconfigBuildJson } from '../templates.js';
|
|
4
|
+
import { BUILD_SCRIPT, ENGINES_NODE, PREVIOUS_START_SCRIPT, PRISMA_IMPORTS, START_DEV_SCRIPT, START_SCRIPT, tsconfigBuildJson } from '../templates.js';
|
|
5
5
|
import { mergePackageJson } from './package-json.js';
|
|
6
6
|
/** A Prisma generator that still writes the client under src/ — tsc does not copy its .js files to dist/. */
|
|
7
7
|
export const LEGACY_PRISMA_OUTPUT = /generator\s+\w+\s*\{[^}]*output\s*=\s*"\.\.\/src\/[^"]*"/;
|
|
@@ -19,6 +19,9 @@ const exists = async (path) => (await readOptional(path)) !== undefined;
|
|
|
19
19
|
export const MANUAL_START_SNIPPET = `In package.json, run the compiled server in production (build first: \`pnpm build\`):
|
|
20
20
|
"start": "${START_SCRIPT}",
|
|
21
21
|
"start:dev": "${START_DEV_SCRIPT}"`;
|
|
22
|
+
export const MANUAL_NODE_ENV_SNIPPET = `Remove NODE_ENV=development from .env: \`pnpm dev\` and \`pnpm basalt\` already set it, and
|
|
23
|
+
\`pnpm start\` now loads .env — with that line it would boot in development, accepting the dev secret
|
|
24
|
+
defaults instead of requiring the real ones.`;
|
|
22
25
|
export const MANUAL_PRISMA_LAYOUT_SNIPPET = `The Prisma client is generated under src/, where \`tsc\` does not copy its .js files — \`node ${PRODUCTION_ENTRY}\` cannot load it. Move it out of src/:
|
|
23
26
|
prisma/schema.prisma output = "../generated/prisma"
|
|
24
27
|
package.json "imports": ${JSON.stringify(PRISMA_IMPORTS)}
|
|
@@ -45,12 +48,15 @@ export async function planProductionPath(dir, packageJsonText, pm = 'pnpm') {
|
|
|
45
48
|
const prismaClient = pkg.dependencies?.['@prisma/client'];
|
|
46
49
|
const merged = mergePackageJson(packageJsonText, {
|
|
47
50
|
scripts: { build: BUILD_SCRIPT },
|
|
51
|
+
replaceScripts: pkg.scripts?.['start'] === PREVIOUS_START_SCRIPT ? { start: { from: PREVIOUS_START_SCRIPT, to: START_SCRIPT } } : {},
|
|
48
52
|
...(schema !== undefined && prismaClient !== undefined
|
|
49
53
|
? { dependencies: { '@prisma/client-runtime-utils': prismaClient } }
|
|
50
54
|
: {}),
|
|
51
55
|
});
|
|
52
56
|
for (const change of merged.changes) {
|
|
53
|
-
if (change.startsWith('scripts:'))
|
|
57
|
+
if (change.startsWith('scripts: start:'))
|
|
58
|
+
notes.push(`package.json: "start" loads .env when it exists (${START_SCRIPT}); needs Node ${ENGINES_NODE}`);
|
|
59
|
+
else if (change.startsWith('scripts:'))
|
|
54
60
|
notes.push(`package.json: a "build" script (${BUILD_SCRIPT})`);
|
|
55
61
|
else
|
|
56
62
|
notes.push(`package.json: @prisma/client-runtime-utils ${prismaClient} — the generated client requires it by name; plain node cannot reach it as a transitive dependency`);
|
|
@@ -58,6 +64,12 @@ export async function planProductionPath(dir, packageJsonText, pm = 'pnpm') {
|
|
|
58
64
|
const start = pkg.scripts?.['start'];
|
|
59
65
|
if (start !== undefined && RUNS_TSX.test(start))
|
|
60
66
|
manual.push(MANUAL_START_SNIPPET);
|
|
67
|
+
// `start` now loads .env: a NODE_ENV=development left there (create-basalt ≤ 1.14
|
|
68
|
+
// wrote one) would boot `pnpm start` in development, with the dev secret defaults.
|
|
69
|
+
const dotEnv = await readOptional(join(dir, '.env'));
|
|
70
|
+
if (dotEnv !== undefined && /^\s*NODE_ENV\s*=\s*["']?development["']?\s*$/m.test(dotEnv)) {
|
|
71
|
+
manual.push(MANUAL_NODE_ENV_SNIPPET);
|
|
72
|
+
}
|
|
61
73
|
const legacyPrisma = schema !== undefined && LEGACY_PRISMA_OUTPUT.test(schema);
|
|
62
74
|
if (legacyPrisma)
|
|
63
75
|
manual.push(MANUAL_PRISMA_LAYOUT_SNIPPET);
|
package/dist/project/update.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { binStatus, hasProjectCommands, manualBinSnippet, patchBasaltBin } from '../bin-template.js';
|
|
3
|
+
import { binStatus, hasDevPrelude, hasProjectCommands, manualBinSnippet, patchBasaltBin } from '../bin-template.js';
|
|
4
4
|
import { devEntryStatus, MANUAL_DEV_SNIPPET, patchDevEntry, patchEnvExample } from '../dev-entry.js';
|
|
5
5
|
import { alwaysLatest, lookupLatestVersions, minimumReleaseAgeMinutes, } from '../latest-versions.js';
|
|
6
6
|
import { BASALT_PROJECT_SCRIPT } from '../templates.js';
|
|
@@ -207,7 +207,7 @@ export async function planUpdate(ctx, options = {}) {
|
|
|
207
207
|
const after = patchBasaltBin(bin);
|
|
208
208
|
files['bin/basalt.ts'] = { before: bin, after };
|
|
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`);
|
|
210
|
+
toolingNotes.push(`bin/basalt.ts: unmodified template from an earlier release — ${hasProjectCommands(bin) ? '' : 'gains update/add/doctor/info; '}${hasDevPrelude(bin) ? '' : 'loads .env for development, runs \`upgrade\` without booting the app, explains env errors; '}runs make:* without booting the app (no database needed to generate code)`);
|
|
211
211
|
}
|
|
212
212
|
else if (status === 'modified' && bin !== undefined) {
|
|
213
213
|
manual.push(`bin/basalt.ts was customised, so it was not patched. To bring it up to date:\n${manualBinSnippet(bin)}`);
|
|
@@ -228,7 +228,7 @@ export async function planUpdate(ctx, options = {}) {
|
|
|
228
228
|
if (example !== undefined && exampleAfter !== undefined) {
|
|
229
229
|
files['.env.example'] = { before: example, after: exampleAfter };
|
|
230
230
|
patched['.env.example'] = exampleAfter;
|
|
231
|
-
toolingNotes.push('.env.example: header now says dev
|
|
231
|
+
toolingNotes.push('.env.example: header now says `dev`, `basalt` and `start` load .env (an exported variable wins)');
|
|
232
232
|
}
|
|
233
233
|
// The production path (BK-026): tsconfig.build.json, a `build` script, the
|
|
234
234
|
// Dockerfile — offered when missing, never overwriting what the app has.
|
package/dist/templates.d.ts
CHANGED
|
@@ -41,7 +41,16 @@ export declare const thirdPartyVersionOf: (pkg: string) => string;
|
|
|
41
41
|
export declare const BUILD_SCRIPT = "tsc -p tsconfig.build.json";
|
|
42
42
|
/** The `db:seed` script of a `--prisma` scaffold with tenancy (prisma.config.ts loads .env, then runs `migrations.seed`). */
|
|
43
43
|
export declare const DB_SEED_SCRIPT = "prisma db seed";
|
|
44
|
-
|
|
44
|
+
/**
|
|
45
|
+
* `start` loads `.env` when it exists (`--env-file-if-exists`): an exported
|
|
46
|
+
* variable still wins, and the file sets no NODE_ENV, so an unset NODE_ENV
|
|
47
|
+
* stays production — secrets required (fail-closed).
|
|
48
|
+
*/
|
|
49
|
+
export declare const START_SCRIPT = "node --env-file-if-exists=.env --enable-source-maps dist/src/server.js";
|
|
50
|
+
/** The `start` create-basalt wrote before it loaded `.env`: `update` replaces it when untouched. */
|
|
51
|
+
export declare const PREVIOUS_START_SCRIPT = "node --enable-source-maps dist/src/server.js";
|
|
52
|
+
/** `--env-file-if-exists` (the `start` script) needs Node 22.9. */
|
|
53
|
+
export declare const ENGINES_NODE = ">=22.9.0";
|
|
45
54
|
export declare const START_DEV_SCRIPT = "tsx src/server.ts";
|
|
46
55
|
/** The `start` script every create-basalt release before the production path wrote. */
|
|
47
56
|
export declare const LEGACY_START_SCRIPT = "tsx src/server.ts";
|
|
@@ -80,7 +89,9 @@ export declare function envPrefix(name: string): string;
|
|
|
80
89
|
* {@link LEGACY_ENV_EXAMPLE_LEAD} ("nothing loads this file"); `update`
|
|
81
90
|
* swaps that for this one in existing apps.
|
|
82
91
|
*/
|
|
83
|
-
export declare const ENV_EXAMPLE_LEAD = "#
|
|
92
|
+
export declare const ENV_EXAMPLE_LEAD = "# Copy this file to .env (a new app already has one). `pnpm dev`, `pnpm basalt`\n# and `pnpm start` load it when it exists; a variable exported in your shell\n# (or by the platform: Docker, systemd, the deploy) always wins.";
|
|
93
|
+
/** The lead create-basalt 1.11–1.14 wrote (\`pnpm start\` did not load .env); \`update\` swaps it. */
|
|
94
|
+
export declare const PREVIOUS_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
95
|
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.";
|
|
85
96
|
export declare function envExample(options: ProjectOptions): string;
|
|
86
97
|
/**
|
|
@@ -99,9 +110,9 @@ export declare function serverTs(): string;
|
|
|
99
110
|
* semantics — an exported variable wins, the file only fills in what is
|
|
100
111
|
* missing — and opts into NODE_ENV=development (dev secret defaults, pretty
|
|
101
112
|
* logs) unless NODE_ENV is already set, then starts the server. Kept out of
|
|
102
|
-
* server.ts on purpose: `pnpm start` runs server
|
|
103
|
-
*
|
|
104
|
-
*
|
|
113
|
+
* server.ts on purpose: `pnpm start` runs the compiled server, which loads
|
|
114
|
+
* `.env` through `--env-file-if-exists` but never opts into development — an
|
|
115
|
+
* unset NODE_ENV counts as production, so secrets are required (fail-closed).
|
|
105
116
|
*/
|
|
106
117
|
export declare function devTs(): string;
|
|
107
118
|
/**
|
package/dist/templates.js
CHANGED
|
@@ -38,7 +38,16 @@ export const thirdPartyVersionOf = (pkg) => {
|
|
|
38
38
|
export const BUILD_SCRIPT = 'tsc -p tsconfig.build.json';
|
|
39
39
|
/** The `db:seed` script of a `--prisma` scaffold with tenancy (prisma.config.ts loads .env, then runs `migrations.seed`). */
|
|
40
40
|
export const DB_SEED_SCRIPT = 'prisma db seed';
|
|
41
|
-
|
|
41
|
+
/**
|
|
42
|
+
* `start` loads `.env` when it exists (`--env-file-if-exists`): an exported
|
|
43
|
+
* variable still wins, and the file sets no NODE_ENV, so an unset NODE_ENV
|
|
44
|
+
* stays production — secrets required (fail-closed).
|
|
45
|
+
*/
|
|
46
|
+
export const START_SCRIPT = `node --env-file-if-exists=.env --enable-source-maps ${PRODUCTION_ENTRY}`;
|
|
47
|
+
/** The `start` create-basalt wrote before it loaded `.env`: `update` replaces it when untouched. */
|
|
48
|
+
export const PREVIOUS_START_SCRIPT = `node --enable-source-maps ${PRODUCTION_ENTRY}`;
|
|
49
|
+
/** `--env-file-if-exists` (the `start` script) needs Node 22.9. */
|
|
50
|
+
export const ENGINES_NODE = '>=22.9.0';
|
|
42
51
|
export const START_DEV_SCRIPT = 'tsx src/server.ts';
|
|
43
52
|
/** The `start` script every create-basalt release before the production path wrote. */
|
|
44
53
|
export const LEGACY_START_SCRIPT = 'tsx src/server.ts';
|
|
@@ -138,10 +147,12 @@ export function packageJson(options) {
|
|
|
138
147
|
version: '0.1.0',
|
|
139
148
|
private: true,
|
|
140
149
|
type: 'module',
|
|
150
|
+
engines: { node: ENGINES_NODE },
|
|
141
151
|
...(options.prisma ? { imports: PRISMA_IMPORTS } : {}),
|
|
142
152
|
scripts: {
|
|
143
|
-
// dev opts into NODE_ENV=development (src/dev.ts); start
|
|
144
|
-
// unset NODE_ENV counts as production and secrets
|
|
153
|
+
// dev opts into NODE_ENV=development (src/dev.ts); start loads .env but
|
|
154
|
+
// never opts in, so an unset NODE_ENV counts as production and secrets
|
|
155
|
+
// are required.
|
|
145
156
|
dev: 'tsx watch src/dev.ts',
|
|
146
157
|
// Production: compile once, run on plain node (no tsx at runtime).
|
|
147
158
|
build: BUILD_SCRIPT,
|
|
@@ -287,7 +298,11 @@ export function envPrefix(name) {
|
|
|
287
298
|
* {@link LEGACY_ENV_EXAMPLE_LEAD} ("nothing loads this file"); `update`
|
|
288
299
|
* swaps that for this one in existing apps.
|
|
289
300
|
*/
|
|
290
|
-
export const ENV_EXAMPLE_LEAD = `#
|
|
301
|
+
export const ENV_EXAMPLE_LEAD = `# Copy this file to .env (a new app already has one). \`pnpm dev\`, \`pnpm basalt\`
|
|
302
|
+
# and \`pnpm start\` load it when it exists; a variable exported in your shell
|
|
303
|
+
# (or by the platform: Docker, systemd, the deploy) always wins.`;
|
|
304
|
+
/** The lead create-basalt 1.11–1.14 wrote (\`pnpm start\` did not load .env); \`update\` swaps it. */
|
|
305
|
+
export const PREVIOUS_ENV_EXAMPLE_LEAD = `# Development: copy this file to .env — \`pnpm dev\` and \`pnpm basalt\` load it
|
|
291
306
|
# automatically (a new app already has one). \`pnpm start\` (production) does
|
|
292
307
|
# NOT: there the variables come from the environment (or \`node --env-file\`).`;
|
|
293
308
|
export const LEGACY_ENV_EXAMPLE_LEAD = `# Nothing loads this file for you: copy it to .env and start with
|
|
@@ -303,8 +318,9 @@ export function envExample(options) {
|
|
|
303
318
|
${prefix}_PORT=3000
|
|
304
319
|
${prefix}_HOST=0.0.0.0
|
|
305
320
|
${prefix}_LOG_LEVEL=info
|
|
306
|
-
# NODE_ENV is a Node-wide convention and is never prefixed.
|
|
307
|
-
|
|
321
|
+
# NODE_ENV is a Node-wide convention and is never prefixed. Leave it out of this
|
|
322
|
+
# file: \`pnpm dev\` and \`pnpm basalt\` set development, and \`pnpm start\`, with it
|
|
323
|
+
# unset, runs as production — where the secrets below are required.
|
|
308
324
|
${options.auth
|
|
309
325
|
? `# Required unless NODE_ENV is development/test — \`pnpm start\` refuses to boot
|
|
310
326
|
# without it. Generate a strong one: openssl rand -base64 48
|
|
@@ -331,8 +347,8 @@ export function devEnvFile(options, appSecret) {
|
|
|
331
347
|
const example = envExample(options);
|
|
332
348
|
const body = example.slice(example.indexOf(`${prefix}_PORT=`));
|
|
333
349
|
return `# Local development settings, generated by create-basalt from .env.example.
|
|
334
|
-
# Git-ignored: never commit it. \`pnpm dev\` and \`pnpm
|
|
335
|
-
# variable exported in your shell wins)
|
|
350
|
+
# Git-ignored: never commit it. \`pnpm dev\`, \`pnpm basalt\` and \`pnpm start\` load it
|
|
351
|
+
# (a variable exported in your shell wins).
|
|
336
352
|
${body.replace(`# ${prefix}_APP_SECRET=\n`, `${prefix}_APP_SECRET=${appSecret}\n`)}`;
|
|
337
353
|
}
|
|
338
354
|
/** A PostgreSQL-safe database name derived from the project name. */
|
|
@@ -367,9 +383,13 @@ export function appTs(options) {
|
|
|
367
383
|
if (options.prisma) {
|
|
368
384
|
imports.push(`import { prismaPlugin } from '@basaltkit/prisma'`);
|
|
369
385
|
imports.push(`import { db, prisma } from './db.js'`);
|
|
370
|
-
plugins.push(`prismaPlugin({
|
|
386
|
+
plugins.push(`prismaPlugin({${options.tenancy
|
|
387
|
+
? `
|
|
371
388
|
// \`db\` is the tenant-scoped client (src/db.ts): db<PrismaClient>() in a
|
|
372
|
-
// handler returns it, already filtered by the request's tenant
|
|
389
|
+
// handler returns it, already filtered by the request's tenant.`
|
|
390
|
+
: `
|
|
391
|
+
// \`db\` is the application client (src/db.ts): db<PrismaClient>() in a
|
|
392
|
+
// handler returns it. No tenancy, so queries are not filtered by tenant.`}
|
|
373
393
|
client: db,
|
|
374
394
|
// Fail the BOOT when this database is not the migrated one — a shell that
|
|
375
395
|
// exported another project's DATABASE_URL, a typo in the database name.
|
|
@@ -621,20 +641,19 @@ for (const signal of ['SIGINT', 'SIGTERM'] as const) {
|
|
|
621
641
|
* semantics — an exported variable wins, the file only fills in what is
|
|
622
642
|
* missing — and opts into NODE_ENV=development (dev secret defaults, pretty
|
|
623
643
|
* logs) unless NODE_ENV is already set, then starts the server. Kept out of
|
|
624
|
-
* server.ts on purpose: `pnpm start` runs server
|
|
625
|
-
*
|
|
626
|
-
*
|
|
644
|
+
* server.ts on purpose: `pnpm start` runs the compiled server, which loads
|
|
645
|
+
* `.env` through `--env-file-if-exists` but never opts into development — an
|
|
646
|
+
* unset NODE_ENV counts as production, so secrets are required (fail-closed).
|
|
627
647
|
*/
|
|
628
648
|
export function devTs() {
|
|
629
|
-
return `// Development entrypoint (\`pnpm dev\`). \`pnpm start\` runs server
|
|
649
|
+
return `// Development entrypoint (\`pnpm dev\`). \`pnpm start\` runs the compiled server,
|
|
630
650
|
// where an unset NODE_ENV counts as production: secrets are then required.
|
|
631
651
|
import { existsSync } from 'node:fs'
|
|
632
652
|
import { fileURLToPath } from 'node:url'
|
|
633
653
|
|
|
634
654
|
// Development loads .env (when present) like \`node --env-file=.env\`: a variable
|
|
635
655
|
// already exported in your shell still wins, the file only fills in what is
|
|
636
|
-
// missing.
|
|
637
|
-
// comes from the real environment.
|
|
656
|
+
// missing. Only development opts into NODE_ENV=development, below.
|
|
638
657
|
const envFile = fileURLToPath(new URL('../.env', import.meta.url))
|
|
639
658
|
if (existsSync(envFile)) process.loadEnvFile(envFile)
|
|
640
659
|
|
|
@@ -1136,8 +1155,10 @@ scaffold with \`--cli\` — \`pnpm basalt prisma:sync\` does the merge for you.)
|
|
|
1136
1155
|
\`src/env.ts\` validates \`process.env\`. For development, ${options.cli ? '`pnpm dev` and `pnpm basalt` load' : '`pnpm dev` loads'} \`.env\`
|
|
1137
1156
|
automatically — create-basalt wrote one for you: git-ignored, with local
|
|
1138
1157
|
values${options.auth ? ' and a generated secret' : ''}. \`.env.example\` is its committed template.
|
|
1139
|
-
\`pnpm start\` (production, \`${PRODUCTION_ENTRY}\`) loads
|
|
1140
|
-
|
|
1158
|
+
\`pnpm start\` (production, \`${PRODUCTION_ENTRY}\`) loads \`.env\` too when it exists
|
|
1159
|
+
(\`node --env-file-if-exists\`), but the file sets no \`NODE_ENV\`: unset, it counts
|
|
1160
|
+
as production, so the secrets are required. Variables the platform exports —
|
|
1161
|
+
Docker, systemd, \`@basaltkit/deploy\` — always win over the file.
|
|
1141
1162
|
|
|
1142
1163
|
The variables are **app-prefixed**: \`${envPrefix(options.name)}_PORT\`,
|
|
1143
1164
|
\`${envPrefix(options.name)}_HOST\`, \`${envPrefix(options.name)}_LOG_LEVEL\`${options.auth ? `, \`${envPrefix(options.name)}_APP_SECRET\`` : ''}${options.prisma ? `, \`${envPrefix(options.name)}_DATABASE_URL\`` : ''}. \`NODE_ENV\` is never prefixed.
|
|
@@ -1164,7 +1185,7 @@ your shell exports: \`env | grep DATABASE_URL\`.
|
|
|
1164
1185
|
|
|
1165
1186
|
\`\`\`bash
|
|
1166
1187
|
pnpm build # tsc -p tsconfig.build.json → dist/ (src only)
|
|
1167
|
-
pnpm start #
|
|
1188
|
+
pnpm start # ${START_SCRIPT} — no tsx at runtime
|
|
1168
1189
|
pnpm start:dev # the server from source with tsx, without building
|
|
1169
1190
|
docker build -t ${options.name} . # the Dockerfile: build stage + plain-node runtime
|
|
1170
1191
|
\`\`\`
|
package/dist/versions.js
CHANGED
|
@@ -11,15 +11,15 @@ export const SCAFFOLD_VERSIONS = {
|
|
|
11
11
|
'@basaltkit/cli': '^1.4.2',
|
|
12
12
|
'@basaltkit/config': '^1.1.2',
|
|
13
13
|
'@basaltkit/core': '^1.6.0',
|
|
14
|
-
'@basaltkit/deploy': '^0.
|
|
14
|
+
'@basaltkit/deploy': '^0.10.0',
|
|
15
15
|
'@basaltkit/env': '^3.1.1',
|
|
16
16
|
'@basaltkit/events': '^1.3.0',
|
|
17
17
|
'@basaltkit/fastify': '^3.0.0',
|
|
18
|
-
'@basaltkit/generator': '^1.
|
|
18
|
+
'@basaltkit/generator': '^1.7.0',
|
|
19
19
|
'@basaltkit/logger': '^1.3.0',
|
|
20
20
|
'@basaltkit/mailer': '^2.1.0',
|
|
21
21
|
'@basaltkit/mcp': '^6.0.0',
|
|
22
|
-
'@basaltkit/prisma': '^4.
|
|
22
|
+
'@basaltkit/prisma': '^4.1.1',
|
|
23
23
|
'@basaltkit/sdk': '^2.1.0',
|
|
24
24
|
'@basaltkit/subscriptions': '^6.0.0',
|
|
25
25
|
'@basaltkit/subscriptions-prisma': '^4.0.0',
|
|
@@ -28,5 +28,5 @@ export const SCAFFOLD_VERSIONS = {
|
|
|
28
28
|
'@basaltkit/tenancy': '^4.0.0',
|
|
29
29
|
'@basaltkit/tenancy-prisma': '^3.0.0',
|
|
30
30
|
'@basaltkit/testing': '^3.0.0',
|
|
31
|
-
'create-basalt': '^1.
|
|
31
|
+
'create-basalt': '^1.15.0',
|
|
32
32
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-basalt",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=22.5.0"
|
|
6
6
|
},
|
|
@@ -21,38 +21,38 @@
|
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@prisma/adapter-pg": "^7.10.
|
|
25
|
-
"@prisma/client": "^7.10.
|
|
26
|
-
"@prisma/client-runtime-utils": "^7.10.
|
|
27
|
-
"@types/node": "^26.6.
|
|
24
|
+
"@prisma/adapter-pg": "^7.10.1",
|
|
25
|
+
"@prisma/client": "^7.10.1",
|
|
26
|
+
"@prisma/client-runtime-utils": "^7.10.1",
|
|
27
|
+
"@types/node": "^26.6.5",
|
|
28
28
|
"@types/pg": "^8.23.1",
|
|
29
|
-
"pg": "^8.23.
|
|
30
|
-
"prisma": "^7.10.
|
|
31
|
-
"tsx": "^4.23.
|
|
29
|
+
"pg": "^8.23.1",
|
|
30
|
+
"prisma": "^7.10.1",
|
|
31
|
+
"tsx": "^4.23.15",
|
|
32
32
|
"typescript": "^7.0.2",
|
|
33
|
-
"vitest": "^5.0.
|
|
34
|
-
"zod": "^4.6.
|
|
33
|
+
"vitest": "^5.0.5",
|
|
34
|
+
"zod": "^4.6.7",
|
|
35
35
|
"@basaltkit/auth": "^5.0.0",
|
|
36
36
|
"@basaltkit/auth-prisma": "^3.0.0",
|
|
37
|
-
"@basaltkit/config": "^1.1.2",
|
|
38
37
|
"@basaltkit/cli": "^1.4.2",
|
|
38
|
+
"@basaltkit/config": "^1.1.2",
|
|
39
39
|
"@basaltkit/core": "^1.6.0",
|
|
40
|
-
"@basaltkit/deploy": "^0.5.0",
|
|
41
40
|
"@basaltkit/events": "^1.3.0",
|
|
41
|
+
"@basaltkit/env": "^3.1.1",
|
|
42
|
+
"@basaltkit/deploy": "^0.10.0",
|
|
42
43
|
"@basaltkit/fastify": "^3.0.0",
|
|
43
|
-
"@basaltkit/
|
|
44
|
+
"@basaltkit/prisma": "^4.1.1",
|
|
44
45
|
"@basaltkit/logger": "^1.3.0",
|
|
45
|
-
"@basaltkit/
|
|
46
|
-
"@basaltkit/prisma": "^4.0.0",
|
|
46
|
+
"@basaltkit/generator": "^1.7.0",
|
|
47
47
|
"@basaltkit/subscriptions": "^6.0.0",
|
|
48
|
+
"@basaltkit/mcp": "^6.0.0",
|
|
48
49
|
"@basaltkit/subscriptions-prisma": "^4.0.0",
|
|
49
|
-
"@basaltkit/teams": "^4.1.1",
|
|
50
50
|
"@basaltkit/teams-prisma": "^1.1.0",
|
|
51
51
|
"@basaltkit/tenancy": "^4.0.0",
|
|
52
52
|
"@basaltkit/tenancy-prisma": "^3.0.0",
|
|
53
|
-
"@basaltkit/env": "^3.1.1",
|
|
54
53
|
"@basaltkit/tsconfig": "^0.24.0",
|
|
55
|
-
"@basaltkit/testing": "^3.0.0"
|
|
54
|
+
"@basaltkit/testing": "^3.0.0",
|
|
55
|
+
"@basaltkit/teams": "^4.1.1"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|