create-basalt 1.14.2 → 1.16.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 +6 -2
- package/dist/bin-template.js +45 -3
- package/dist/dev-entry.d.ts +3 -2
- package/dist/dev-entry.js +7 -5
- package/dist/project/doctor.js +8 -2
- 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 +34 -17
- package/dist/versions.js +4 -4
- package/package.json +15 -15
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
|
@@ -4,6 +4,8 @@ export declare const PROJECT_COMMANDS_MARKER = "['update', 'add', 'doctor', 'inf
|
|
|
4
4
|
export declare const DEV_PRELUDE_MARKER = "process.loadEnvFile(envFile)";
|
|
5
5
|
/** Marker proving a bin/basalt.ts already runs the generators without booting the app. */
|
|
6
6
|
export declare const GENERATORS_PRELUDE_MARKER = "process.argv[2]?.startsWith('make:')";
|
|
7
|
+
/** Marker proving a bin/basalt.ts already starts `dev` without booting the app. */
|
|
8
|
+
export declare const DEV_SERVER_PRELUDE_MARKER = "if (process.argv[2] === 'dev')";
|
|
7
9
|
export declare function basaltBin(): string;
|
|
8
10
|
/**
|
|
9
11
|
* Hashes of every bin/basalt.ts an earlier create-basalt release generated
|
|
@@ -14,6 +16,7 @@ export declare const LEGACY_BIN_HASHES: ReadonlySet<string>;
|
|
|
14
16
|
export declare const hasProjectCommands: (content: string) => boolean;
|
|
15
17
|
export declare const hasDevPrelude: (content: string) => boolean;
|
|
16
18
|
export declare const hasGeneratorsPrelude: (content: string) => boolean;
|
|
19
|
+
export declare const hasDevServerPrelude: (content: string) => boolean;
|
|
17
20
|
/**
|
|
18
21
|
* Upgrades a template-generated bin/basalt.ts to the current template, step by
|
|
19
22
|
* step: (1) without the project commands, inserts their prelude after the
|
|
@@ -21,8 +24,9 @@ export declare const hasGeneratorsPrelude: (content: string) => boolean;
|
|
|
21
24
|
* longer run before it); (2) without the dev prelude, inserts it right after
|
|
22
25
|
* the project commands and routes the app import through `explainBootFailure`;
|
|
23
26
|
* (3) without the generators prelude, inserts it right before the dev tools
|
|
24
|
-
* are imported for the booted CLI
|
|
25
|
-
*
|
|
27
|
+
* are imported for the booted CLI; (4) without the dev server prelude, inserts
|
|
28
|
+
* it at the same place, after the generators prelude.
|
|
29
|
+
* Deterministic for the known templates — for the latest ones (1.9 to 1.15) the
|
|
26
30
|
* result is exactly {@link basaltBin}.
|
|
27
31
|
*/
|
|
28
32
|
export declare function patchBasaltBin(content: string): string;
|
package/dist/bin-template.js
CHANGED
|
@@ -197,12 +197,31 @@ if (process.argv[2]?.startsWith('make:')) {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
`;
|
|
200
|
+
/**
|
|
201
|
+
* The DEV SERVER PRELUDE, after the generators prelude and still before
|
|
202
|
+
* anything of the app is imported: `basalt dev` must start while the app
|
|
203
|
+
* cannot boot (a variable missing, the database down, code mid-edit) — that
|
|
204
|
+
* is when a watcher is needed. `runDev` boots the app only for the route
|
|
205
|
+
* table, prints why when it does not, and starts the watcher either way.
|
|
206
|
+
*/
|
|
207
|
+
const DEV_SERVER_PRELUDE = `// \`dev\` starts the watcher even while the app cannot boot (database down, a
|
|
208
|
+
// variable missing, code mid-edit): the route table is printed when it boots.
|
|
209
|
+
if (process.argv[2] === 'dev') {
|
|
210
|
+
const { runDev } = await import('@basaltkit/cli')
|
|
211
|
+
process.env['NODE_ENV'] ??= 'development'
|
|
212
|
+
process.exit(await runDev({
|
|
213
|
+
loadApp: async () => (await import('../src/app.js')).buildApp({ logLevel: 'silent' }),
|
|
214
|
+
}))
|
|
215
|
+
}
|
|
216
|
+
`;
|
|
200
217
|
/** Marker proving a bin/basalt.ts already delegates the project commands. */
|
|
201
218
|
export const PROJECT_COMMANDS_MARKER = "['update', 'add', 'doctor', 'info'].includes(process.argv[2]";
|
|
202
219
|
/** Marker proving a bin/basalt.ts already has the dev prelude (.env loading, `upgrade`, env errors). */
|
|
203
220
|
export const DEV_PRELUDE_MARKER = 'process.loadEnvFile(envFile)';
|
|
204
221
|
/** Marker proving a bin/basalt.ts already runs the generators without booting the app. */
|
|
205
222
|
export const GENERATORS_PRELUDE_MARKER = "process.argv[2]?.startsWith('make:')";
|
|
223
|
+
/** Marker proving a bin/basalt.ts already starts `dev` without booting the app. */
|
|
224
|
+
export const DEV_SERVER_PRELUDE_MARKER = "if (process.argv[2] === 'dev')";
|
|
206
225
|
const APP_IMPORT = "await import('../src/app.js')";
|
|
207
226
|
const APP_IMPORT_EXPLAINED = `${APP_IMPORT}.catch(explainBootFailure)`;
|
|
208
227
|
const RUN_CLI = 'process.exit(await runCli({ app })';
|
|
@@ -211,6 +230,7 @@ export function basaltBin() {
|
|
|
211
230
|
${PRELUDE}
|
|
212
231
|
${DEV_PRELUDE}
|
|
213
232
|
${GENERATORS_PRELUDE}
|
|
233
|
+
${DEV_SERVER_PRELUDE}
|
|
214
234
|
// The dev tools are imported dynamically, after the project commands above.
|
|
215
235
|
const { runCli } = await import('@basaltkit/cli')
|
|
216
236
|
const { generatorCommands } = await import('@basaltkit/generator')
|
|
@@ -259,10 +279,14 @@ export const LEGACY_BIN_HASHES = new Set([
|
|
|
259
279
|
'sha256-bd0b6c9c40089a18c2c2f1a70953044d6a74a329d38a72903b494b1f2265a114',
|
|
260
280
|
// 2026-10-08: database diagnoses in explainBootFailure — make:* still booted.
|
|
261
281
|
'sha256-abea8cbfdb41a302cabad7929617f7fc2fe822345aa8db6ff777e923eb0fc96b',
|
|
282
|
+
// 2026-10-25 (create-basalt ≤ 1.15): make:* without a boot — but `dev`
|
|
283
|
+
// booted the app first, so it did not start while the app could not boot.
|
|
284
|
+
'sha256-5c2cf3f431399b961de890af457c7be5f9a0cb810cd96d6bdf080ac942e33f1b',
|
|
262
285
|
]);
|
|
263
286
|
export const hasProjectCommands = (content) => content.includes(PROJECT_COMMANDS_MARKER);
|
|
264
287
|
export const hasDevPrelude = (content) => content.includes(DEV_PRELUDE_MARKER);
|
|
265
288
|
export const hasGeneratorsPrelude = (content) => content.includes(GENERATORS_PRELUDE_MARKER);
|
|
289
|
+
export const hasDevServerPrelude = (content) => content.includes(DEV_SERVER_PRELUDE_MARKER);
|
|
266
290
|
/**
|
|
267
291
|
* Upgrades a template-generated bin/basalt.ts to the current template, step by
|
|
268
292
|
* step: (1) without the project commands, inserts their prelude after the
|
|
@@ -270,8 +294,9 @@ export const hasGeneratorsPrelude = (content) => content.includes(GENERATORS_PRE
|
|
|
270
294
|
* longer run before it); (2) without the dev prelude, inserts it right after
|
|
271
295
|
* the project commands and routes the app import through `explainBootFailure`;
|
|
272
296
|
* (3) without the generators prelude, inserts it right before the dev tools
|
|
273
|
-
* are imported for the booted CLI
|
|
274
|
-
*
|
|
297
|
+
* are imported for the booted CLI; (4) without the dev server prelude, inserts
|
|
298
|
+
* it at the same place, after the generators prelude.
|
|
299
|
+
* Deterministic for the known templates — for the latest ones (1.9 to 1.15) the
|
|
275
300
|
* result is exactly {@link basaltBin}.
|
|
276
301
|
*/
|
|
277
302
|
export function patchBasaltBin(content) {
|
|
@@ -282,6 +307,8 @@ export function patchBasaltBin(content) {
|
|
|
282
307
|
text = addDevPrelude(text);
|
|
283
308
|
if (!hasGeneratorsPrelude(text))
|
|
284
309
|
text = addGeneratorsPrelude(text);
|
|
310
|
+
if (!hasDevServerPrelude(text))
|
|
311
|
+
text = addDevServerPrelude(text);
|
|
285
312
|
return text;
|
|
286
313
|
}
|
|
287
314
|
function addProjectCommands(content) {
|
|
@@ -317,11 +344,19 @@ function addGeneratorsPrelude(content) {
|
|
|
317
344
|
return content;
|
|
318
345
|
return `${content.slice(0, anchor.index)}${GENERATORS_PRELUDE}\n${content.slice(anchor.index)}`;
|
|
319
346
|
}
|
|
347
|
+
/** Inserts the dev server prelude right before the dev tools are imported for the booted CLI (after the generators prelude). */
|
|
348
|
+
function addDevServerPrelude(content) {
|
|
349
|
+
const anchor = /^(?:\/\/ The dev tools are imported dynamically[^\n]*\n)?const \{ runCli \} = await import\('@basaltkit\/cli'\)$/m.exec(content);
|
|
350
|
+
// Without the template's dynamic CLI import, the file is not ours to rearrange.
|
|
351
|
+
if (!anchor || !hasGeneratorsPrelude(content))
|
|
352
|
+
return content;
|
|
353
|
+
return `${content.slice(0, anchor.index)}${DEV_SERVER_PRELUDE}\n${content.slice(anchor.index)}`;
|
|
354
|
+
}
|
|
320
355
|
/** Where a bin/basalt.ts stands: already current, an untouched old template, or user code. */
|
|
321
356
|
export function binStatus(content, manifestHash) {
|
|
322
357
|
if (content === undefined)
|
|
323
358
|
return 'absent';
|
|
324
|
-
if (hasProjectCommands(content) && hasDevPrelude(content) && hasGeneratorsPrelude(content))
|
|
359
|
+
if (hasProjectCommands(content) && hasDevPrelude(content) && hasGeneratorsPrelude(content) && hasDevServerPrelude(content))
|
|
325
360
|
return 'current';
|
|
326
361
|
const hash = hashContent(content);
|
|
327
362
|
return LEGACY_BIN_HASHES.has(hash) || hash === manifestHash ? 'patchable' : 'modified';
|
|
@@ -351,6 +386,13 @@ booted CLI) — it runs the make:* generators without booting the app, so they
|
|
|
351
386
|
work before the database is up or migrated:
|
|
352
387
|
|
|
353
388
|
${GENERATORS_PRELUDE}`);
|
|
389
|
+
}
|
|
390
|
+
if (!hasDevServerPrelude(content)) {
|
|
391
|
+
steps.push(`${steps.length > 0 ? 'Then paste' : 'Paste'} this after the generators prelude (before the dev tools are imported for
|
|
392
|
+
the booted CLI) — \`basalt dev\` then starts its watcher even while the app cannot
|
|
393
|
+
boot (database down, a variable missing):
|
|
394
|
+
|
|
395
|
+
${DEV_SERVER_PRELUDE}`);
|
|
354
396
|
}
|
|
355
397
|
return steps.join('\n');
|
|
356
398
|
}
|
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,7 +382,7 @@ 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 (it lacks some of: .env loading, pre-boot project commands, make:* without booting the app) — `npx create-basalt@latest update` patches it.');
|
|
385
|
+
push('warn', 'tooling', 'bin/basalt.ts is an older template (it lacks some of: .env loading, pre-boot project commands, make:* and dev without booting the app) — `npx create-basalt@latest update` patches it.');
|
|
386
386
|
}
|
|
387
387
|
if (status === 'modified') {
|
|
388
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.');
|
|
@@ -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, hasDevPrelude, hasProjectCommands, manualBinSnippet, patchBasaltBin } from '../bin-template.js';
|
|
3
|
+
import { binStatus, hasDevPrelude, hasGeneratorsPrelude, 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; '}${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)`);
|
|
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; '}${hasGeneratorsPrelude(bin) ? '' : 'runs make:* without booting the app (no database needed to generate code); '}starts \`basalt dev\` even while the app cannot boot (the route table when it does)`);
|
|
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. */
|
|
@@ -625,20 +641,19 @@ for (const signal of ['SIGINT', 'SIGTERM'] as const) {
|
|
|
625
641
|
* semantics — an exported variable wins, the file only fills in what is
|
|
626
642
|
* missing — and opts into NODE_ENV=development (dev secret defaults, pretty
|
|
627
643
|
* logs) unless NODE_ENV is already set, then starts the server. Kept out of
|
|
628
|
-
* server.ts on purpose: `pnpm start` runs server
|
|
629
|
-
*
|
|
630
|
-
*
|
|
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).
|
|
631
647
|
*/
|
|
632
648
|
export function devTs() {
|
|
633
|
-
return `// Development entrypoint (\`pnpm dev\`). \`pnpm start\` runs server
|
|
649
|
+
return `// Development entrypoint (\`pnpm dev\`). \`pnpm start\` runs the compiled server,
|
|
634
650
|
// where an unset NODE_ENV counts as production: secrets are then required.
|
|
635
651
|
import { existsSync } from 'node:fs'
|
|
636
652
|
import { fileURLToPath } from 'node:url'
|
|
637
653
|
|
|
638
654
|
// Development loads .env (when present) like \`node --env-file=.env\`: a variable
|
|
639
655
|
// already exported in your shell still wins, the file only fills in what is
|
|
640
|
-
// missing.
|
|
641
|
-
// comes from the real environment.
|
|
656
|
+
// missing. Only development opts into NODE_ENV=development, below.
|
|
642
657
|
const envFile = fileURLToPath(new URL('../.env', import.meta.url))
|
|
643
658
|
if (existsSync(envFile)) process.loadEnvFile(envFile)
|
|
644
659
|
|
|
@@ -1140,8 +1155,10 @@ scaffold with \`--cli\` — \`pnpm basalt prisma:sync\` does the merge for you.)
|
|
|
1140
1155
|
\`src/env.ts\` validates \`process.env\`. For development, ${options.cli ? '`pnpm dev` and `pnpm basalt` load' : '`pnpm dev` loads'} \`.env\`
|
|
1141
1156
|
automatically — create-basalt wrote one for you: git-ignored, with local
|
|
1142
1157
|
values${options.auth ? ' and a generated secret' : ''}. \`.env.example\` is its committed template.
|
|
1143
|
-
\`pnpm start\` (production, \`${PRODUCTION_ENTRY}\`) loads
|
|
1144
|
-
|
|
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.
|
|
1145
1162
|
|
|
1146
1163
|
The variables are **app-prefixed**: \`${envPrefix(options.name)}_PORT\`,
|
|
1147
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.
|
|
@@ -1168,7 +1185,7 @@ your shell exports: \`env | grep DATABASE_URL\`.
|
|
|
1168
1185
|
|
|
1169
1186
|
\`\`\`bash
|
|
1170
1187
|
pnpm build # tsc -p tsconfig.build.json → dist/ (src only)
|
|
1171
|
-
pnpm start #
|
|
1188
|
+
pnpm start # ${START_SCRIPT} — no tsx at runtime
|
|
1172
1189
|
pnpm start:dev # the server from source with tsx, without building
|
|
1173
1190
|
docker build -t ${options.name} . # the Dockerfile: build stage + plain-node runtime
|
|
1174
1191
|
\`\`\`
|
package/dist/versions.js
CHANGED
|
@@ -8,10 +8,10 @@ export const SCAFFOLD_VERSIONS = {
|
|
|
8
8
|
'@basaltkit/ai-mcp': '^0.4.0',
|
|
9
9
|
'@basaltkit/auth': '^5.0.0',
|
|
10
10
|
'@basaltkit/auth-prisma': '^3.0.0',
|
|
11
|
-
'@basaltkit/cli': '^1.
|
|
11
|
+
'@basaltkit/cli': '^1.6.0',
|
|
12
12
|
'@basaltkit/config': '^1.1.2',
|
|
13
13
|
'@basaltkit/core': '^1.6.0',
|
|
14
|
-
'@basaltkit/deploy': '^0.
|
|
14
|
+
'@basaltkit/deploy': '^0.10.1',
|
|
15
15
|
'@basaltkit/env': '^3.1.1',
|
|
16
16
|
'@basaltkit/events': '^1.3.0',
|
|
17
17
|
'@basaltkit/fastify': '^3.0.0',
|
|
@@ -19,7 +19,7 @@ export const SCAFFOLD_VERSIONS = {
|
|
|
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.16.0',
|
|
32
32
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-basalt",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.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.
|
|
24
|
+
"@prisma/adapter-pg": "^7.10.1",
|
|
25
|
+
"@prisma/client": "^7.10.1",
|
|
26
|
+
"@prisma/client-runtime-utils": "^7.10.1",
|
|
27
27
|
"@types/node": "^26.6.5",
|
|
28
28
|
"@types/pg": "^8.23.1",
|
|
29
29
|
"pg": "^8.23.1",
|
|
30
|
-
"prisma": "^7.10.
|
|
30
|
+
"prisma": "^7.10.1",
|
|
31
31
|
"tsx": "^4.23.15",
|
|
32
32
|
"typescript": "^7.0.2",
|
|
33
|
-
"vitest": "^5.0.
|
|
34
|
-
"zod": "^4.6.
|
|
35
|
-
"@basaltkit/
|
|
33
|
+
"vitest": "^5.0.5",
|
|
34
|
+
"zod": "^4.6.7",
|
|
35
|
+
"@basaltkit/auth-prisma": "^3.0.0",
|
|
36
36
|
"@basaltkit/config": "^1.1.2",
|
|
37
|
+
"@basaltkit/auth": "^5.0.0",
|
|
37
38
|
"@basaltkit/core": "^1.6.0",
|
|
38
|
-
"@basaltkit/
|
|
39
|
-
"@basaltkit/deploy": "^0.
|
|
39
|
+
"@basaltkit/cli": "^1.6.0",
|
|
40
|
+
"@basaltkit/deploy": "^0.10.1",
|
|
40
41
|
"@basaltkit/env": "^3.1.1",
|
|
41
|
-
"@basaltkit/events": "^1.3.0",
|
|
42
42
|
"@basaltkit/fastify": "^3.0.0",
|
|
43
|
-
"@basaltkit/
|
|
43
|
+
"@basaltkit/events": "^1.3.0",
|
|
44
44
|
"@basaltkit/logger": "^1.3.0",
|
|
45
45
|
"@basaltkit/mcp": "^6.0.0",
|
|
46
|
-
"@basaltkit/prisma": "^4.0.0",
|
|
47
46
|
"@basaltkit/subscriptions": "^6.0.0",
|
|
48
47
|
"@basaltkit/subscriptions-prisma": "^4.0.0",
|
|
49
48
|
"@basaltkit/teams": "^4.1.1",
|
|
49
|
+
"@basaltkit/prisma": "^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/generator": "^1.7.0",
|
|
53
54
|
"@basaltkit/testing": "^3.0.0",
|
|
54
|
-
"@basaltkit/tsconfig": "^0.24.0"
|
|
55
|
-
"@basaltkit/auth": "^5.0.0"
|
|
55
|
+
"@basaltkit/tsconfig": "^0.24.0"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|