create-basalt 1.12.0 → 1.14.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 CHANGED
@@ -273,7 +273,11 @@ newest release **on the app's current major** (a newer major is listed as
273
273
  `minimumReleaseAge`, read from the project's `pnpm-workspace.yaml` when set) is
274
274
  left for later so the install cannot refuse it. When a framework release
275
275
  declares a peer range the app would not meet (say `zod ^5` while zod is held on
276
- 4), the plan warns before anything is written.
276
+ 4), the plan warns before anything is written. When a framework release
277
+ requires an `@basaltkit/*` peer the app does not list (`@basaltkit/testing` 3
278
+ takes `@basaltkit/mailer`), the plan adds it at its latest version (in
279
+ `dependencies` when a runtime dependency needs it, else `devDependencies`), or
280
+ warns when it cannot; optional peers are never added.
277
281
 
278
282
  Both `package.json` and `web/package.json` are updated, **in place**: only the
279
283
  version strings change — order, indentation and range style (`^`, `~`, exact)
@@ -466,7 +470,7 @@ Detects the manager that invoked the command from `npm_config_user_agent` (or th
466
470
  | --- | --- |
467
471
  | `runProjectCommand(argv, deps)` | Runs `update`/`add`/`doctor`/`info` and returns the exit code; every side effect (output, prompts, package-manager runs, registry fetch, codemods) is injected through `deps` |
468
472
  | `loadProject(dir, pm?)` | Reads an app: package.json (+ `web/`), manifest, detected features and package manager. Throws `NotABasaltAppError` |
469
- | `planUpdate(ctx, { major?, only?, tooling?, registry? })` | The update plan — entries, the full before/after of every file, tooling, warnings, framework majors. Writes nothing |
473
+ | `planUpdate(ctx, { major?, only?, tooling?, registry? })` | The update plan — entries, the full before/after of every file, tooling, warnings, framework majors, required peers it adds (`addedPeers`). Writes nothing |
470
474
  | `planAdd(ctx, feature, { force?, resolveLatest?, registry? })` | The add plan — created/merged/skipped files and manual steps. Writes nothing |
471
475
  | `runDoctor(ctx, options)` | Doctor findings (`{ level: 'ok' \| 'info' \| 'warn' \| 'error', area, message }`) |
472
476
  | `MANIFEST_PATH`, `readManifest(dir)`, `hashContent(text)` | The scaffold manifest |
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { randomBytes } from 'node:crypto';
2
2
  import { mkdir, readdir, writeFile } from 'node:fs/promises';
3
3
  import { dirname, join, resolve } from 'node:path';
4
- import { appTest, appTs, dbTs, devEnvFile, devTs, dockerfile, dockerignore, envExample, envTs, gitignore, mcpJson, basaltBin, packageJson, pnpmWorkspaceYaml, prismaConfigTs, prismaSchema, prismaSeedTs, readme, routesTs, serverTs, tsconfigBuildJson, tsconfigJson, } from './templates.js';
4
+ import { appTest, appTs, dbTs, devEnvFile, devTs, dockerfile, dockerignore, envExample, envTs, deployConfigTs, gitignore, mcpJson, basaltBin, packageJson, pnpmWorkspaceYaml, prismaConfigTs, prismaSchema, prismaSeedTs, readme, routesTs, serverTs, tsconfigBuildJson, tsconfigJson, } from './templates.js';
5
5
  import { uiFiles } from './templates-ui.js';
6
6
  import { INSECURE_SECRET } from './project/doctor.js';
7
7
  import { createManifest, MANIFEST_PATH, serializeManifest } from './project/manifest.js';
@@ -51,6 +51,7 @@ export function scaffoldFiles(options) {
51
51
  'README.md': readme(options),
52
52
  'pnpm-workspace.yaml': pnpmWorkspaceYaml(options),
53
53
  'src/env.ts': envTs(options),
54
+ 'deploy.config.ts': deployConfigTs(options),
54
55
  'src/app.ts': appTs(options),
55
56
  'src/routes.ts': routesTs(options),
56
57
  'src/server.ts': serverTs(),
@@ -114,6 +114,8 @@ export interface LatestInfo {
114
114
  latest?: string;
115
115
  /** `peerDependencies` declared by that latest version. */
116
116
  peers: Record<string, string>;
117
+ /** The peers its `peerDependenciesMeta` marks optional (absent: none). */
118
+ optionalPeers?: string[];
117
119
  /**
118
120
  * Release age of `latest` against the window: `mature` (provably older, or
119
121
  * not probed), `recent` (inside the window) or `unknown` (could not prove it).
@@ -153,6 +153,15 @@ function peersOf(body) {
153
153
  }
154
154
  return peers;
155
155
  }
156
+ /** The peers `peerDependenciesMeta` marks `optional: true`. */
157
+ function optionalPeersOf(body) {
158
+ const raw = body?.peerDependenciesMeta;
159
+ if (!raw || typeof raw !== 'object')
160
+ return [];
161
+ return Object.entries(raw)
162
+ .filter(([, meta]) => typeof meta === 'object' && meta !== null && meta.optional === true)
163
+ .map(([name]) => name);
164
+ }
156
165
  async function lookupLatest(fetchImpl, registry, name, signal) {
157
166
  try {
158
167
  const response = await fetchImpl(latestUrl(registry, name), {
@@ -165,7 +174,9 @@ async function lookupLatest(fetchImpl, registry, name, signal) {
165
174
  return 'miss';
166
175
  const body = (await response.json());
167
176
  const version = body?.version;
168
- return typeof version === 'string' && STABLE_SEMVER.test(version) ? { version, peers: peersOf(body) } : 'miss';
177
+ return typeof version === 'string' && STABLE_SEMVER.test(version)
178
+ ? { version, peers: peersOf(body), optionalPeers: optionalPeersOf(body) }
179
+ : 'miss';
169
180
  }
170
181
  catch {
171
182
  // Network error, per-request timeout, or malformed JSON.
@@ -223,7 +234,7 @@ export async function lookupLatestVersions(names, shouldProbe, options = {}) {
223
234
  const age = windowMs === 0 || !shouldProbe(name, found.version)
224
235
  ? 'mature'
225
236
  : await probeAge(fetchImpl, registry, name, windowMs, now, AbortSignal.any([AbortSignal.timeout(timeoutMs), overall.signal]));
226
- results.set(name, { latest: found.version, peers: found.peers, age });
237
+ results.set(name, { latest: found.version, peers: found.peers, optionalPeers: found.optionalPeers, age });
227
238
  }
228
239
  };
229
240
  const pool = Math.max(1, Math.min(options.concurrency ?? CONCURRENCY, names.length));
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
3
  import { basaltBin } from '../bin-template.js';
4
4
  import { collectDependencies, resolveFileVersions, resolveLatestVersions, } from '../latest-versions.js';
5
- import { appTs, BASALT_PROJECT_SCRIPT, gitignore, mcpJson, pnpmWorkspaceYaml, readme, readmeCliSection, readmeMcpSection, readmeUiSection, routesTs, versionOf, webDevScript, } from '../templates.js';
5
+ import { appTs, BASALT_PROJECT_SCRIPT, gitignore, mcpJson, pnpmWorkspaceYaml, readme, deployConfigTs, readmeCliSection, readmeMcpSection, readmeUiSection, routesTs, versionOf, webDevScript, } from '../templates.js';
6
6
  import { uiFiles } from '../templates-ui.js';
7
7
  import { createManifest, extendManifest, isPristine, MANIFEST_PATH, serializeManifest } from './manifest.js';
8
8
  import { mergePackageJson } from './package-json.js';
@@ -255,6 +255,10 @@ export async function planAdd(ctx, feature, options = {}) {
255
255
  const ignore = await readOptional(ctx.dir, '.gitignore');
256
256
  plannedEdit(b, '.gitignore', ignore, ignore === undefined ? gitignore(next) : ensureGitignore(ignore, ['node_modules/', 'dist/']), 'ignore web/ build output');
257
257
  await plannedReadme(b, regenOptions, '## Web UI', readmeUiSection(next));
258
+ // The deploy builds web/ too (served as web/dist by the proxy).
259
+ if ((await readOptional(ctx.dir, 'deploy.config.ts')) !== undefined) {
260
+ await plannedSource(b, 'deploy.config.ts', regenOptions ? () => deployConfigTs(regenOptions) : undefined, (source) => (/\bweb:/.test(source) ? source : /build: \{ ([^}\n]*) \}/.test(source) ? source.replace(/build: \{ ([^}\n]*) \}/, "build: { $1, web: 'web' }") : undefined), "add web: 'web' to build in deploy.config.ts, so the deploy builds the frontend.");
261
+ }
258
262
  b.notes.push('No CORS change needed: the Vite dev server proxies /api to the API on :3000.');
259
263
  }
260
264
  if (feature === 'cli') {
@@ -76,6 +76,17 @@ export interface UpdatePlan {
76
76
  to: string;
77
77
  changelog: string;
78
78
  }[];
79
+ /**
80
+ * Required `@basaltkit/*` peers of the framework releases the app ends up on
81
+ * that its package.json did not list (testing 3 takes mailer): added at their
82
+ * latest version, in `dependencies` when a runtime dependency needs them.
83
+ */
84
+ addedPeers: {
85
+ name: string;
86
+ range: string;
87
+ section: 'dependencies' | 'devDependencies';
88
+ requiredBy: string[];
89
+ }[];
79
90
  registry: string;
80
91
  }
81
92
  export interface UpdateOptions {
@@ -277,6 +277,50 @@ export async function planUpdate(ctx, options = {}) {
277
277
  }
278
278
  }
279
279
  }
280
+ // A required @basaltkit peer the app never declared: pnpm and npm may
281
+ // auto-install it, but yarn PnP, `auto-install-peers=false` or
282
+ // `--legacy-peer-deps` do not, and `doctor` checks installed versions, not
283
+ // the manifest. Add it at its latest version; when that is impossible
284
+ // (registry, release-age window, out of range), say so.
285
+ const declared = new Set(entries.filter((entry) => entry.file === 'package.json').map((entry) => entry.name));
286
+ const missing = new Map();
287
+ for (const entry of entries) {
288
+ if (!entry.framework || (entry.status !== 'update' && entry.status !== 'current') || entry.file !== 'package.json')
289
+ continue;
290
+ const info = results.get(entry.name);
291
+ for (const [peer, wanted] of Object.entries(info?.peers ?? {})) {
292
+ if (!isFramework(peer) || declared.has(peer) || info?.optionalPeers?.includes(peer))
293
+ continue;
294
+ const prior = missing.get(peer);
295
+ const section = entry.section === 'dependencies' || prior?.section === 'dependencies' ? 'dependencies' : 'devDependencies';
296
+ const requiredBy = [...(prior?.requiredBy ?? []), `${entry.name}@${info?.latest}`];
297
+ missing.set(peer, { wanted: prior?.wanted ?? wanted, requiredBy: [...new Set(requiredBy)], section });
298
+ }
299
+ }
300
+ const addedPeers = [];
301
+ if (missing.size > 0) {
302
+ const peerLookup = await lookupLatestVersions([...missing.keys()].sort(), (name) => !exempt(name), {
303
+ ...options.registry,
304
+ minimumReleaseAge: window,
305
+ });
306
+ const additions = { dependencies: {}, devDependencies: {} };
307
+ for (const [peer, need] of missing) {
308
+ const found = peerLookup.results.get(peer);
309
+ if (found?.latest !== undefined && found.age === 'mature' && satisfies(found.latest, need.wanted) === true) {
310
+ const range = `^${found.latest}`;
311
+ additions[need.section][peer] = range;
312
+ addedPeers.push({ name: peer, range, section: need.section, requiredBy: need.requiredBy });
313
+ }
314
+ else {
315
+ warnings.push(`${need.requiredBy.join(', ')} requires ${peer} ${need.wanted}, which package.json does not list — add it (${ctx.pm} add ${need.section === 'devDependencies' ? '-D ' : ''}${peer})`);
316
+ }
317
+ }
318
+ if (addedPeers.length > 0) {
319
+ const merged = mergePackageJson(files['package.json']?.after ?? ctx.packageJsonText, additions);
320
+ if (merged.changes.length > 0)
321
+ files['package.json'] = { before: ctx.packageJsonText, after: merged.text };
322
+ }
323
+ }
280
324
  const failed = entries.filter((entry) => entry.status === 'failed').map((entry) => entry.name);
281
325
  if (failed.length > 0)
282
326
  warnings.push(`The registry did not answer for ${[...new Set(failed)].join(', ')} — left unchanged.`);
@@ -289,7 +333,7 @@ export async function planUpdate(ctx, options = {}) {
289
333
  changelog: changelogUrl(entry.name),
290
334
  }))
291
335
  .filter((major, i, all) => all.findIndex((other) => other.name === major.name) === i);
292
- return { entries, updates, files, tooling: toolingNotes, manual, warnings, majors, registry };
336
+ return { entries, updates, files, tooling: toolingNotes, manual, warnings, majors, addedPeers, registry };
293
337
  }
294
338
  /** The plan as terminal lines: the update table, then notes, tooling, warnings and majors. */
295
339
  export function renderUpdatePlan(plan, colors) {
@@ -328,6 +372,12 @@ export function renderUpdatePlan(plan, colors) {
328
372
  lines.push(` ${major.name} ${major.from} → ${major.to}: ${major.changelog}`);
329
373
  lines.push(` Upgrade notes: ${DOCS_UPGRADING_URL}`);
330
374
  }
375
+ if (plan.addedPeers.length > 0) {
376
+ lines.push('', colors.bold('Required peers the app did not list (added):'));
377
+ for (const peer of plan.addedPeers) {
378
+ lines.push(` ${colors.cyan(peer.name)} ${peer.range} (${peer.section}) — required by ${peer.requiredBy.join(', ')}`);
379
+ }
380
+ }
331
381
  if (plan.tooling.length > 0) {
332
382
  lines.push('', colors.bold('Project tooling:'));
333
383
  for (const note of plan.tooling)
@@ -20,8 +20,8 @@ export { basaltBin } from './bin-template.js';
20
20
  export { SCAFFOLD_VERSIONS } from './versions.js';
21
21
  export { THIRD_PARTY_VERSIONS } from './latest-versions.js';
22
22
  /**
23
- * The dependency range for a @basaltkit/* package: the current release line
24
- * (`^<major>.<minor>.0`) of its workspace version, from the generated
23
+ * The dependency range for a @basaltkit/* package: its workspace version as
24
+ * the floor (`^<major>.<minor>.<patch>`), from the generated
25
25
  * {@link SCAFFOLD_VERSIONS} map. Throws for an unknown package rather than
26
26
  * guessing a range — a stale guess once pinned new apps to frozen 1.x lines.
27
27
  */
@@ -155,6 +155,18 @@ export declare function mcpJson(_options: ProjectOptions): string;
155
155
  * `certs/server.key` through.
156
156
  */
157
157
  export declare function dockerignore(): string;
158
+ /**
159
+ * The C4 owner label `@basaltkit/deploy` names everything with
160
+ * (`[a-z][a-z0-9-]{1,30}`), from the package name.
161
+ */
162
+ export declare function deployAppName(name: string): string;
163
+ /**
164
+ * `deploy.config.ts` (RFC 0007 §3): what `basalt-deploy init` writes for this
165
+ * scaffold — PM2 behind Apache, a dedicated Postgres when the app has one, the
166
+ * compiled build, the app's own secret generated on the server. Typed by
167
+ * src/env.ts. The domain is the one thing to change.
168
+ */
169
+ export declare function deployConfigTs(options: ProjectOptions): string;
158
170
  export declare function gitignore(options: ProjectOptions): string;
159
171
  /**
160
172
  * pnpm settings: esbuild's build script is required by tsx; with --prisma,
package/dist/templates.js CHANGED
@@ -5,8 +5,8 @@ export { basaltBin } from './bin-template.js';
5
5
  export { SCAFFOLD_VERSIONS } from './versions.js';
6
6
  export { THIRD_PARTY_VERSIONS } from './latest-versions.js';
7
7
  /**
8
- * The dependency range for a @basaltkit/* package: the current release line
9
- * (`^<major>.<minor>.0`) of its workspace version, from the generated
8
+ * The dependency range for a @basaltkit/* package: its workspace version as
9
+ * the floor (`^<major>.<minor>.<patch>`), from the generated
10
10
  * {@link SCAFFOLD_VERSIONS} map. Throws for an unknown package rather than
11
11
  * guessing a range — a stale guess once pinned new apps to frozen 1.x lines.
12
12
  */
@@ -104,9 +104,16 @@ export function packageJson(options) {
104
104
  }
105
105
  const devDependencies = {
106
106
  '@basaltkit/testing': versionOf('@basaltkit/testing'),
107
+ // @basaltkit/testing's peer: fakeMailer() binds the app's own MAILER token,
108
+ // so the copy must be the app's (a package manager that skips peers would
109
+ // otherwise leave `@basaltkit/testing` unable to load).
110
+ '@basaltkit/mailer': versionOf('@basaltkit/mailer'),
107
111
  // The project commands (\`pnpm basalt update | add | doctor | info\`) — dev
108
112
  // tooling with no dependencies of its own, never imported by the app.
109
113
  'create-basalt': versionOf('create-basalt'),
114
+ // Production deploy (deploy.config.ts): dev tooling, run on the server as
115
+ // `node node_modules/@basaltkit/deploy/dist/bin.js run`, never imported by the app.
116
+ '@basaltkit/deploy': versionOf('@basaltkit/deploy'),
110
117
  };
111
118
  for (const pkg of ['@types/node', 'pino-pretty', 'tsx', 'typescript', 'vitest']) {
112
119
  devDependencies[pkg] = thirdPartyVersionOf(pkg);
@@ -725,9 +732,17 @@ model AuthApiKey {
725
732
  expiresAt DateTime?
726
733
  lastUsedAt DateTime?
727
734
  revokedAt DateTime?
735
+ // 3.0: API key lifecycle (migration \`add_api_key_lifecycle\`).
736
+ serviceId String?
737
+ previousHash String? @unique
738
+ previousHashExpiresAt DateTime?
739
+ rotatedAt DateTime?
740
+ allowedIps String[] @default([])
741
+ meta Json?
728
742
 
729
743
  @@index([tenantId])
730
744
  @@index([userId])
745
+ @@index([serviceId])
731
746
  @@map("auth_api_keys")
732
747
  }
733
748
 
@@ -1274,6 +1289,64 @@ export function mcpJson(_options) {
1274
1289
  export function dockerignore() {
1275
1290
  return DOCKERIGNORE;
1276
1291
  }
1292
+ /**
1293
+ * The C4 owner label `@basaltkit/deploy` names everything with
1294
+ * (`[a-z][a-z0-9-]{1,30}`), from the package name.
1295
+ */
1296
+ export function deployAppName(name) {
1297
+ // Trimmed in linear time: an anchored `-+$` regex backtracks on long runs of '-'.
1298
+ const base = name.replace(/^@[^/]+\//, '').toLowerCase().replace(/[^a-z0-9]+/g, '-');
1299
+ let start = 0;
1300
+ while (start < base.length && !(base[start] >= 'a' && base[start] <= 'z'))
1301
+ start++;
1302
+ let end = Math.min(base.length, start + 31);
1303
+ while (end > start && base[end - 1] === '-')
1304
+ end--;
1305
+ const slug = base.slice(start, end);
1306
+ return /^[a-z][a-z0-9-]{1,30}$/.test(slug) ? slug : 'app';
1307
+ }
1308
+ /**
1309
+ * `deploy.config.ts` (RFC 0007 §3): what `basalt-deploy init` writes for this
1310
+ * scaffold — PM2 behind Apache, a dedicated Postgres when the app has one, the
1311
+ * compiled build, the app's own secret generated on the server. Typed by
1312
+ * src/env.ts. The domain is the one thing to change.
1313
+ */
1314
+ export function deployConfigTs(options) {
1315
+ const app = deployAppName(options.name);
1316
+ const helpers = ['apache', 'defineDeploy', ...(options.prisma ? ['dockerInfra'] : []), 'pm2', ...(options.auth ? ['secret'] : [])];
1317
+ const build = [...(options.prisma ? [`prisma: ['prisma.config.ts']`] : []), `script: 'build'`, ...(options.ui ? [`web: 'web'`] : [])];
1318
+ return `/**
1319
+ * Production deploy with @basaltkit/deploy, on one Linux server. Holds no secrets.
1320
+ *
1321
+ * node node_modules/@basaltkit/deploy/dist/bin.js check # this file, without a server (CI)
1322
+ * node node_modules/@basaltkit/deploy/dist/bin.js plan # on the server: what run would do
1323
+ * node node_modules/@basaltkit/deploy/dist/bin.js run
1324
+ *
1325
+ * Rewrite it from the project at any time:
1326
+ * node node_modules/@basaltkit/deploy/dist/bin.js init --force --domain=<host>
1327
+ */
1328
+ import type { env } from './src/env.js'
1329
+ import { ${helpers.join(', ')} } from '@basaltkit/deploy'
1330
+
1331
+ export default defineDeploy<typeof env>({
1332
+ app: '${app}',
1333
+ domain: '${app}.example.com', // the domain the app answers on
1334
+
1335
+ env: {
1336
+ schema: 'src/env.ts',
1337
+ fixed: { NODE_ENV: 'production', HOST: '127.0.0.1' },${options.auth ? `
1338
+ generate: { APP_SECRET: secret(32) },` : ''}
1339
+ },${options.prisma ? `
1340
+ infra: dockerInfra('${app}', { redis: false }),` : ''}
1341
+ build: { ${build.join(', ')} },${options.prisma ? `
1342
+ migrate: { central: true },` : ''}
1343
+
1344
+ runtime: pm2(),
1345
+ proxy: apache(),
1346
+ health: { path: '/health' },
1347
+ })
1348
+ `;
1349
+ }
1277
1350
  export function gitignore(options) {
1278
1351
  return `node_modules/
1279
1352
  dist/
package/dist/versions.js CHANGED
@@ -1,29 +1,32 @@
1
1
  // GENERATED by scripts/sync-versions.mjs (runs before every build) — do not edit.
2
2
  // The dependency range a new app gets for each @basaltkit/* package: the
3
- // current release line (^<major>.<minor>.0) of the workspace version.
3
+ // workspace version as the floor (^<major>.<minor>.<patch>), so a new app never
4
+ // resolves an older patch of the same line.
4
5
  export const SCAFFOLD_VERSIONS = {
5
6
  '@basaltkit/admin': '^2.0.0',
6
- '@basaltkit/admin-shadcn': '^1.1.0',
7
+ '@basaltkit/admin-shadcn': '^1.1.1',
7
8
  '@basaltkit/ai-mcp': '^0.4.0',
8
- '@basaltkit/auth': '^4.2.0',
9
- '@basaltkit/auth-prisma': '^2.1.0',
10
- '@basaltkit/cli': '^1.4.0',
11
- '@basaltkit/config': '^1.1.0',
9
+ '@basaltkit/auth': '^5.0.0',
10
+ '@basaltkit/auth-prisma': '^3.0.0',
11
+ '@basaltkit/cli': '^1.4.1',
12
+ '@basaltkit/config': '^1.1.2',
12
13
  '@basaltkit/core': '^1.6.0',
13
- '@basaltkit/env': '^3.1.0',
14
+ '@basaltkit/deploy': '^0.3.0',
15
+ '@basaltkit/env': '^3.1.1',
14
16
  '@basaltkit/events': '^1.3.0',
15
- '@basaltkit/fastify': '^2.6.0',
17
+ '@basaltkit/fastify': '^3.0.0',
16
18
  '@basaltkit/generator': '^1.6.0',
17
19
  '@basaltkit/logger': '^1.3.0',
18
- '@basaltkit/mcp': '^5.1.0',
19
- '@basaltkit/prisma': '^3.1.0',
20
+ '@basaltkit/mailer': '^2.1.0',
21
+ '@basaltkit/mcp': '^6.0.0',
22
+ '@basaltkit/prisma': '^4.0.0',
20
23
  '@basaltkit/sdk': '^2.1.0',
21
- '@basaltkit/subscriptions': '^5.0.0',
22
- '@basaltkit/subscriptions-prisma': '^3.0.0',
23
- '@basaltkit/teams': '^4.1.0',
24
+ '@basaltkit/subscriptions': '^6.0.0',
25
+ '@basaltkit/subscriptions-prisma': '^4.0.0',
26
+ '@basaltkit/teams': '^4.1.1',
24
27
  '@basaltkit/teams-prisma': '^1.1.0',
25
- '@basaltkit/tenancy': '^3.2.0',
26
- '@basaltkit/tenancy-prisma': '^2.1.0',
27
- '@basaltkit/testing': '^2.0.0',
28
- 'create-basalt': '^1.12.0',
28
+ '@basaltkit/tenancy': '^4.0.0',
29
+ '@basaltkit/tenancy-prisma': '^3.0.0',
30
+ '@basaltkit/testing': '^3.0.0',
31
+ 'create-basalt': '^1.14.0',
29
32
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-basalt",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "engines": {
5
5
  "node": ">=22.5.0"
6
6
  },
@@ -32,26 +32,27 @@
32
32
  "typescript": "^7.0.2",
33
33
  "vitest": "^5.0.1",
34
34
  "zod": "^4.6.5",
35
- "@basaltkit/auth": "^4.2.0",
36
- "@basaltkit/auth-prisma": "^2.1.0",
37
- "@basaltkit/cli": "^1.4.0",
35
+ "@basaltkit/auth": "^5.0.0",
36
+ "@basaltkit/auth-prisma": "^3.0.0",
37
+ "@basaltkit/cli": "^1.4.1",
38
+ "@basaltkit/config": "^1.1.2",
38
39
  "@basaltkit/core": "^1.6.0",
40
+ "@basaltkit/env": "^3.1.1",
39
41
  "@basaltkit/events": "^1.3.0",
40
- "@basaltkit/fastify": "^2.6.0",
41
- "@basaltkit/config": "^1.1.2",
42
+ "@basaltkit/fastify": "^3.0.0",
42
43
  "@basaltkit/generator": "^1.6.0",
43
44
  "@basaltkit/logger": "^1.3.0",
44
- "@basaltkit/env": "^3.1.1",
45
- "@basaltkit/mcp": "^5.1.0",
46
- "@basaltkit/prisma": "^3.1.0",
47
- "@basaltkit/subscriptions": "^5.0.0",
48
- "@basaltkit/subscriptions-prisma": "^3.0.0",
49
- "@basaltkit/teams": "^4.1.0",
50
- "@basaltkit/tenancy": "^3.2.0",
45
+ "@basaltkit/prisma": "^4.0.0",
46
+ "@basaltkit/subscriptions": "^6.0.0",
47
+ "@basaltkit/deploy": "^0.3.0",
48
+ "@basaltkit/mcp": "^6.0.0",
49
+ "@basaltkit/teams": "^4.1.1",
50
+ "@basaltkit/subscriptions-prisma": "^4.0.0",
51
+ "@basaltkit/tenancy-prisma": "^3.0.0",
51
52
  "@basaltkit/teams-prisma": "^1.1.0",
52
- "@basaltkit/tenancy-prisma": "^2.1.0",
53
- "@basaltkit/tsconfig": "^0.24.0",
54
- "@basaltkit/testing": "^2.0.3"
53
+ "@basaltkit/testing": "^3.0.0",
54
+ "@basaltkit/tenancy": "^4.0.0",
55
+ "@basaltkit/tsconfig": "^0.24.0"
55
56
  },
56
57
  "publishConfig": {
57
58
  "access": "public"