create-basalt 1.4.2 → 1.6.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 +28 -5
- package/dist/args.d.ts +21 -0
- package/dist/args.js +76 -0
- package/dist/cli.js +15 -69
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -2
- package/dist/latest-versions.d.ts +125 -0
- package/dist/latest-versions.js +293 -0
- package/dist/templates-ui.d.ts +1 -1
- package/dist/templates-ui.js +70 -62
- package/dist/templates.d.ts +44 -1
- package/dist/templates.js +204 -48
- package/dist/versions.d.ts +1 -0
- package/dist/versions.js +24 -0
- package/package.json +20 -18
package/dist/templates.js
CHANGED
|
@@ -1,55 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { THIRD_PARTY_VERSIONS } from './latest-versions.js';
|
|
2
|
+
import { SCAFFOLD_VERSIONS } from './versions.js';
|
|
3
|
+
export { SCAFFOLD_VERSIONS } from './versions.js';
|
|
4
|
+
export { THIRD_PARTY_VERSIONS } from './latest-versions.js';
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* The dependency range for a @basaltkit/* package: the current release line
|
|
7
|
+
* (`^<major>.<minor>.0`) of its workspace version, from the generated
|
|
8
|
+
* {@link SCAFFOLD_VERSIONS} map. Throws for an unknown package rather than
|
|
9
|
+
* guessing a range — a stale guess once pinned new apps to frozen 1.x lines.
|
|
7
10
|
*/
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
export const versionOf = (pkg) => {
|
|
12
|
+
const range = SCAFFOLD_VERSIONS[pkg];
|
|
13
|
+
if (range === undefined) {
|
|
14
|
+
throw new Error(`create-basalt: no release line for ${pkg} — add it to scripts/sync-versions.mjs.`);
|
|
15
|
+
}
|
|
16
|
+
return range;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The fallback range for a third-party package the templates emit, from
|
|
20
|
+
* {@link THIRD_PARTY_VERSIONS}. At scaffold time the CLI replaces it with
|
|
21
|
+
* `^<latest>` when the registry's latest is on the same major. Throws for an
|
|
22
|
+
* unknown package so every emitted range lives in that single table.
|
|
23
|
+
*/
|
|
24
|
+
export const thirdPartyVersionOf = (pkg) => {
|
|
25
|
+
const range = THIRD_PARTY_VERSIONS[pkg];
|
|
26
|
+
if (range === undefined) {
|
|
27
|
+
throw new Error(`create-basalt: no fallback range for ${pkg} — add it to THIRD_PARTY_VERSIONS.`);
|
|
28
|
+
}
|
|
29
|
+
return range;
|
|
11
30
|
};
|
|
12
|
-
/**
|
|
13
|
-
export const
|
|
31
|
+
/** True when the scaffold binds users to the tenant they act on (tenancy + auth). */
|
|
32
|
+
export const enforcesMembership = (options) => options.tenancy && options.auth;
|
|
14
33
|
export function packageJson(options) {
|
|
15
|
-
const
|
|
16
|
-
'@basaltkit/config': BASALT_VERSION,
|
|
17
|
-
'@basaltkit/core': BASALT_VERSION,
|
|
18
|
-
'@basaltkit/env': BASALT_VERSION,
|
|
19
|
-
'@basaltkit/events': BASALT_VERSION,
|
|
20
|
-
'@basaltkit/fastify': BASALT_VERSION,
|
|
21
|
-
'@basaltkit/logger': BASALT_VERSION,
|
|
22
|
-
zod: '^4.0.0',
|
|
23
|
-
};
|
|
34
|
+
const basalt = ['@basaltkit/config', '@basaltkit/core', '@basaltkit/env', '@basaltkit/events', '@basaltkit/fastify', '@basaltkit/logger'];
|
|
24
35
|
if (options.tenancy)
|
|
25
|
-
|
|
36
|
+
basalt.push('@basaltkit/tenancy');
|
|
26
37
|
if (options.auth)
|
|
27
|
-
|
|
38
|
+
basalt.push('@basaltkit/auth');
|
|
39
|
+
// Tenancy + auth: @basaltkit/teams binds each user to the tenants they belong
|
|
40
|
+
// to (tenantMembershipPlugin) — without it x-tenant-id/Host is a free choice.
|
|
41
|
+
if (enforcesMembership(options))
|
|
42
|
+
basalt.push('@basaltkit/teams');
|
|
28
43
|
if (options.billing)
|
|
29
|
-
|
|
44
|
+
basalt.push('@basaltkit/subscriptions');
|
|
30
45
|
if (options.mcp)
|
|
31
|
-
|
|
46
|
+
basalt.push('@basaltkit/mcp');
|
|
32
47
|
if (options.cli) {
|
|
33
48
|
// Runtime deps: app.ts uses commandsPlugin (@basaltkit/cli); prisma powers
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
// Apply per-package range overrides. Only @basaltkit/* packages: versionOf
|
|
39
|
-
// falls back to BASALT_VERSION, which would clobber third-party ranges
|
|
40
|
-
// (this once rewrote zod's range to the @basalt base line).
|
|
41
|
-
for (const pkg of Object.keys(dependencies)) {
|
|
42
|
-
if (pkg.startsWith('@basaltkit/'))
|
|
43
|
-
dependencies[pkg] = versionOf(pkg);
|
|
49
|
+
// `basalt prisma:sync` (and prismaPlugin once the app adds a PrismaClient —
|
|
50
|
+
// the scaffold wires no database itself). @basaltkit/generator is dev-only (below).
|
|
51
|
+
basalt.push('@basaltkit/cli', '@basaltkit/prisma');
|
|
44
52
|
}
|
|
53
|
+
const dependencies = { zod: thirdPartyVersionOf('zod') };
|
|
54
|
+
for (const pkg of basalt)
|
|
55
|
+
dependencies[pkg] = versionOf(pkg);
|
|
45
56
|
const devDependencies = {
|
|
46
57
|
'@basaltkit/testing': versionOf('@basaltkit/testing'),
|
|
47
|
-
'@types/node': '^22.15.0',
|
|
48
|
-
'pino-pretty': '^13.0.0',
|
|
49
|
-
tsx: '^4.19.0',
|
|
50
|
-
typescript: '^5.8.0',
|
|
51
|
-
vitest: '^3.1.0',
|
|
52
58
|
};
|
|
59
|
+
for (const pkg of ['@types/node', 'pino-pretty', 'tsx', 'typescript', 'vitest']) {
|
|
60
|
+
devDependencies[pkg] = thirdPartyVersionOf(pkg);
|
|
61
|
+
}
|
|
53
62
|
if (options.cli) {
|
|
54
63
|
// Dev-only: only bin/basalt.ts imports the code generator — the runtime server
|
|
55
64
|
// never does, so the app runs completely without the codegen/AI layer.
|
|
@@ -67,7 +76,9 @@ export function packageJson(options) {
|
|
|
67
76
|
private: true,
|
|
68
77
|
type: 'module',
|
|
69
78
|
scripts: {
|
|
70
|
-
dev
|
|
79
|
+
// dev opts into NODE_ENV=development (src/dev.ts); start does not, so an
|
|
80
|
+
// unset NODE_ENV counts as production and secrets are required.
|
|
81
|
+
dev: 'tsx watch src/dev.ts',
|
|
71
82
|
start: 'tsx src/server.ts',
|
|
72
83
|
test: 'vitest run',
|
|
73
84
|
typecheck: 'tsc --noEmit',
|
|
@@ -104,21 +115,49 @@ export const env = defineEnv({
|
|
|
104
115
|
// Typed against the logger's LogLevel union — a free-form string here fails
|
|
105
116
|
// \`pnpm typecheck\` where loggerPlugin({ level }) consumes it.
|
|
106
117
|
LOG_LEVEL: z.enum(LOG_LEVELS).default('info'),
|
|
107
|
-
|
|
118
|
+
// Unset counts as production (fail-closed); \`pnpm dev\` sets development.
|
|
119
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('production'),${options.auth
|
|
108
120
|
? `
|
|
109
|
-
// Signs JWTs and sessions. secret() is fail-closed: required
|
|
110
|
-
// (no fallback
|
|
121
|
+
// Signs JWTs and sessions. secret() is fail-closed: required unless NODE_ENV
|
|
122
|
+
// is explicitly development/test (no fallback when NODE_ENV is unset),
|
|
123
|
+
// rejected if it looks like a placeholder. \`pnpm dev\` uses devDefault.
|
|
111
124
|
APP_SECRET: secret({ minLength: 32, devDefault: 'dev-only-insecure-secret-please-change-me' }),`
|
|
112
125
|
: ''}
|
|
113
126
|
})
|
|
114
127
|
`;
|
|
115
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* An app-specific env-var prefix derived from the project name
|
|
131
|
+
* (`my-saas` → `MY_SAAS`), suggested for variables whose generic names
|
|
132
|
+
* (`DATABASE_URL`, …) other projects export too.
|
|
133
|
+
*/
|
|
134
|
+
export function envPrefix(name) {
|
|
135
|
+
let base = name
|
|
136
|
+
.replace(/^@[^/]+\//, '')
|
|
137
|
+
.toUpperCase()
|
|
138
|
+
.replace(/[^A-Z0-9]+/g, '_');
|
|
139
|
+
// Trim underscores in linear time (an anchored `_+$` regex backtracks).
|
|
140
|
+
let start = 0;
|
|
141
|
+
let end = base.length;
|
|
142
|
+
while (start < end && base[start] === '_')
|
|
143
|
+
start++;
|
|
144
|
+
while (end > start && base[end - 1] === '_')
|
|
145
|
+
end--;
|
|
146
|
+
base = base.slice(start, end);
|
|
147
|
+
return base === '' || /^\d/.test(base) ? `APP_${base}` : base;
|
|
148
|
+
}
|
|
116
149
|
export function envExample(options) {
|
|
117
|
-
|
|
150
|
+
const prefix = envPrefix(options.name);
|
|
151
|
+
return `# Nothing loads this file for you: copy it to .env and start with
|
|
152
|
+
# \`node --env-file=.env\` / \`tsx --env-file=.env\`, or export the variables.
|
|
153
|
+
# --env-file NEVER overrides a variable already exported in your shell: if
|
|
154
|
+
# another project exported DATABASE_URL, the app silently uses THAT one. Give
|
|
155
|
+
# generic names an app-specific prefix, e.g. ${prefix}_DATABASE_URL.
|
|
156
|
+
PORT=3000
|
|
118
157
|
HOST=0.0.0.0
|
|
119
158
|
LOG_LEVEL=info
|
|
120
159
|
NODE_ENV=development
|
|
121
|
-
${options.auth ? '# Required
|
|
160
|
+
${options.auth ? '# Required unless NODE_ENV is development/test — `pnpm start` refuses to boot\n# without it. Generate a strong one: openssl rand -base64 48\n# APP_SECRET=\n' : ''}`;
|
|
122
161
|
}
|
|
123
162
|
export function appTs(options) {
|
|
124
163
|
const imports = [
|
|
@@ -134,8 +173,11 @@ export function appTs(options) {
|
|
|
134
173
|
`eventsPlugin()`,
|
|
135
174
|
`securityPlugin({
|
|
136
175
|
// Secure response headers (HSTS, X-Frame-Options, nosniff, …) are on by
|
|
137
|
-
// default
|
|
138
|
-
//
|
|
176
|
+
// default, and so is a global per-IP rate limit (auth routes add their
|
|
177
|
+
// own stricter budget). Behind a proxy, make the adapter set request.ip
|
|
178
|
+
// from it; with several replicas, pass a shared \`store\`.
|
|
179
|
+
rateLimit: { limit: 120, windowMs: 60_000 },
|
|
180
|
+
// Add a CORS allow-list if a browser app on another origin calls the API:
|
|
139
181
|
// cors: { origin: ['https://app.example.com'], credentials: true },
|
|
140
182
|
})`,
|
|
141
183
|
];
|
|
@@ -162,6 +204,25 @@ export function appTs(options) {
|
|
|
162
204
|
// password recovery. mfaRoutes(): TOTP enroll/activate/status/disable.
|
|
163
205
|
routesExpression = '[...appRoutes, ...authRoutes(), ...mfaRoutes()]';
|
|
164
206
|
}
|
|
207
|
+
if (enforcesMembership(options)) {
|
|
208
|
+
// Secure by default: the tenant comes from client input (x-tenant-id / Host),
|
|
209
|
+
// so it is identification, never authorization. tenantMembershipPlugin()
|
|
210
|
+
// rejects (403) every authenticated request for a tenant the user is not a
|
|
211
|
+
// member of. Routes that act outside a single tenant opt out with
|
|
212
|
+
// meta: { central: true }.
|
|
213
|
+
imports[0] = `import { createApp, definePlugin } from '@basaltkit/core'`;
|
|
214
|
+
imports.push(`import { TEAMS, teamsPlugin, tenantMembershipPlugin } from '@basaltkit/teams'`);
|
|
215
|
+
plugins.push(`teamsPlugin({
|
|
216
|
+
// TODO: the default membership/invitation stores are in-memory — pass
|
|
217
|
+
// persistent ones (memberships, invitations) before production.
|
|
218
|
+
})`);
|
|
219
|
+
plugins.push(`// Rejects authenticated requests for a tenant the user is not a member of.
|
|
220
|
+
tenantMembershipPlugin()`);
|
|
221
|
+
plugins.push(`// Dev-only seed: each new registrant joins the 'demo' tenant so the scaffold
|
|
222
|
+
// works out of the box. Never in production — add members explicitly there
|
|
223
|
+
// (on tenant creation, or via TEAMS invite()/accept()).
|
|
224
|
+
...(env.NODE_ENV === 'production' ? [] : [demoMembershipSeed()])`);
|
|
225
|
+
}
|
|
165
226
|
if (options.billing) {
|
|
166
227
|
imports.push(`import { definePlans, subscriptionsPlugin } from '@basaltkit/subscriptions'`);
|
|
167
228
|
plugins.push(`subscriptionsPlugin({
|
|
@@ -211,7 +272,21 @@ export function buildApp(options: BuildAppOptions = {}) {
|
|
|
211
272
|
],
|
|
212
273
|
})
|
|
213
274
|
}
|
|
214
|
-
|
|
275
|
+
${enforcesMembership(options)
|
|
276
|
+
? `
|
|
277
|
+
/** Dev-only: adds each new registrant as a member of the 'demo' tenant. */
|
|
278
|
+
function demoMembershipSeed() {
|
|
279
|
+
return definePlugin({
|
|
280
|
+
name: 'app:demo-membership-seed',
|
|
281
|
+
register({ container, hooks }) {
|
|
282
|
+
hooks.on('auth:registered', async ({ user }) => {
|
|
283
|
+
await container.get(TEAMS).addMember('demo', user.id, 'member')
|
|
284
|
+
})
|
|
285
|
+
},
|
|
286
|
+
})
|
|
287
|
+
}
|
|
288
|
+
`
|
|
289
|
+
: ''}`;
|
|
215
290
|
}
|
|
216
291
|
export function routesTs(options) {
|
|
217
292
|
const endpoints = [
|
|
@@ -283,12 +358,29 @@ for (const signal of ['SIGINT', 'SIGTERM'] as const) {
|
|
|
283
358
|
}
|
|
284
359
|
`;
|
|
285
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* `pnpm dev` entrypoint. Opts into NODE_ENV=development (dev secret defaults,
|
|
363
|
+
* pretty logs) unless NODE_ENV is already set, then starts the server. Kept out
|
|
364
|
+
* of server.ts on purpose: `pnpm start` runs server.ts directly, where an unset
|
|
365
|
+
* NODE_ENV counts as production and secrets are required (fail-closed).
|
|
366
|
+
*/
|
|
367
|
+
export function devTs() {
|
|
368
|
+
return `// Development entrypoint (\`pnpm dev\`). \`pnpm start\` runs server.ts directly,
|
|
369
|
+
// where an unset NODE_ENV counts as production: secrets are then required.
|
|
370
|
+
process.env['NODE_ENV'] ??= 'development'
|
|
371
|
+
await import('./server.js')
|
|
372
|
+
`;
|
|
373
|
+
}
|
|
286
374
|
export function basaltBin() {
|
|
287
375
|
return `#!/usr/bin/env node
|
|
288
376
|
import { runCli } from '@basaltkit/cli'
|
|
289
377
|
import { generatorCommands } from '@basaltkit/generator'
|
|
290
378
|
import { prismaSyncCommand } from '@basaltkit/prisma'
|
|
291
|
-
|
|
379
|
+
|
|
380
|
+
// Dev tooling: opt into development defaults unless NODE_ENV is already set
|
|
381
|
+
// (imported dynamically below so env.ts is evaluated after this line).
|
|
382
|
+
process.env['NODE_ENV'] ??= 'development'
|
|
383
|
+
const { buildApp } = await import('../src/app.js')
|
|
292
384
|
|
|
293
385
|
// The 'basalt' CLI: boots the app WITH the dev/CLI commands, runs one, shuts down.
|
|
294
386
|
// The dev tools (@basaltkit/generator; add @basaltkit/ai for ai:*) are imported
|
|
@@ -362,6 +454,18 @@ pnpm install
|
|
|
362
454
|
pnpm dev # API on http://localhost:3000
|
|
363
455
|
pnpm test
|
|
364
456
|
\`\`\`
|
|
457
|
+
|
|
458
|
+
## Environment
|
|
459
|
+
|
|
460
|
+
\`src/env.ts\` validates \`process.env\` — nothing loads \`.env\` for you. Copy
|
|
461
|
+
\`.env.example\` to \`.env\` and launch with \`--env-file=.env\` (Node/tsx), or
|
|
462
|
+
export the variables.
|
|
463
|
+
|
|
464
|
+
**\`--env-file\` never overrides a variable that is already exported.** In a shell
|
|
465
|
+
where another project exported \`DATABASE_URL\` (or \`PORT\`), this app boots
|
|
466
|
+
against THAT value and only fails on the first request that touches it. Give
|
|
467
|
+
generic names an app-specific prefix — \`${envPrefix(options.name)}_DATABASE_URL\` rather than
|
|
468
|
+
\`DATABASE_URL\` — and check \`env | grep DATABASE_URL\` when in doubt.
|
|
365
469
|
${options.cli
|
|
366
470
|
? `
|
|
367
471
|
## The \`basalt\` CLI
|
|
@@ -375,6 +479,18 @@ pnpm basalt make:service Project # a single artifact (--force to overwrite)
|
|
|
375
479
|
|
|
376
480
|
Generated resources land in \`src/modules/<name>/\`. Register the generated
|
|
377
481
|
plugin in \`src/app.ts\` to wire it up.
|
|
482
|
+
|
|
483
|
+
With pnpm 11, \`pnpm basalt …\` first verifies dependencies
|
|
484
|
+
(\`verifyDepsBeforeRun\`, default \`install\`): when any workspace project is out
|
|
485
|
+
of sync it runs \`pnpm install\` — network included — before the command. To
|
|
486
|
+
run the CLI without that check, call it directly:
|
|
487
|
+
|
|
488
|
+
\`\`\`bash
|
|
489
|
+
node_modules/.bin/tsx bin/basalt.ts make:resource Project
|
|
490
|
+
\`\`\`
|
|
491
|
+
|
|
492
|
+
or set \`verifyDepsBeforeRun: warn\` in \`pnpm-workspace.yaml\` (a conscious
|
|
493
|
+
choice: you then run \`pnpm install\` yourself after dependency changes).
|
|
378
494
|
`
|
|
379
495
|
: ''}${options.ui
|
|
380
496
|
? `
|
|
@@ -433,6 +549,29 @@ export function mcpJson(_options) {
|
|
|
433
549
|
},
|
|
434
550
|
}, null, 2)}\n`;
|
|
435
551
|
}
|
|
552
|
+
/**
|
|
553
|
+
* Keeps secrets and local state out of Docker build contexts, so a
|
|
554
|
+
* `COPY . .` can never bake `.env` or private keys into an image layer. Every
|
|
555
|
+
* rule is `**`-prefixed: .dockerignore patterns are anchored at the context
|
|
556
|
+
* root, so a bare `.env` or `*.pem` would still let `prisma/.env` or
|
|
557
|
+
* `certs/server.key` through.
|
|
558
|
+
*/
|
|
559
|
+
export function dockerignore() {
|
|
560
|
+
return `**/.env
|
|
561
|
+
**/.env.*
|
|
562
|
+
!**/.env.example
|
|
563
|
+
**/.npmrc
|
|
564
|
+
**/.git
|
|
565
|
+
**/node_modules
|
|
566
|
+
**/coverage
|
|
567
|
+
**/*.log
|
|
568
|
+
**/*.pem
|
|
569
|
+
**/*.key
|
|
570
|
+
**/*.p12
|
|
571
|
+
**/*.pfx
|
|
572
|
+
**/.DS_Store
|
|
573
|
+
`;
|
|
574
|
+
}
|
|
436
575
|
export function gitignore() {
|
|
437
576
|
return `node_modules/
|
|
438
577
|
dist/
|
|
@@ -447,6 +586,12 @@ dist/
|
|
|
447
586
|
* msgpackr-extract (optional native accelerator via BullMQ) is declined —
|
|
448
587
|
* msgpackr falls back to pure JS. With --ui, `web` is a workspace member so
|
|
449
588
|
* its own dependencies resolve.
|
|
589
|
+
*
|
|
590
|
+
* pnpm 11 notes (BK-002), spelled out in the file because both bite silently:
|
|
591
|
+
* `minimumReleaseAgeExclude` is evaluated first-match-wins BY PACKAGE NAME, so
|
|
592
|
+
* per-version exclusions of one package must be a single `||` union entry; and
|
|
593
|
+
* `verifyDepsBeforeRun` defaults to `install`, so any `pnpm <script>` may run
|
|
594
|
+
* `pnpm install` first — `warn` is offered commented out, never set for you.
|
|
450
595
|
*/
|
|
451
596
|
export function pnpmWorkspaceYaml(options) {
|
|
452
597
|
return `${options.ui
|
|
@@ -460,5 +605,16 @@ export function pnpmWorkspaceYaml(options) {
|
|
|
460
605
|
# pnpm's minimumReleaseAge policy so \`pnpm up\` is never blocked on a fresh release.
|
|
461
606
|
minimumReleaseAgeExclude:
|
|
462
607
|
- '@basaltkit/*'
|
|
608
|
+
# To let specific versions of ONE package bypass the policy, write ONE entry
|
|
609
|
+
# with a \`||\` union. pnpm evaluates this list first match wins by package
|
|
610
|
+
# name, so a second '<name>@<version>' entry for the same package is ignored:
|
|
611
|
+
# - '@types/node@22.20.4 || 26.6.2'
|
|
612
|
+
|
|
613
|
+
# pnpm 11 checks dependencies before every \`pnpm <script>\` / \`pnpm exec\`
|
|
614
|
+
# (verifyDepsBeforeRun defaults to \`install\`): when node_modules is out of sync
|
|
615
|
+
# with ANY workspace project's manifest, it runs \`pnpm install\` first — network
|
|
616
|
+
# and supply-chain checks included. To opt out consciously (you then run
|
|
617
|
+
# \`pnpm install\` yourself after dependency changes), uncomment:
|
|
618
|
+
# verifyDepsBeforeRun: warn
|
|
463
619
|
`;
|
|
464
620
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SCAFFOLD_VERSIONS: Readonly<Record<string, string>>;
|
package/dist/versions.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// GENERATED by scripts/sync-versions.mjs (runs before every build) — do not edit.
|
|
2
|
+
// The dependency range a new app gets for each @basaltkit/* package: the
|
|
3
|
+
// current release line (^<major>.<minor>.0) of the workspace version.
|
|
4
|
+
export const SCAFFOLD_VERSIONS = {
|
|
5
|
+
'@basaltkit/admin': '^2.0.0',
|
|
6
|
+
'@basaltkit/admin-shadcn': '^1.1.0',
|
|
7
|
+
'@basaltkit/ai-mcp': '^0.1.0',
|
|
8
|
+
'@basaltkit/auth': '^3.1.0',
|
|
9
|
+
'@basaltkit/cli': '^1.2.0',
|
|
10
|
+
'@basaltkit/config': '^1.1.0',
|
|
11
|
+
'@basaltkit/core': '^1.3.0',
|
|
12
|
+
'@basaltkit/env': '^3.0.0',
|
|
13
|
+
'@basaltkit/events': '^1.3.0',
|
|
14
|
+
'@basaltkit/fastify': '^2.2.0',
|
|
15
|
+
'@basaltkit/generator': '^1.4.0',
|
|
16
|
+
'@basaltkit/logger': '^1.3.0',
|
|
17
|
+
'@basaltkit/mcp': '^3.0.0',
|
|
18
|
+
'@basaltkit/prisma': '^2.1.0',
|
|
19
|
+
'@basaltkit/sdk': '^2.0.0',
|
|
20
|
+
'@basaltkit/subscriptions': '^4.0.0',
|
|
21
|
+
'@basaltkit/teams': '^3.0.0',
|
|
22
|
+
'@basaltkit/tenancy': '^2.0.0',
|
|
23
|
+
'@basaltkit/testing': '^2.0.0',
|
|
24
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-basalt",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=22.5.0"
|
|
6
6
|
},
|
|
@@ -21,24 +21,25 @@
|
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@types/node": "^26.
|
|
24
|
+
"@types/node": "^26.6.1",
|
|
25
25
|
"typescript": "^7.0.2",
|
|
26
|
-
"vitest": "^
|
|
27
|
-
"zod": "^
|
|
28
|
-
"@basaltkit/auth": "^1.
|
|
29
|
-
"@basaltkit/cli": "^1.2.3",
|
|
26
|
+
"vitest": "^5.0.1",
|
|
27
|
+
"zod": "^4.6.5",
|
|
28
|
+
"@basaltkit/auth": "^3.1.0",
|
|
30
29
|
"@basaltkit/config": "^1.1.2",
|
|
31
|
-
"@basaltkit/core": "^1.3.
|
|
32
|
-
"@basaltkit/env": "^
|
|
33
|
-
"@basaltkit/
|
|
34
|
-
"@basaltkit/
|
|
35
|
-
"@basaltkit/generator": "^1.
|
|
36
|
-
"@basaltkit/logger": "^1.
|
|
37
|
-
"@basaltkit/mcp": "^
|
|
38
|
-
"@basaltkit/prisma": "^1.
|
|
39
|
-
"@basaltkit/
|
|
40
|
-
"@basaltkit/
|
|
41
|
-
"@basaltkit/
|
|
30
|
+
"@basaltkit/core": "^1.3.2",
|
|
31
|
+
"@basaltkit/env": "^3.0.0",
|
|
32
|
+
"@basaltkit/cli": "^1.2.5",
|
|
33
|
+
"@basaltkit/events": "^1.3.0",
|
|
34
|
+
"@basaltkit/generator": "^1.4.0",
|
|
35
|
+
"@basaltkit/logger": "^1.3.0",
|
|
36
|
+
"@basaltkit/mcp": "^3.0.0",
|
|
37
|
+
"@basaltkit/prisma": "^2.1.0",
|
|
38
|
+
"@basaltkit/teams": "^3.0.1",
|
|
39
|
+
"@basaltkit/fastify": "^2.2.0",
|
|
40
|
+
"@basaltkit/tenancy": "^2.0.0",
|
|
41
|
+
"@basaltkit/testing": "^2.0.2",
|
|
42
|
+
"@basaltkit/subscriptions": "^4.0.0",
|
|
42
43
|
"@basaltkit/tsconfig": "^0.24.0"
|
|
43
44
|
},
|
|
44
45
|
"publishConfig": {
|
|
@@ -61,7 +62,8 @@
|
|
|
61
62
|
"boilerplate"
|
|
62
63
|
],
|
|
63
64
|
"scripts": {
|
|
64
|
-
"build": "tsc -p tsconfig.build.json",
|
|
65
|
+
"build": "node scripts/sync-versions.mjs && tsc -p tsconfig.build.json",
|
|
66
|
+
"sync-versions": "node scripts/sync-versions.mjs",
|
|
65
67
|
"test": "vitest run",
|
|
66
68
|
"typecheck": "tsc --noEmit"
|
|
67
69
|
}
|