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/README.md +161 -9
- package/dist/args.d.ts +1 -1
- package/dist/args.js +11 -0
- package/dist/bin-template.d.ts +23 -0
- package/dist/bin-template.js +140 -0
- package/dist/cli.js +44 -5
- package/dist/index.d.ts +9 -1
- package/dist/index.js +32 -26
- package/dist/latest-versions.d.ts +31 -2
- package/dist/latest-versions.js +91 -51
- package/dist/project/add.d.ts +66 -0
- package/dist/project/add.js +322 -0
- package/dist/project/context.d.ts +53 -0
- package/dist/project/context.js +112 -0
- package/dist/project/doctor.d.ts +40 -0
- package/dist/project/doctor.js +350 -0
- package/dist/project/manifest.d.ts +36 -0
- package/dist/project/manifest.js +81 -0
- package/dist/project/package-json.d.ts +57 -0
- package/dist/project/package-json.js +161 -0
- package/dist/project/run.d.ts +55 -0
- package/dist/project/run.js +473 -0
- package/dist/project/semver.d.ts +29 -0
- package/dist/project/semver.js +132 -0
- package/dist/project/term.d.ts +24 -0
- package/dist/project/term.js +39 -0
- package/dist/project/update.d.ts +101 -0
- package/dist/project/update.js +302 -0
- package/dist/templates.d.ts +11 -1
- package/dist/templates.js +78 -42
- package/dist/versions.js +15 -14
- package/package.json +20 -20
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1049
|
-
pnpm
|
|
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
|
-
|
|
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
|
|
1157
|
-
#
|
|
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.
|
|
8
|
-
'@basaltkit/auth': '^
|
|
9
|
-
'@basaltkit/auth-prisma': '^
|
|
10
|
-
'@basaltkit/cli': '^1.
|
|
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.
|
|
12
|
+
'@basaltkit/core': '^1.5.0',
|
|
13
13
|
'@basaltkit/env': '^3.1.0',
|
|
14
14
|
'@basaltkit/events': '^1.3.0',
|
|
15
|
-
'@basaltkit/fastify': '^2.
|
|
15
|
+
'@basaltkit/fastify': '^2.5.0',
|
|
16
16
|
'@basaltkit/generator': '^1.5.0',
|
|
17
17
|
'@basaltkit/logger': '^1.3.0',
|
|
18
|
-
'@basaltkit/mcp': '^
|
|
19
|
-
'@basaltkit/prisma': '^
|
|
18
|
+
'@basaltkit/mcp': '^5.0.0',
|
|
19
|
+
'@basaltkit/prisma': '^3.0.0',
|
|
20
20
|
'@basaltkit/sdk': '^2.1.0',
|
|
21
|
-
'@basaltkit/subscriptions': '^
|
|
22
|
-
'@basaltkit/subscriptions-prisma': '^
|
|
23
|
-
'@basaltkit/teams': '^
|
|
24
|
-
'@basaltkit/teams-prisma': '^1.
|
|
25
|
-
'@basaltkit/tenancy': '^
|
|
26
|
-
'@basaltkit/tenancy-prisma': '^
|
|
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.
|
|
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
|
|
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/
|
|
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/
|
|
44
|
-
"@basaltkit/fastify": "^2.
|
|
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": "^
|
|
47
|
-
"@basaltkit/prisma": "^
|
|
48
|
-
"@basaltkit/subscriptions": "^
|
|
49
|
-
"@basaltkit/teams": "^
|
|
50
|
-
"@basaltkit/
|
|
51
|
-
"@basaltkit/
|
|
52
|
-
"@basaltkit/
|
|
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"
|