create-basalt 1.3.0 → 1.4.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/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawn } from 'node:child_process';
3
3
  import { stdin, stdout } from 'node:process';
4
- import { createProject, detectPackageManager, runWizard, ttyPrompter, TargetNotEmptyError, WizardCancelledError, } from './index.js';
4
+ import { createProject, detectPackageManager, resolveRunDefaults, runWizard, ttyPrompter, TargetNotEmptyError, WizardCancelledError, } from './index.js';
5
5
  const USAGE = `Usage: npm create basalt <name> [options]
6
6
 
7
7
  Options:
@@ -12,8 +12,12 @@ Options:
12
12
  --ui Scaffold a web/ frontend (React + shadcn + SDK)
13
13
  --cli Scaffold the 'basalt' CLI (code generators + commands)
14
14
  --mcp Expose read-only routes as MCP tools at /mcp
15
- --install Install dependencies after scaffolding
15
+ --install Install dependencies (default: yes in an interactive
16
+ terminal, skipped in CI/non-TTY; --no-install to opt out)
17
+ --no-install Never install dependencies
16
18
  --git Initialize a git repository with a first commit
19
+ (same default rule as --install; --no-git to opt out)
20
+ --no-git Never initialize a git repository
17
21
  --pm=<manager> Package manager: pnpm | npm | yarn | bun (default: auto-detect)
18
22
  -y, --yes Skip prompts and accept defaults
19
23
  -h, --help Show this help
@@ -28,8 +32,6 @@ function parseArgs(argv) {
28
32
  ui: false,
29
33
  cli: false,
30
34
  mcp: false,
31
- install: false,
32
- git: false,
33
35
  yes: false,
34
36
  };
35
37
  for (const token of argv) {
@@ -47,8 +49,12 @@ function parseArgs(argv) {
47
49
  flags.mcp = true;
48
50
  else if (token === '--install')
49
51
  flags.install = true;
52
+ else if (token === '--no-install')
53
+ flags.install = false;
50
54
  else if (token === '--git')
51
55
  flags.git = true;
56
+ else if (token === '--no-git')
57
+ flags.git = false;
52
58
  else if (token === '-y' || token === '--yes')
53
59
  flags.yes = true;
54
60
  else if (token.startsWith('--dir='))
@@ -131,21 +137,30 @@ try {
131
137
  console.log(`\nCreated ${result.options.name} in ${result.dir}\n`);
132
138
  for (const file of result.files)
133
139
  console.log(` ${file}`);
134
- if (flags.git) {
140
+ const run_ = resolveRunDefaults({
141
+ install: flags.install,
142
+ git: flags.git,
143
+ isTTY: Boolean(stdin.isTTY),
144
+ ci: Boolean(process.env['CI']),
145
+ });
146
+ if (flags.install === undefined && !run_.interactive) {
147
+ console.log('\nSkipping dependency install (CI/non-interactive) — pass --install to force it.');
148
+ }
149
+ if (run_.git) {
135
150
  console.log('\nInitializing git repository…');
136
151
  const ok = (await run('git', ['init', '-q'], result.dir)) &&
137
152
  (await run('git', ['add', '-A'], result.dir)) &&
138
153
  (await run('git', ['commit', '-q', '-m', 'Initial commit from create-basalt'], result.dir));
139
154
  console.log(ok ? ' git repository initialized.' : ' (skipped — git unavailable or already a repo)');
140
155
  }
141
- if (flags.install) {
156
+ if (run_.install) {
142
157
  console.log(`\nInstalling dependencies with ${pm}…`);
143
158
  const ok = await run(pm, ['install'], result.dir);
144
159
  if (!ok)
145
160
  console.log(` (install failed — run "${pm} install" yourself)`);
146
161
  }
147
162
  const steps = [`cd ${result.dir}`];
148
- if (!flags.install)
163
+ if (!run_.install)
149
164
  steps.push(`${pm} install`);
150
165
  steps.push(`${pm} run dev${flags.ui ? ' # API on :3000' : ''}`);
151
166
  // `web` is wired as a pnpm workspace member (pnpm-workspace.yaml), so its dev
package/dist/index.d.ts CHANGED
@@ -28,6 +28,24 @@ export type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';
28
28
  * `npm_config_user_agent` env var npm/pnpm/yarn/bun all set. Falls back to npm.
29
29
  */
30
30
  export declare function detectPackageManager(userAgent?: string | undefined): PackageManager;
31
+ /**
32
+ * Resolve whether to install dependencies / init git when the flag was not
33
+ * given explicitly (D1, ecosystem review 2026-08): interactive terminals
34
+ * default to YES — `npm create basalt my-app` should end in a runnable app —
35
+ * while CI and non-TTY runs default to NO, so automation never gets a
36
+ * surprise install. An explicit `--install`/`--no-install` (or git flag)
37
+ * always wins over the environment.
38
+ */
39
+ export declare function resolveRunDefaults(input: {
40
+ install?: boolean | undefined;
41
+ git?: boolean | undefined;
42
+ isTTY: boolean;
43
+ ci: boolean;
44
+ }): {
45
+ install: boolean;
46
+ git: boolean;
47
+ interactive: boolean;
48
+ };
31
49
  /** Generates a ready-to-run Basalt app. Does not install dependencies. */
32
50
  export declare function createProject(input: CreateProjectInput): Promise<CreateProjectResult>;
33
51
  export { runWizard, validateProjectName, PRESETS, FEATURES, type WizardResult, type WizardOptions, type FeatureKey } from './wizard.js';
package/dist/index.js CHANGED
@@ -18,6 +18,22 @@ export function detectPackageManager(userAgent = process.env['npm_config_user_ag
18
18
  return name;
19
19
  return 'npm';
20
20
  }
21
+ /**
22
+ * Resolve whether to install dependencies / init git when the flag was not
23
+ * given explicitly (D1, ecosystem review 2026-08): interactive terminals
24
+ * default to YES — `npm create basalt my-app` should end in a runnable app —
25
+ * while CI and non-TTY runs default to NO, so automation never gets a
26
+ * surprise install. An explicit `--install`/`--no-install` (or git flag)
27
+ * always wins over the environment.
28
+ */
29
+ export function resolveRunDefaults(input) {
30
+ const interactive = input.isTTY && !input.ci;
31
+ return {
32
+ interactive,
33
+ install: input.install ?? interactive,
34
+ git: input.git ?? interactive,
35
+ };
36
+ }
21
37
  /** Generates a ready-to-run Basalt app. Does not install dependencies. */
22
38
  export async function createProject(input) {
23
39
  const options = {
package/dist/templates.js CHANGED
@@ -95,12 +95,15 @@ export function tsconfigJson() {
95
95
  }
96
96
  export function envTs(options) {
97
97
  return `import { defineEnv${options.auth ? ', secret' : ''} } from '@basaltkit/env'
98
+ import { LOG_LEVELS } from '@basaltkit/logger'
98
99
  import { z } from 'zod'
99
100
 
100
101
  export const env = defineEnv({
101
102
  PORT: z.coerce.number().default(3000),
102
103
  HOST: z.string().default('0.0.0.0'),
103
- LOG_LEVEL: z.string().default('info'),
104
+ // Typed against the logger's LogLevel union — a free-form string here fails
105
+ // \`pnpm typecheck\` where loggerPlugin({ level }) consumes it.
106
+ LOG_LEVEL: z.enum(LOG_LEVELS).default('info'),
104
107
  NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),${options.auth
105
108
  ? `
106
109
  // Signs JWTs and sessions. secret() is fail-closed: required in production
@@ -123,7 +126,7 @@ export function appTs(options) {
123
126
  `import { configPlugin } from '@basaltkit/config'`,
124
127
  `import { eventsPlugin } from '@basaltkit/events'`,
125
128
  `import { fastifyPlugin, securityPlugin } from '@basaltkit/fastify'`,
126
- `import { loggerPlugin } from '@basaltkit/logger'`,
129
+ `import { loggerPlugin, type LogLevel } from '@basaltkit/logger'`,
127
130
  ];
128
131
  const plugins = [
129
132
  `configPlugin({ app: { name: '${options.name}' } })`,
@@ -197,7 +200,7 @@ export function appTs(options) {
197
200
  import { appRoutes } from './routes.js'
198
201
 
199
202
  export interface BuildAppOptions {
200
- logLevel?: string
203
+ logLevel?: LogLevel
201
204
  pretty?: boolean${commandsField}
202
205
  }
203
206
 
package/dist/wizard.js CHANGED
@@ -70,8 +70,8 @@ export async function runWizard(prompter, options = {}) {
70
70
  prompter.note(` Note: the Web UI is a pnpm workspace — using pnpm instead of ${pm}.`);
71
71
  pm = 'pnpm';
72
72
  }
73
- const install = await prompter.confirm({ message: 'Install dependencies now?', initial: false });
74
- const git = await prompter.confirm({ message: 'Initialize a git repository?', initial: false });
73
+ const install = await prompter.confirm({ message: 'Install dependencies now?', initial: true });
74
+ const git = await prompter.confirm({ message: 'Initialize a git repository?', initial: true });
75
75
  const enabled = FEATURES.filter((f) => featureSet.has(f.value)).map((f) => f.label);
76
76
  prompter.note(`\n Summary\n` +
77
77
  ` name ${name}\n` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-basalt",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "description": "Scaffold a production-shaped Basalt SaaS app: npm create basalt my-saas [--billing] [--ui] [--cli] [--install] [--git]",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,6 +20,21 @@
20
20
  "@types/node": "^26.3.0",
21
21
  "typescript": "^7.0.2",
22
22
  "vitest": "^4.1.11",
23
+ "zod": "^4.0.0",
24
+ "@basaltkit/auth": "^1.6.3",
25
+ "@basaltkit/config": "^1.1.1",
26
+ "@basaltkit/cli": "^1.2.1",
27
+ "@basaltkit/env": "^1.0.1",
28
+ "@basaltkit/core": "^1.3.0",
29
+ "@basaltkit/fastify": "^1.7.0",
30
+ "@basaltkit/generator": "^1.2.0",
31
+ "@basaltkit/events": "^1.0.1",
32
+ "@basaltkit/logger": "^1.2.1",
33
+ "@basaltkit/mcp": "^1.0.3",
34
+ "@basaltkit/subscriptions": "^2.7.0",
35
+ "@basaltkit/tenancy": "^1.4.0",
36
+ "@basaltkit/prisma": "^1.4.2",
37
+ "@basaltkit/testing": "^1.1.0",
23
38
  "@basaltkit/tsconfig": "^0.24.0"
24
39
  },
25
40
  "publishConfig": {