create-basalt 1.8.0 → 1.10.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/dist/templates.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { THIRD_PARTY_VERSIONS } from './latest-versions.js';
2
2
  import { SCAFFOLD_VERSIONS } from './versions.js';
3
+ export { basaltBin } from './bin-template.js';
3
4
  export { SCAFFOLD_VERSIONS } from './versions.js';
4
5
  export { THIRD_PARTY_VERSIONS } from './latest-versions.js';
5
6
  /**
@@ -28,6 +29,10 @@ export const thirdPartyVersionOf = (pkg) => {
28
29
  }
29
30
  return range;
30
31
  };
32
+ /** The root `basalt` script of an app without `--cli`: create-basalt's project commands. */
33
+ export const BASALT_PROJECT_SCRIPT = 'create-basalt --project';
34
+ /** The root `dev:web` script of a `--ui` app (web/ is a pnpm workspace member). */
35
+ export const webDevScript = (options) => `pnpm --filter ${options.name}-web dev`;
31
36
  /** True when the scaffold binds users to the tenant they act on (tenancy + auth). */
32
37
  export const enforcesMembership = (options) => options.tenancy && options.auth;
33
38
  export function packageJson(options) {
@@ -76,6 +81,9 @@ export function packageJson(options) {
76
81
  }
77
82
  const devDependencies = {
78
83
  '@basaltkit/testing': versionOf('@basaltkit/testing'),
84
+ // The project commands (\`pnpm basalt update | add | doctor | info\`) — dev
85
+ // tooling with no dependencies of its own, never imported by the app.
86
+ 'create-basalt': versionOf('create-basalt'),
79
87
  };
80
88
  for (const pkg of ['@types/node', 'pino-pretty', 'tsx', 'typescript', 'vitest']) {
81
89
  devDependencies[pkg] = thirdPartyVersionOf(pkg);
@@ -107,7 +115,11 @@ export function packageJson(options) {
107
115
  start: 'tsx src/server.ts',
108
116
  test: 'vitest run',
109
117
  typecheck: 'tsc --noEmit',
110
- ...(options.cli ? { basalt: 'tsx bin/basalt.ts' } : {}),
118
+ // With --cli, bin/basalt.ts serves the generators AND hands the project
119
+ // commands to create-basalt; without it, \`pnpm basalt update\` goes to
120
+ // create-basalt directly (\`create-basalt add cli\` swaps the script).
121
+ basalt: options.cli ? 'tsx bin/basalt.ts' : BASALT_PROJECT_SCRIPT,
122
+ ...(options.ui ? { 'dev:web': webDevScript(options) } : {}),
111
123
  ...(options.prisma
112
124
  ? {
113
125
  // Generate right after install so `pnpm typecheck` has the client
@@ -526,33 +538,6 @@ process.env['NODE_ENV'] ??= 'development'
526
538
  await import('./server.js')
527
539
  `;
528
540
  }
529
- export function basaltBin() {
530
- return `#!/usr/bin/env node
531
- import { runCli } from '@basaltkit/cli'
532
- import { generatorCommands } from '@basaltkit/generator'
533
- import { prismaSyncCommand } from '@basaltkit/prisma'
534
-
535
- // Dev tooling: opt into development defaults unless NODE_ENV is already set
536
- // (imported dynamically below so env.ts is evaluated after this line).
537
- process.env['NODE_ENV'] ??= 'development'
538
- const { buildApp } = await import('../src/app.js')
539
-
540
- // The 'basalt' CLI: boots the app WITH the dev/CLI commands, runs one, shuts down.
541
- // The dev tools (@basaltkit/generator; add @basaltkit/ai for ai:*) are imported
542
- // ONLY here — the runtime server (src/server.ts) never loads them, so the SaaS
543
- // runs without the codegen/AI layer.
544
- // pnpm basalt dev — dev server: route table + watch (--worker for a queue worker)
545
- // pnpm basalt list — show available commands
546
- // pnpm basalt routes — list registered HTTP routes
547
- // pnpm basalt make:resource Project — generate a full resource vertical
548
- // pnpm basalt make:service Project — generate a single artifact (schema/service/…)
549
- const app = buildApp({
550
- logLevel: 'silent',
551
- commands: [...generatorCommands(), prismaSyncCommand()],
552
- })
553
- process.exit(await runCli({ app }))
554
- `;
555
- }
556
541
  /**
557
542
  * The models each `@basaltkit/<domain>-prisma` package needs, copied VERBATIM
558
543
  * from that package's reference `prisma/schema.prisma` — the same blocks
@@ -654,6 +639,36 @@ model AuthTokenVersion {
654
639
  version Int @default(0)
655
640
 
656
641
  @@map("auth_token_versions")
642
+ }
643
+
644
+ model AuthAccountLink {
645
+ // SHA-256 (hex) of provider + NUL + subject — the natural key hashed so the
646
+ // primary key stays short on MySQL (an OIDC \`sub\` may be 255 characters).
647
+ id String @id
648
+ provider String
649
+ subject String
650
+ userId String
651
+ email String
652
+ createdAt DateTime
653
+
654
+ @@index([userId])
655
+ @@map("auth_account_links")
656
+ }
657
+
658
+ model AuthPasskey {
659
+ // SHA-256 (hex) of the credential id (credential ids reach 1 023 bytes).
660
+ id String @id
661
+ credentialId String
662
+ userId String
663
+ publicKey String
664
+ counter BigInt
665
+ transports String?
666
+ deviceName String?
667
+ createdAt DateTime
668
+ lastUsedAt DateTime?
669
+
670
+ @@index([userId])
671
+ @@map("auth_passkeys")
657
672
  }`,
658
673
  teams: `model TeamMembership {
659
674
  tenantId String
@@ -1014,8 +1029,24 @@ database and \`DATABASE_URL\` is read as \`${envPrefix(options.name)}_DATABASE_U
1014
1029
  To drop the fallback entirely (prefixed names only), write
1015
1030
  \`prefix: { value: '${envPrefix(options.name)}', fallback: false }\`. When in doubt about what
1016
1031
  your shell exports: \`env | grep DATABASE_URL\`.
1017
- ${options.cli
1018
- ? `
1032
+
1033
+ ## Keeping it up to date
1034
+
1035
+ \`\`\`bash
1036
+ pnpm basalt update # dependencies → latest (framework always; third-party within its major)
1037
+ pnpm basalt update --dry # preview the table, write nothing
1038
+ pnpm basalt add ui # add a feature later: ui, cli, mcp
1039
+ pnpm basalt doctor # Node, package manager, versions, env and Prisma checks
1040
+ \`\`\`
1041
+
1042
+ \`.basalt/project.json\` records what create-basalt generated (options and file
1043
+ hashes) — commit it: \`add\` and \`update\` use it to tell untouched template
1044
+ files from the ones you edited.
1045
+ ${options.cli ? readmeCliSection(options) : ''}${options.ui ? readmeUiSection(options) : ''}${options.mcp ? readmeMcpSection(options) : ''}`;
1046
+ }
1047
+ /** README section for the \`basalt\` CLI (also appended by \`create-basalt add cli\`). */
1048
+ export function readmeCliSection(_options) {
1049
+ return `
1019
1050
  ## The \`basalt\` CLI
1020
1051
 
1021
1052
  \`\`\`bash
@@ -1039,21 +1070,25 @@ node_modules/.bin/tsx bin/basalt.ts make:resource Project
1039
1070
 
1040
1071
  or set \`verifyDepsBeforeRun: warn\` in \`pnpm-workspace.yaml\` (a conscious
1041
1072
  choice: you then run \`pnpm install\` yourself after dependency changes).
1042
- `
1043
- : ''}${options.ui
1044
- ? `
1073
+ `;
1074
+ }
1075
+ /** README section for the web/ frontend (also appended by \`create-basalt add ui\`). */
1076
+ export function readmeUiSection(options) {
1077
+ return `
1045
1078
  ## Web UI
1046
1079
 
1047
1080
  \`\`\`bash
1048
- pnpm dev # terminal 1 — API on :3000
1049
- pnpm --filter ${options.name}-web dev # terminal 2 — UI on http://localhost:5180
1081
+ pnpm dev # terminal 1 — API on :3000
1082
+ pnpm dev:web # terminal 2 — UI on http://localhost:5180 (pnpm --filter ${options.name}-web dev)
1050
1083
  \`\`\`
1051
1084
 
1052
1085
  Open <http://localhost:5180>. The Vite dev server proxies \`/api\` to the API,
1053
1086
  so there is no CORS to configure${options.auth ? '. Register, then sign in' : ''}.
1054
- `
1055
- : ''}${options.mcp
1056
- ? `
1087
+ `;
1088
+ }
1089
+ /** README section for the MCP server (also appended by \`create-basalt add mcp\`). */
1090
+ export function readmeMcpSection(_options) {
1091
+ return `
1057
1092
  ## MCP server
1058
1093
 
1059
1094
  Read-only routes marked with \`meta.mcp\` in \`src/routes.ts\` (the overview and
@@ -1079,8 +1114,7 @@ app's runtime) with MCP clients such as Claude Code and Claude Desktop. It expos
1079
1114
  \`basalt_make\` (preview by default, writes confined to this project) plus workflow
1080
1115
  prompts. Claude Code picks up \`.mcp.json\` automatically; for Claude Desktop add the
1081
1116
  same server to its config with \`--cwd=<absolute project path>\`.
1082
- `
1083
- : ''}`;
1117
+ `;
1084
1118
  }
1085
1119
  /**
1086
1120
  * A Claude Code / generic MCP client config that registers the dev-only
@@ -1153,10 +1187,12 @@ export function pnpmWorkspaceYaml(options) {
1153
1187
  : ''}allowBuilds:
1154
1188
  esbuild: true
1155
1189
  msgpackr-extract: false
1156
- # @basaltkit/* releases in lockstep, often within hours — exclude the scope from
1157
- # pnpm's minimumReleaseAge policy so \`pnpm up\` is never blocked on a fresh release.
1190
+ # @basaltkit/* releases in lockstep, often within hours — exclude the scope (and
1191
+ # create-basalt, which serves \`pnpm basalt update\`) from pnpm's minimumReleaseAge
1192
+ # policy so an update is never blocked on a fresh release.
1158
1193
  minimumReleaseAgeExclude:
1159
1194
  - '@basaltkit/*'
1195
+ - create-basalt
1160
1196
  # To let specific versions of ONE package bypass the policy, write ONE entry
1161
1197
  # with a \`||\` union. pnpm evaluates this list first match wins by package
1162
1198
  # name, so a second '<name>@<version>' entry for the same package is ignored:
package/dist/versions.js CHANGED
@@ -4,25 +4,26 @@
4
4
  export const SCAFFOLD_VERSIONS = {
5
5
  '@basaltkit/admin': '^2.0.0',
6
6
  '@basaltkit/admin-shadcn': '^1.1.0',
7
- '@basaltkit/ai-mcp': '^0.1.0',
8
- '@basaltkit/auth': '^3.1.0',
9
- '@basaltkit/auth-prisma': '^1.6.0',
10
- '@basaltkit/cli': '^1.2.0',
7
+ '@basaltkit/ai-mcp': '^0.3.0',
8
+ '@basaltkit/auth': '^4.1.0',
9
+ '@basaltkit/auth-prisma': '^2.0.0',
10
+ '@basaltkit/cli': '^1.3.0',
11
11
  '@basaltkit/config': '^1.1.0',
12
- '@basaltkit/core': '^1.4.0',
12
+ '@basaltkit/core': '^1.5.0',
13
13
  '@basaltkit/env': '^3.1.0',
14
14
  '@basaltkit/events': '^1.3.0',
15
- '@basaltkit/fastify': '^2.3.0',
15
+ '@basaltkit/fastify': '^2.5.0',
16
16
  '@basaltkit/generator': '^1.5.0',
17
17
  '@basaltkit/logger': '^1.3.0',
18
- '@basaltkit/mcp': '^3.0.0',
19
- '@basaltkit/prisma': '^2.2.0',
18
+ '@basaltkit/mcp': '^5.0.0',
19
+ '@basaltkit/prisma': '^3.0.0',
20
20
  '@basaltkit/sdk': '^2.1.0',
21
- '@basaltkit/subscriptions': '^4.0.0',
22
- '@basaltkit/subscriptions-prisma': '^2.2.0',
23
- '@basaltkit/teams': '^3.0.0',
24
- '@basaltkit/teams-prisma': '^1.0.0',
25
- '@basaltkit/tenancy': '^2.0.0',
26
- '@basaltkit/tenancy-prisma': '^1.2.0',
21
+ '@basaltkit/subscriptions': '^5.0.0',
22
+ '@basaltkit/subscriptions-prisma': '^3.0.0',
23
+ '@basaltkit/teams': '^4.0.0',
24
+ '@basaltkit/teams-prisma': '^1.1.0',
25
+ '@basaltkit/tenancy': '^3.1.0',
26
+ '@basaltkit/tenancy-prisma': '^2.0.0',
27
27
  '@basaltkit/testing': '^2.0.0',
28
+ 'create-basalt': '^1.10.0',
28
29
  };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "create-basalt",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "engines": {
5
5
  "node": ">=22.5.0"
6
6
  },
7
- "description": "Scaffold a production-shaped Basalt SaaS app: npm create basalt my-saas [--billing] [--ui] [--cli] [--install] [--git]",
7
+ "description": "Scaffold a production-shaped Basalt SaaS app (npm create basalt my-saas [--billing] [--ui] [--cli] [--install] [--git]) — then keep it current: create-basalt update | add | doctor | info",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "sideEffects": false,
@@ -21,10 +21,6 @@
21
21
  "dist"
22
22
  ],
23
23
  "devDependencies": {
24
- "@basaltkit/auth-prisma": "^1.5.1",
25
- "@basaltkit/subscriptions-prisma": "^2.2.3",
26
- "@basaltkit/teams-prisma": "^1.0.3",
27
- "@basaltkit/tenancy-prisma": "^1.2.0",
28
24
  "@prisma/adapter-pg": "^7.10.0",
29
25
  "@prisma/client": "^7.10.0",
30
26
  "@types/node": "^26.6.1",
@@ -34,22 +30,26 @@
34
30
  "typescript": "^7.0.2",
35
31
  "vitest": "^5.0.1",
36
32
  "zod": "^4.6.5",
37
- "@basaltkit/auth": "^3.1.0",
38
- "@basaltkit/cli": "^1.2.5",
39
- "@basaltkit/config": "^1.1.2",
40
- "@basaltkit/core": "^1.4.0",
41
- "@basaltkit/env": "^3.1.0",
33
+ "@basaltkit/core": "^1.5.0",
42
34
  "@basaltkit/events": "^1.3.0",
43
- "@basaltkit/generator": "^1.5.0",
44
- "@basaltkit/fastify": "^2.3.0",
35
+ "@basaltkit/env": "^3.1.1",
36
+ "@basaltkit/fastify": "^2.5.0",
37
+ "@basaltkit/auth": "^4.1.0",
38
+ "@basaltkit/auth-prisma": "^2.0.0",
45
39
  "@basaltkit/logger": "^1.3.0",
46
- "@basaltkit/mcp": "^3.0.0",
47
- "@basaltkit/prisma": "^2.2.0",
48
- "@basaltkit/subscriptions": "^4.0.0",
49
- "@basaltkit/teams": "^3.0.1",
50
- "@basaltkit/tenancy": "^2.0.0",
51
- "@basaltkit/testing": "^2.0.2",
52
- "@basaltkit/tsconfig": "^0.24.0"
40
+ "@basaltkit/mcp": "^5.0.0",
41
+ "@basaltkit/prisma": "^3.0.0",
42
+ "@basaltkit/subscriptions-prisma": "^3.0.0",
43
+ "@basaltkit/teams": "^4.0.0",
44
+ "@basaltkit/generator": "^1.5.0",
45
+ "@basaltkit/cli": "^1.3.0",
46
+ "@basaltkit/tenancy": "^3.1.0",
47
+ "@basaltkit/teams-prisma": "^1.1.0",
48
+ "@basaltkit/tenancy-prisma": "^2.0.0",
49
+ "@basaltkit/testing": "^2.0.3",
50
+ "@basaltkit/subscriptions": "^5.0.0",
51
+ "@basaltkit/tsconfig": "^0.24.0",
52
+ "@basaltkit/config": "^1.1.2"
53
53
  },
54
54
  "publishConfig": {
55
55
  "access": "public"