create-basalt 1.0.0 → 1.1.1
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/LICENSE +1 -1
- package/dist/{chunk-RFS7HGZ6.js → chunk-TYOPE3RU.js} +41 -21
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/LICENSE
CHANGED
|
@@ -21,12 +21,22 @@ function packageJson(options) {
|
|
|
21
21
|
if (options.billing) dependencies["@basaltkit/subscriptions"] = BASALT_VERSION;
|
|
22
22
|
if (options.cli) {
|
|
23
23
|
dependencies["@basaltkit/cli"] = BASALT_VERSION;
|
|
24
|
-
dependencies["@basaltkit/generator"] = BASALT_VERSION;
|
|
25
24
|
dependencies["@basaltkit/prisma"] = BASALT_VERSION;
|
|
26
25
|
}
|
|
27
26
|
for (const pkg of Object.keys(dependencies)) {
|
|
28
27
|
if (pkg.startsWith("@basaltkit/")) dependencies[pkg] = versionOf(pkg);
|
|
29
28
|
}
|
|
29
|
+
const devDependencies = {
|
|
30
|
+
"@basaltkit/testing": versionOf("@basaltkit/testing"),
|
|
31
|
+
"@types/node": "^22.15.0",
|
|
32
|
+
"pino-pretty": "^13.0.0",
|
|
33
|
+
tsx: "^4.19.0",
|
|
34
|
+
typescript: "^5.8.0",
|
|
35
|
+
vitest: "^3.1.0"
|
|
36
|
+
};
|
|
37
|
+
if (options.cli) {
|
|
38
|
+
devDependencies["@basaltkit/generator"] = versionOf("@basaltkit/generator");
|
|
39
|
+
}
|
|
30
40
|
return `${JSON.stringify(
|
|
31
41
|
{
|
|
32
42
|
name: options.name,
|
|
@@ -41,14 +51,7 @@ function packageJson(options) {
|
|
|
41
51
|
...options.cli ? { basalt: "tsx bin/basalt.ts" } : {}
|
|
42
52
|
},
|
|
43
53
|
dependencies: Object.fromEntries(Object.entries(dependencies).sort()),
|
|
44
|
-
devDependencies:
|
|
45
|
-
"@basaltkit/testing": versionOf("@basaltkit/testing"),
|
|
46
|
-
"@types/node": "^22.15.0",
|
|
47
|
-
"pino-pretty": "^13.0.0",
|
|
48
|
-
tsx: "^4.19.0",
|
|
49
|
-
typescript: "^5.8.0",
|
|
50
|
-
vitest: "^3.1.0"
|
|
51
|
-
}
|
|
54
|
+
devDependencies: Object.fromEntries(Object.entries(devDependencies).sort())
|
|
52
55
|
},
|
|
53
56
|
null,
|
|
54
57
|
2
|
|
@@ -77,7 +80,7 @@ function tsconfigJson() {
|
|
|
77
80
|
`;
|
|
78
81
|
}
|
|
79
82
|
function envTs(options) {
|
|
80
|
-
return `import { defineEnv } from '@basaltkit/env'
|
|
83
|
+
return `import { defineEnv${options.auth ? ", secret" : ""} } from '@basaltkit/env'
|
|
81
84
|
import { z } from 'zod'
|
|
82
85
|
|
|
83
86
|
export const env = defineEnv({
|
|
@@ -85,7 +88,9 @@ export const env = defineEnv({
|
|
|
85
88
|
HOST: z.string().default('0.0.0.0'),
|
|
86
89
|
LOG_LEVEL: z.string().default('info'),
|
|
87
90
|
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),${options.auth ? `
|
|
88
|
-
|
|
91
|
+
// Signs JWTs and sessions. secret() is fail-closed: required in production
|
|
92
|
+
// (no fallback), rejected if it looks like a placeholder. Dev uses devDefault.
|
|
93
|
+
APP_SECRET: secret({ minLength: 32, devDefault: 'dev-only-insecure-secret-please-change-me' }),` : ""}
|
|
89
94
|
})
|
|
90
95
|
`;
|
|
91
96
|
}
|
|
@@ -94,20 +99,26 @@ function envExample(options) {
|
|
|
94
99
|
HOST=0.0.0.0
|
|
95
100
|
LOG_LEVEL=info
|
|
96
101
|
NODE_ENV=development
|
|
97
|
-
${options.auth ? "
|
|
102
|
+
${options.auth ? "# Required in production (the app refuses to boot without it).\n# Generate a strong one: openssl rand -base64 48\n# APP_SECRET=\n" : ""}`;
|
|
98
103
|
}
|
|
99
104
|
function appTs(options) {
|
|
100
105
|
const imports = [
|
|
101
106
|
`import { createApp } from '@basaltkit/core'`,
|
|
102
107
|
`import { configPlugin } from '@basaltkit/config'`,
|
|
103
108
|
`import { eventsPlugin } from '@basaltkit/events'`,
|
|
104
|
-
`import { fastifyPlugin } from '@basaltkit/fastify'`,
|
|
109
|
+
`import { fastifyPlugin, securityPlugin } from '@basaltkit/fastify'`,
|
|
105
110
|
`import { loggerPlugin } from '@basaltkit/logger'`
|
|
106
111
|
];
|
|
107
112
|
const plugins = [
|
|
108
113
|
`configPlugin({ app: { name: '${options.name}' } })`,
|
|
109
114
|
`loggerPlugin({ level: options.logLevel ?? 'info', ...(options.pretty ? { pretty: true } : {}) })`,
|
|
110
|
-
`eventsPlugin()
|
|
115
|
+
`eventsPlugin()`,
|
|
116
|
+
`securityPlugin({
|
|
117
|
+
// Secure response headers (HSTS, X-Frame-Options, nosniff, \u2026) are on by
|
|
118
|
+
// default. Turn on rate limiting and a CORS allow-list for production:
|
|
119
|
+
// rateLimit: { limit: 120, windowMs: 60_000 },
|
|
120
|
+
// cors: { origin: ['https://app.example.com'], credentials: true },
|
|
121
|
+
})`
|
|
111
122
|
];
|
|
112
123
|
let routesExpression = "appRoutes";
|
|
113
124
|
if (options.tenancy) {
|
|
@@ -143,18 +154,19 @@ function appTs(options) {
|
|
|
143
154
|
})`);
|
|
144
155
|
}
|
|
145
156
|
if (options.cli) {
|
|
146
|
-
imports.push(`import { commandsPlugin } from '@basaltkit/cli'`);
|
|
147
|
-
|
|
148
|
-
imports.push(`import { prismaSyncCommand } from '@basaltkit/prisma'`);
|
|
149
|
-
plugins.push(`commandsPlugin([...generatorCommands(), prismaSyncCommand()])`);
|
|
157
|
+
imports.push(`import { commandsPlugin, type CommandDefinition } from '@basaltkit/cli'`);
|
|
158
|
+
plugins.push(`...(options.commands && options.commands.length > 0 ? [commandsPlugin(options.commands)] : [])`);
|
|
150
159
|
}
|
|
151
160
|
plugins.push(`fastifyPlugin({ routes: ${routesExpression} })`);
|
|
161
|
+
const commandsField = options.cli ? `
|
|
162
|
+
/** Dev/CLI commands (make:*, ai:*, prisma:sync) \u2014 passed ONLY by bin/basalt.ts. */
|
|
163
|
+
commands?: CommandDefinition[]` : "";
|
|
152
164
|
return `${imports.join("\n")}
|
|
153
165
|
import { appRoutes } from './routes.js'
|
|
154
166
|
|
|
155
167
|
export interface BuildAppOptions {
|
|
156
168
|
logLevel?: string
|
|
157
|
-
pretty?: boolean
|
|
169
|
+
pretty?: boolean${commandsField}
|
|
158
170
|
}
|
|
159
171
|
|
|
160
172
|
export function buildApp(options: BuildAppOptions = {}) {
|
|
@@ -229,14 +241,22 @@ for (const signal of ['SIGINT', 'SIGTERM'] as const) {
|
|
|
229
241
|
function basaltBin() {
|
|
230
242
|
return `#!/usr/bin/env node
|
|
231
243
|
import { runCli } from '@basaltkit/cli'
|
|
244
|
+
import { generatorCommands } from '@basaltkit/generator'
|
|
245
|
+
import { prismaSyncCommand } from '@basaltkit/prisma'
|
|
232
246
|
import { buildApp } from '../src/app.js'
|
|
233
247
|
|
|
234
|
-
// The 'basalt' CLI: boots the app, runs one
|
|
248
|
+
// The 'basalt' CLI: boots the app WITH the dev/CLI commands, runs one, shuts down.
|
|
249
|
+
// The dev tools (@basaltkit/generator; add @basaltkit/ai for ai:*) are imported
|
|
250
|
+
// ONLY here \u2014 the runtime server (src/server.ts) never loads them, so the SaaS
|
|
251
|
+
// runs without the codegen/AI layer.
|
|
235
252
|
// pnpm basalt list \u2014 show available commands
|
|
236
253
|
// pnpm basalt routes \u2014 list registered HTTP routes
|
|
237
254
|
// pnpm basalt make:resource Project \u2014 generate a full resource vertical
|
|
238
255
|
// pnpm basalt make:service Project \u2014 generate a single artifact (schema/service/\u2026)
|
|
239
|
-
const app = buildApp({
|
|
256
|
+
const app = buildApp({
|
|
257
|
+
logLevel: 'silent',
|
|
258
|
+
commands: [...generatorCommands(), prismaSyncCommand()],
|
|
259
|
+
})
|
|
240
260
|
process.exit(await runCli({ app }))
|
|
241
261
|
`;
|
|
242
262
|
}
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED