generatesaas 3.2.0 → 3.3.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.
|
@@ -122,8 +122,8 @@ Creates:
|
|
|
122
122
|
`added` files; `unmodified`, `deleted`, and `removed` files have none.
|
|
123
123
|
- `references/update-manifest.json` - lists of added, modified, and removed files,
|
|
124
124
|
plus `renamed` (upstream renames detected by identical content: `[{from, to}]`)
|
|
125
|
-
and `sensitive` (database schema
|
|
126
|
-
|
|
125
|
+
and `sensitive` (database schema and `.env.example` changes, which carry follow-up work:
|
|
126
|
+
a schema push, new env vars)
|
|
127
127
|
|
|
128
128
|
### Step 2: Present Changelog
|
|
129
129
|
|
|
@@ -134,7 +134,7 @@ Each release's notes may be one of two shapes:
|
|
|
134
134
|
- **Curated** - contains explicit `## Breaking`, `## Migration`, `## Features`, `## Fixes` (or similar) sections. Use those sections verbatim; they are authoritative.
|
|
135
135
|
- **Raw** - an auto-generated flat list of change titles (one line per commit or PR, no sections). This is the common case. You can group the titles into features/fixes by reading them, but you **cannot** reliably infer breaking changes or migration steps from titles alone.
|
|
136
136
|
|
|
137
|
-
Also read `sensitive` in `references/update-manifest.json`: database schema changes mean
|
|
137
|
+
Also read `sensitive` in `references/update-manifest.json`: database schema changes mean the live database has to be pushed to match, and may drop or rewrite existing data (see [Database](#database-schema)), and `.env.example` changes mean new or changed environment variables. Mention both in the summary and again in the final post-update steps.
|
|
138
138
|
|
|
139
139
|
Present a clear, organized summary:
|
|
140
140
|
|
|
@@ -143,9 +143,9 @@ Present a clear, organized summary:
|
|
|
143
143
|
> **Breaking changes:** {from a Breaking section, or "⚠️ Not specified in the changelog - review the diffs in Step 7 carefully, especially database/schema and config files"}
|
|
144
144
|
> **New features:** {list}
|
|
145
145
|
> **Bug fixes:** {list}
|
|
146
|
-
> **
|
|
146
|
+
> **Follow-up steps required:** {from a Migration section, or "⚠️ None listed - if this update changes the database schema or required env vars, you may still have follow-up work. I'll flag schema/config changes as we review them."}
|
|
147
147
|
|
|
148
|
-
**Be honest about uncertainty.** Never present an inferred "Breaking changes: None" or "
|
|
148
|
+
**Be honest about uncertainty.** Never present an inferred "Breaking changes: None" or "Follow-up steps: None" as if it were authoritative when the changelog is raw PR titles - say it's not specified and that you'll watch for schema/config/env changes during the file review. A silently-missed schema change (e.g. a new DB column that never reaches the database) is the worst failure mode.
|
|
149
149
|
|
|
150
150
|
Then ask: *"Ready to proceed with the file analysis?"*
|
|
151
151
|
|
|
@@ -341,15 +341,13 @@ Preview first (especially useful in Careful mode or when unsure), then apply:
|
|
|
341
341
|
node __SKILL_ROOT__/generatesaas-update/scripts/apply-auto.js --dry-run # lists every file it would update/create, changes nothing
|
|
342
342
|
node __SKILL_ROOT__/generatesaas-update/scripts/apply-auto.js
|
|
343
343
|
```
|
|
344
|
-
`apply-auto.js` copies only `unmodified` (safe replace) + `new` (any upstream-added file whose tree the buyer has not deleted). It will **never** touch `newInDeletedTree` files, and it aborts without writing anything if any source is missing from staging (no half-applied tree). Report what was applied
|
|
345
|
-
|
|
346
|
-
It also holds back everything under `packages/database/drizzle/` and lists what it skipped. Those are NOT pending work you can copy in afterwards - migrations must be regenerated into the project's own history or they never run. See [Database](#database-schema-migrations).
|
|
344
|
+
`apply-auto.js` copies only `unmodified` (safe replace) + `new` (any upstream-added file whose tree the buyer has not deleted). It will **never** touch `newInDeletedTree` files, and it aborts without writing anything if any source is missing from staging (no half-applied tree). Report what was applied, and mark all auto-update and new file items as `[x]` in the plan.
|
|
347
345
|
|
|
348
346
|
**Careful mode:**
|
|
349
347
|
Present the list of safe auto-updates and new files to the user:
|
|
350
348
|
> These {N} files haven't been customized and can be safely replaced with the new version. {N} new files will be created. Want me to apply all of these, or would you like to review any specific ones first?
|
|
351
349
|
|
|
352
|
-
If the user wants to review specific files, show them the diff for each requested file. Apply only after approval.
|
|
350
|
+
If the user wants to review specific files, show them the diff for each requested file. Apply only after approval.
|
|
353
351
|
|
|
354
352
|
### Step 7: Review Modified Files
|
|
355
353
|
|
|
@@ -539,7 +537,7 @@ This updates `.generatesaas/manifest.json` to the new version, regenerates file
|
|
|
539
537
|
|
|
540
538
|
### Post-update steps
|
|
541
539
|
- Run `pnpm install` if dependencies changed
|
|
542
|
-
-
|
|
540
|
+
- Push the schema if it was updated (`pnpm --filter @repo/database setup` in development)
|
|
543
541
|
- {any other steps from the changelog}
|
|
544
542
|
|
|
545
543
|
### Skipped changes
|
|
@@ -576,28 +574,44 @@ Config files are the most commonly customized.
|
|
|
576
574
|
- Keep user-added business logic intact
|
|
577
575
|
- Watch for new imports or dependency changes
|
|
578
576
|
|
|
579
|
-
### Database (schema
|
|
577
|
+
### Database (schema)
|
|
580
578
|
|
|
581
579
|
- NEVER auto-merge schema files - always present for user review
|
|
582
|
-
- Warn about schema changes
|
|
583
|
-
|
|
584
|
-
**
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
580
|
+
- Warn about schema changes, and say what applying them will do to live data
|
|
581
|
+
|
|
582
|
+
**This boilerplate keeps no migration history.** The schema files under `packages/database/src/db/`
|
|
583
|
+
are the source of truth, and `db:deploy` applies them with `drizzle-kit push` and then verifies the
|
|
584
|
+
live database really matches. There is no `drizzle/` directory, no `generate`, no `migrate`, and
|
|
585
|
+
nothing to regenerate into a project's own history. An upstream schema change is an ordinary file
|
|
586
|
+
change here: merge it after review, then apply it.
|
|
587
|
+
|
|
588
|
+
1. Merge the upstream change into `packages/database/src/db/*.ts` (user review first, as above).
|
|
589
|
+
2. Apply it: `pnpm --filter @repo/database setup` in development, and `db:deploy` on the next
|
|
590
|
+
deploy in production.
|
|
591
|
+
|
|
592
|
+
**Say what push will do BEFORE the user applies it to a database with data in it.** Push makes the
|
|
593
|
+
database match the schema files, and `db:deploy` passes `--force`, so it does not stop to ask:
|
|
594
|
+
|
|
595
|
+
- a new table or column is added, which is safe;
|
|
596
|
+
- a **removed** column or table is **dropped, with its data**;
|
|
597
|
+
- a **narrowed** type is rewritten in place, and Postgres refuses the whole statement when a value
|
|
598
|
+
does not fit - it never truncates one silently.
|
|
599
|
+
|
|
600
|
+
For anything in the last two categories, tell the user what will be dropped or rewritten and let
|
|
601
|
+
them decide, rather than applying it as part of a routine update. If they need the old data, it has
|
|
602
|
+
to be copied somewhere else first; push has no place to put a data transform and no down step.
|
|
603
|
+
|
|
604
|
+
**Push can report success without applying anything.** `drizzle-kit push` prints its error and
|
|
605
|
+
still exits 0 when a change cannot be applied. `db:deploy` is why that no longer matters in
|
|
606
|
+
production: it re-reads the live schema afterwards and fails the boot naming the tables and columns
|
|
607
|
+
that differ. If a user applies a change by hand with `push` instead, have them run `db:deploy`
|
|
608
|
+
after it, or check the column themselves - a green push is not evidence on its own.
|
|
609
|
+
|
|
610
|
+
**A project generated before push-only** may still have `packages/database/drizzle/` and `generate`
|
|
611
|
+
/ `migrate` scripts. Those are vestigial: the update removes the scripts, and the directory can be
|
|
612
|
+
deleted whenever the user is comfortable. Their database is already at whatever state the old
|
|
613
|
+
migrations left it, so the first push simply diffs from there - usually a no-op if the schema
|
|
614
|
+
matched. Review that first push on a production database rather than letting it ride a deploy.
|
|
601
615
|
|
|
602
616
|
### Package Dependencies (`package.json`)
|
|
603
617
|
|
|
@@ -47,9 +47,9 @@ function hashFile(filePath) {
|
|
|
47
47
|
const WALK_EXCLUSIONS = new Set([
|
|
48
48
|
".git", "node_modules", ".pnpm-store", ".env", ".env.test",
|
|
49
49
|
".turbo", ".data", "dist",
|
|
50
|
-
".next", ".svelte-kit", ".wrangler",
|
|
50
|
+
".next", ".next-e2e-web", ".next-e2e-desktop", ".svelte-kit", ".wrangler",
|
|
51
51
|
".devcontainer", "playwright-report", "test-results",
|
|
52
|
-
".drive-out",
|
|
52
|
+
".drive-out", ".mastra",
|
|
53
53
|
"pnpm-lock.yaml",
|
|
54
54
|
]);
|
|
55
55
|
|
|
@@ -10,9 +10,6 @@ const fs = require("node:fs");
|
|
|
10
10
|
const path = require("node:path");
|
|
11
11
|
const { findProjectRoot, ensureDir, STAGING_DIR } = require("./_helpers.js");
|
|
12
12
|
|
|
13
|
-
/** Drizzle migration history. Held back from every auto-copy - see filesToCopy. */
|
|
14
|
-
const MIGRATION_DIR = "packages/database/drizzle/";
|
|
15
|
-
|
|
16
13
|
function main() {
|
|
17
14
|
const root = findProjectRoot();
|
|
18
15
|
if (!root) {
|
|
@@ -44,19 +41,15 @@ function main() {
|
|
|
44
41
|
// handles by prompt (never here).
|
|
45
42
|
const candidates = [...classification.unmodified, ...classification.new];
|
|
46
43
|
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
// history instead, which is only possible if this step leaves them alone.
|
|
54
|
-
const heldMigrations = candidates.filter((f) => f.startsWith(MIGRATION_DIR));
|
|
55
|
-
const filesToCopy = candidates.filter((f) => !f.startsWith(MIGRATION_DIR));
|
|
44
|
+
// NOTHING IS HELD BACK ANY MORE. This used to quarantine `packages/database/drizzle/`,
|
|
45
|
+
// because a pasted-in migration silently never runs. The boilerplate keeps no migration
|
|
46
|
+
// history now - the schema files are the source of truth and `db:deploy` pushes them - so
|
|
47
|
+
// there is no such directory upstream and nothing to quarantine. A schema change arrives as a
|
|
48
|
+
// change to `packages/database/src/db/`, which is an ordinary file like any other here.
|
|
49
|
+
const filesToCopy = candidates;
|
|
56
50
|
|
|
57
51
|
if (filesToCopy.length === 0) {
|
|
58
52
|
console.log("No files to auto-update. All changed files need manual merge.");
|
|
59
|
-
reportHeldMigrations(heldMigrations);
|
|
60
53
|
return;
|
|
61
54
|
}
|
|
62
55
|
|
|
@@ -84,7 +77,6 @@ function main() {
|
|
|
84
77
|
console.log(` ${unmodifiedSet.has(filePath) ? "update" : "create"} ${filePath}`);
|
|
85
78
|
}
|
|
86
79
|
console.log("\n[dry run] No files were modified.");
|
|
87
|
-
reportHeldMigrations(heldMigrations);
|
|
88
80
|
return;
|
|
89
81
|
}
|
|
90
82
|
|
|
@@ -118,36 +110,10 @@ function main() {
|
|
|
118
110
|
}
|
|
119
111
|
}
|
|
120
112
|
|
|
121
|
-
reportHeldMigrations(heldMigrations);
|
|
122
113
|
|
|
123
114
|
console.log("\nAfter merging all files, run complete-update.js to finalize.");
|
|
124
115
|
}
|
|
125
116
|
|
|
126
|
-
/**
|
|
127
|
-
* Report migration files deliberately NOT copied, so the AI knows they are
|
|
128
|
-
* waiting rather than assuming the tree is settled. Silent when there are none.
|
|
129
|
-
*
|
|
130
|
-
* States the whole procedure rather than pointing at SKILL.md. The AI loads
|
|
131
|
-
* SKILL.md at the start of the update, BEFORE step 1a refreshes the bundle, so
|
|
132
|
-
* for one release after this ships it is following the previous release's prose
|
|
133
|
-
* - which says migrations can be added directly. This output has to stand alone
|
|
134
|
-
* against that reader, or the fix reads as an obstacle to work around.
|
|
135
|
-
*/
|
|
136
|
-
function reportHeldMigrations(heldMigrations) {
|
|
137
|
-
if (heldMigrations.length === 0) return;
|
|
138
|
-
console.log(`\n${heldMigrations.length} migration file(s) held back - NOT copied into the project:`);
|
|
139
|
-
for (const f of heldMigrations) console.log(` - ${f}`);
|
|
140
|
-
console.log("\nDo NOT copy these in by hand, and do not take the upstream meta/ snapshots either.");
|
|
141
|
-
console.log("Drizzle runs a migration only when its journal entry is newer than the newest one");
|
|
142
|
-
console.log("already applied, so a pasted-in file never runs, `migrate` still exits 0, and the");
|
|
143
|
-
console.log("table it should have created silently does not exist. Regenerate instead:");
|
|
144
|
-
console.log(" 1. Merge the upstream schema change into packages/database/src/db/");
|
|
145
|
-
console.log(" 2. Run: pnpm --filter @repo/database generate");
|
|
146
|
-
console.log(" 3. Copy any hand-written statements (seeds, backfills, data migrations) out of the");
|
|
147
|
-
console.log(" staged .sql at .generatesaas/staging/<path above> into the file step 2 wrote -");
|
|
148
|
-
console.log(" `generate` infers structure only, so those statements are lost otherwise");
|
|
149
|
-
console.log(" 4. Run: pnpm --filter @repo/database migrate");
|
|
150
|
-
}
|
|
151
117
|
|
|
152
118
|
try {
|
|
153
119
|
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "generatesaas",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for scaffolding and managing GenerateSaaS projects",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -13,16 +13,16 @@
|
|
|
13
13
|
"dist"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@clack/prompts": "^1.
|
|
17
|
-
"commander": "^
|
|
16
|
+
"@clack/prompts": "^1.7.0",
|
|
17
|
+
"commander": "^15.0.0",
|
|
18
18
|
"picocolors": "^1.1.1",
|
|
19
|
-
"tar": "^7.5.
|
|
19
|
+
"tar": "^7.5.22"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@types/node": "^
|
|
22
|
+
"@types/node": "^26.2.0",
|
|
23
23
|
"tsup": "^8.5.1",
|
|
24
24
|
"typescript": "^6.0.3",
|
|
25
|
-
"vitest": "^4.1.
|
|
25
|
+
"vitest": "^4.1.10",
|
|
26
26
|
"@repo/tsconfig": "1.0.0"
|
|
27
27
|
},
|
|
28
28
|
"engines": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsup",
|
|
33
|
-
"postbuild": "node -e \"const fs=require('node:fs');fs.rmSync('dist/skill/content',{recursive:true,force:true});fs.mkdirSync('dist/skill',{recursive:true});fs.cpSync('src/skill/content','dist/skill/content',{recursive:true})\"",
|
|
33
|
+
"postbuild": "node -e \"const fs=require('node:fs');fs.rmSync('dist/skill/content',{recursive:true,force:true});fs.mkdirSync('dist/skill',{recursive:true});fs.cpSync('src/skill/content','dist/skill/content',{recursive:true});fs.rmSync('dist/generators/content',{recursive:true,force:true});fs.mkdirSync('dist/generators',{recursive:true});fs.cpSync('src/generators/content','dist/generators/content',{recursive:true})\"",
|
|
34
34
|
"dev": "tsup --watch",
|
|
35
35
|
"check-types": "tsc --noEmit",
|
|
36
36
|
"test": "vitest run",
|