@webjsdev/cli 0.10.28 → 0.10.29
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/bin/webjs.js +6 -0
- package/lib/create.js +24 -15
- package/lib/saas-template.js +8 -8
- package/package.json +1 -1
- package/templates/AGENTS.md +8 -5
- package/templates/CONVENTIONS.md +5 -4
package/bin/webjs.js
CHANGED
|
@@ -147,6 +147,12 @@ async function main() {
|
|
|
147
147
|
// down on exit so a watcher cannot outlive the server.
|
|
148
148
|
const { readAppTasks } = await import('../lib/app-tasks.js');
|
|
149
149
|
const devTasks = readAppTasks(process.cwd());
|
|
150
|
+
// Load `.env` BEFORE the before-steps (same as `start`, L188), so a
|
|
151
|
+
// `dev.before` `webjs db migrate` sees DATABASE_URL from `.env`. Without
|
|
152
|
+
// this a Postgres dev migrate runs with no connection string and fails
|
|
153
|
+
// (sqlite survives via its `?? 'db/dev.db'` config fallback). The watch
|
|
154
|
+
// child / inline server load `.env` again later (idempotent).
|
|
155
|
+
loadAppEnv(process.cwd());
|
|
150
156
|
await runPhaseBeforeSteps('dev', devTasks.dev.before, process.cwd());
|
|
151
157
|
const killTasks = await startDevParallelTasks(devTasks.dev.parallel, process.cwd());
|
|
152
158
|
process.on('SIGINT', () => { killTasks(); process.exit(0); });
|
package/lib/create.js
CHANGED
|
@@ -314,9 +314,9 @@ export async function scaffoldApp(name, cwd, opts = {}) {
|
|
|
314
314
|
},
|
|
315
315
|
scripts: {
|
|
316
316
|
// No `predev` / `prestart` hooks (#550): the `webjs` block below holds
|
|
317
|
-
// the start orchestration (`webjs db migrate`), run INSIDE `webjs
|
|
318
|
-
// so `npm run start` (
|
|
319
|
-
//
|
|
317
|
+
// the dev + start orchestration (`webjs db migrate`), run INSIDE `webjs
|
|
318
|
+
// dev` / `webjs start`, so `npm run dev` / `start` (thin aliases) behave
|
|
319
|
+
// identically. Both apply pending migrations before serving (#725).
|
|
320
320
|
//
|
|
321
321
|
// Bun runtime (#541): the long-running server scripts (`dev` / `start`)
|
|
322
322
|
// are prefixed `bun --bun` so the app SERVES on Bun. The `--bun` overrides
|
|
@@ -386,16 +386,16 @@ export async function scaffoldApp(name, cwd, opts = {}) {
|
|
|
386
386
|
// into components/ui/ (they import @webjsdev/core, not the kit), and the
|
|
387
387
|
// CLI resolves @webjsdev/ui from its own install.
|
|
388
388
|
},
|
|
389
|
-
//
|
|
390
|
-
//
|
|
391
|
-
// identically.
|
|
392
|
-
//
|
|
389
|
+
// Dev + start task orchestration (#550). `webjs dev` / `webjs start` read
|
|
390
|
+
// `before` and run it in-process, so `npm run dev` / `start` (thin aliases
|
|
391
|
+
// above) behave identically. Both apply pending migrations via `webjs db
|
|
392
|
+
// migrate` (idempotent, a no-op when the db is current), so a freshly
|
|
393
|
+
// generated migration is applied without a manual step (#725). The scaffold
|
|
393
394
|
// uses the Tailwind browser runtime (no CSS build step), so there is no dev
|
|
394
395
|
// `parallel` watcher here; an app that adds the Tailwind CLI puts its
|
|
395
396
|
// `--watch` command under `webjs.dev.parallel`.
|
|
396
397
|
webjs: {
|
|
397
|
-
|
|
398
|
-
// applies pending migrations at boot via `webjs db migrate` (drizzle-kit).
|
|
398
|
+
dev: { before: ['webjs db migrate'] },
|
|
399
399
|
start: { before: ['webjs db migrate'] },
|
|
400
400
|
},
|
|
401
401
|
}, null, 2) + '\n');
|
|
@@ -1388,13 +1388,22 @@ For AI agents, read this before editing scaffolded files:
|
|
|
1388
1388
|
// Single copy-paste line so the user can move from "scaffold done"
|
|
1389
1389
|
// to "dev server up" in one command. The full-stack and saas
|
|
1390
1390
|
// templates ship with @webjsdev/ui already initialised; the api
|
|
1391
|
-
// template has no UI but may add one later.
|
|
1392
|
-
// generate + migrate before the first run (the example User model wants
|
|
1393
|
-
// its table to exist). Drizzle splits Prisma's `migrate dev` into
|
|
1394
|
-
// `db:generate` (schema to SQL) then `db:migrate` (apply).
|
|
1391
|
+
// template has no UI but may add one later.
|
|
1395
1392
|
const installSegment = installed ? '' : `${pm} install && `;
|
|
1396
|
-
|
|
1393
|
+
// The saas example queries the users table on its first request (auth), so it
|
|
1394
|
+
// needs a migration authored first: `db:generate` writes it and the
|
|
1395
|
+
// `webjs.dev.before` migrate applies it on `run dev` (Drizzle splits Prisma's
|
|
1396
|
+
// `migrate dev` into generate-then-migrate). The full-stack / api examples do
|
|
1397
|
+
// not query the db on first paint, so they boot with just `run dev`; once you
|
|
1398
|
+
// add a db route, `db:generate` then `run dev` is the loop (dev auto-migrates).
|
|
1399
|
+
const dbSegment = isSaas ? `${pm} run db:generate && ` : '';
|
|
1397
1400
|
const runCommand = `cd ${name} && ${installSegment}${dbSegment}${pm} run dev`;
|
|
1401
|
+
// Postgres needs a reachable DATABASE_URL before any migrate (sqlite uses a
|
|
1402
|
+
// local file with no .env). Point it at a running database; `dev` / `start`
|
|
1403
|
+
// then apply pending migrations via webjs.*.before.
|
|
1404
|
+
const pgNote = dialect === 'postgres'
|
|
1405
|
+
? `\nPostgres: copy .env.example to .env and set DATABASE_URL to a running database before \`${pm} run dev\`.\n`
|
|
1406
|
+
: '';
|
|
1398
1407
|
// Use `npx webjsdev ui ...` here, not `npx webjs ui ...`. The bare
|
|
1399
1408
|
// `webjs` npm name is owned by an unrelated package; `npx webjs
|
|
1400
1409
|
// <cmd>` would fetch THAT package instead of ours when run outside
|
|
@@ -1410,7 +1419,7 @@ For AI agents, read this before editing scaffolded files:
|
|
|
1410
1419
|
Next steps:
|
|
1411
1420
|
${runCommand}
|
|
1412
1421
|
# → http://localhost:8080
|
|
1413
|
-
|
|
1422
|
+
${pgNote}
|
|
1414
1423
|
Optional:
|
|
1415
1424
|
${uiNote}
|
|
1416
1425
|
`);
|
package/lib/saas-template.js
CHANGED
|
@@ -186,9 +186,10 @@ export async function writeSaasFiles(appDir, opts = {}) {
|
|
|
186
186
|
// ALWAYS once the app modules import: auth() only reads a cookie, no DB
|
|
187
187
|
// query. This is the headline security assertion and it is REAL.
|
|
188
188
|
// The signup, login, and protected-route flow writes + reads a user, so it
|
|
189
|
-
// needs the
|
|
190
|
-
//
|
|
191
|
-
//
|
|
189
|
+
// needs the migrated users table (`npm run db:generate`, then `npm run dev`
|
|
190
|
+
// applies it via webjs.dev.before). Until then those flows error, so the
|
|
191
|
+
// suite probes readiness and skips with a clear message instead of crashing,
|
|
192
|
+
// then runs for real once the db is set up.
|
|
192
193
|
await mkdir(join(appDir, 'test', 'auth'), { recursive: true });
|
|
193
194
|
// The generated comments reference `npm run db:*` setup; bun-ify them so a
|
|
194
195
|
// bun-flavored saas app reads `bun run db:*` (#541; db is Node tooling, so a
|
|
@@ -205,12 +206,11 @@ export async function writeSaasFiles(appDir, opts = {}) {
|
|
|
205
206
|
"const appDir = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');",
|
|
206
207
|
"",
|
|
207
208
|
"// The auth pages + dashboard middleware query the users table via Drizzle.",
|
|
208
|
-
"// Until `npm run db:generate`
|
|
209
|
-
"//
|
|
209
|
+
"// Until `npm run db:generate` has authored the migration (then `npm run dev`",
|
|
210
|
+
"// applies it via webjs.dev.before, or `npm run db:migrate` directly), a",
|
|
211
|
+
"// request hitting those modules 500s; we detect that at the RESPONSE level",
|
|
210
212
|
"// (a 5xx on the dashboard) and SKIP with a clear message rather than report",
|
|
211
|
-
"// a misleading failure. After
|
|
212
|
-
"// npm install && npm run db:generate && npm run db:migrate",
|
|
213
|
-
"// every assertion below runs for real.",
|
|
213
|
+
"// a misleading failure. After the db is set up every assertion runs for real.",
|
|
214
214
|
"process.env.DATABASE_URL ||= 'file:./dev.db';",
|
|
215
215
|
"process.env.AUTH_SECRET ||= 'test-secret-at-least-32-characters-long!!';",
|
|
216
216
|
"",
|
package/package.json
CHANGED
package/templates/AGENTS.md
CHANGED
|
@@ -329,7 +329,7 @@ db/
|
|
|
329
329
|
columns.server.ts column helpers (dialect-specific; the only file to swap for Postgres)
|
|
330
330
|
connection.server.ts opens the driver, exports the \`db\` singleton (import \`db\` from here)
|
|
331
331
|
seed.server.ts optional seed (run via \`webjs db seed\`)
|
|
332
|
-
dev.db SQLite file (gitignored);
|
|
332
|
+
dev.db SQLite file (gitignored); created when migrations apply (\`dev\`/\`start\` run \`webjs db migrate\`)
|
|
333
333
|
migrations/ generated migration SQL (committed)
|
|
334
334
|
drizzle.config.ts drizzle-kit config (root; SQLite by default, --db postgres to switch)
|
|
335
335
|
public/ static assets, served at /public/*
|
|
@@ -387,13 +387,16 @@ lives in the `webjs` block of `package.json` and runs INSIDE
|
|
|
387
387
|
|
|
388
388
|
```jsonc
|
|
389
389
|
"webjs": {
|
|
390
|
+
"dev": { "before": ["webjs db migrate"] },
|
|
390
391
|
"start": { "before": ["webjs db migrate"] }
|
|
391
392
|
}
|
|
392
393
|
```
|
|
393
394
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
395
|
+
Both `dev` and `start` apply pending migrations via `webjs db migrate`
|
|
396
|
+
(idempotent, a no-op when the db is current), so a freshly generated
|
|
397
|
+
migration is applied without a manual step. An app that adds the Tailwind
|
|
398
|
+
CLI puts its `--watch` command under `webjs.dev.parallel` and it runs
|
|
399
|
+
alongside the server, torn down on exit.
|
|
397
400
|
`before` steps run to completion first; a failed `webjs db migrate`
|
|
398
401
|
aborts the boot with a clear message rather than serving a stale schema.
|
|
399
402
|
|
|
@@ -457,7 +460,7 @@ Scripts (all wrap `drizzle-kit`):
|
|
|
457
460
|
- `npm run db:push`: `webjs db push` (push the schema straight to the dev DB)
|
|
458
461
|
- `npm run db:studio`: `webjs db studio` (visual DB browser)
|
|
459
462
|
- `npm run db:seed`: `webjs db seed` (run `db/seed.server.ts`)
|
|
460
|
-
- `webjs.start.before`
|
|
463
|
+
- `webjs.dev.before` and `webjs.start.before` both run `webjs db migrate` inside `webjs dev` / `webjs start` (idempotent; replaces the old `prestart` hook), so after you `db:generate` a migration it is applied on the next boot with no manual `db:migrate` step.
|
|
461
464
|
|
|
462
465
|
Always import `db` from `db/connection.server.ts` (the globalThis-cached
|
|
463
466
|
singleton avoids opening a new connection on every dev-server reload), and
|
package/templates/CONVENTIONS.md
CHANGED
|
@@ -268,11 +268,12 @@ docs". That is the agent's default behavior in a webjs project.
|
|
|
268
268
|
|
|
269
269
|
Every webjs app uses **Drizzle + SQLite** for persistence by default. The
|
|
270
270
|
scaffold ships the `db/` folder (`schema.server.ts`, `columns.server.ts`,
|
|
271
|
-
`connection.server.ts`), the `webjs.
|
|
272
|
-
`webjs db migrate` inside `webjs start` (#550), and the
|
|
271
|
+
`connection.server.ts`), the `webjs.dev.before` + `webjs.start.before` steps
|
|
272
|
+
that run `webjs db migrate` inside `webjs dev` / `webjs start` (#550), and the
|
|
273
273
|
`npm run db:generate` / `db:migrate` / `db:push` / `db:studio` / `db:seed`
|
|
274
|
-
scripts (which route through `webjs db` to drizzle-kit).
|
|
275
|
-
|
|
274
|
+
scripts (which route through `webjs db` to drizzle-kit). The loop after a
|
|
275
|
+
schema change is `db:generate` (authors the migration) then `webjs dev` (the
|
|
276
|
+
`dev.before` step applies it); `db:generate` is never auto-run on boot.
|
|
276
277
|
|
|
277
278
|
**AI agents: these rules are absolute.**
|
|
278
279
|
|