@notionx/create-notionx-app 1.0.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.
Files changed (239) hide show
  1. package/README.md +139 -0
  2. package/dist/answers.js +332 -0
  3. package/dist/answers.js.map +1 -0
  4. package/dist/cli-notionx.js +388 -0
  5. package/dist/cli-notionx.js.map +1 -0
  6. package/dist/cli-notionx.test.js +277 -0
  7. package/dist/cli-notionx.test.js.map +1 -0
  8. package/dist/diff.js +40 -0
  9. package/dist/diff.js.map +1 -0
  10. package/dist/diff.test.js +90 -0
  11. package/dist/diff.test.js.map +1 -0
  12. package/dist/index.js +99 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/locale-add/apply.js +39 -0
  15. package/dist/locale-add/apply.js.map +1 -0
  16. package/dist/locale-add/format.js +38 -0
  17. package/dist/locale-add/format.js.map +1 -0
  18. package/dist/locale-add/list.js +44 -0
  19. package/dist/locale-add/list.js.map +1 -0
  20. package/dist/locale-add/list.test.js +45 -0
  21. package/dist/locale-add/list.test.js.map +1 -0
  22. package/dist/locale-add/plan.js +128 -0
  23. package/dist/locale-add/plan.js.map +1 -0
  24. package/dist/locale-add/validate.js +46 -0
  25. package/dist/locale-add/validate.js.map +1 -0
  26. package/dist/metadata.js +41 -0
  27. package/dist/metadata.js.map +1 -0
  28. package/dist/notion-translation-sources/apply.js +61 -0
  29. package/dist/notion-translation-sources/apply.js.map +1 -0
  30. package/dist/notion-translation-sources/index.js +3 -0
  31. package/dist/notion-translation-sources/index.js.map +1 -0
  32. package/dist/notion-translation-sources/plan.js +33 -0
  33. package/dist/notion-translation-sources/plan.js.map +1 -0
  34. package/dist/notionx-source.js +142 -0
  35. package/dist/notionx-source.js.map +1 -0
  36. package/dist/notionx-source.test.js +144 -0
  37. package/dist/notionx-source.test.js.map +1 -0
  38. package/dist/password.js +18 -0
  39. package/dist/password.js.map +1 -0
  40. package/dist/presets.js +83 -0
  41. package/dist/presets.js.map +1 -0
  42. package/dist/presets.test.js +50 -0
  43. package/dist/presets.test.js.map +1 -0
  44. package/dist/prompt.js +218 -0
  45. package/dist/prompt.js.map +1 -0
  46. package/dist/provision/cloudflare.js +236 -0
  47. package/dist/provision/cloudflare.js.map +1 -0
  48. package/dist/provision/dependencies.js +219 -0
  49. package/dist/provision/dependencies.js.map +1 -0
  50. package/dist/provision/index.js +681 -0
  51. package/dist/provision/index.js.map +1 -0
  52. package/dist/provision/index.test.js +54 -0
  53. package/dist/provision/index.test.js.map +1 -0
  54. package/dist/provision/inspect.js +109 -0
  55. package/dist/provision/inspect.js.map +1 -0
  56. package/dist/provision/inspect.test.js +75 -0
  57. package/dist/provision/inspect.test.js.map +1 -0
  58. package/dist/provision/notion.js +1981 -0
  59. package/dist/provision/notion.js.map +1 -0
  60. package/dist/provision/notion.test.js +542 -0
  61. package/dist/provision/notion.test.js.map +1 -0
  62. package/dist/provision/ntn-credentials.js +198 -0
  63. package/dist/provision/ntn-credentials.js.map +1 -0
  64. package/dist/provision/options.js +15 -0
  65. package/dist/provision/options.js.map +1 -0
  66. package/dist/provision/password-hash.js +78 -0
  67. package/dist/provision/password-hash.js.map +1 -0
  68. package/dist/provision/prompts.js +115 -0
  69. package/dist/provision/prompts.js.map +1 -0
  70. package/dist/provision/repair.js +48 -0
  71. package/dist/provision/repair.js.map +1 -0
  72. package/dist/provision/repair.test.js +141 -0
  73. package/dist/provision/repair.test.js.map +1 -0
  74. package/dist/provision/shell.js +84 -0
  75. package/dist/provision/shell.js.map +1 -0
  76. package/dist/provision/wire.js +78 -0
  77. package/dist/provision/wire.js.map +1 -0
  78. package/dist/registry/doctor.js +181 -0
  79. package/dist/registry/doctor.js.map +1 -0
  80. package/dist/registry/doctor.test.js +180 -0
  81. package/dist/registry/doctor.test.js.map +1 -0
  82. package/dist/registry/install.js +217 -0
  83. package/dist/registry/install.js.map +1 -0
  84. package/dist/registry/install.test.js +168 -0
  85. package/dist/registry/install.test.js.map +1 -0
  86. package/dist/registry/load-registry.js +24 -0
  87. package/dist/registry/load-registry.js.map +1 -0
  88. package/dist/registry/load-registry.test.js +59 -0
  89. package/dist/registry/load-registry.test.js.map +1 -0
  90. package/dist/registry/migration-planner.js +204 -0
  91. package/dist/registry/migration-planner.js.map +1 -0
  92. package/dist/registry/migration-planner.test.js +340 -0
  93. package/dist/registry/migration-planner.test.js.map +1 -0
  94. package/dist/registry/migrations-store.js +125 -0
  95. package/dist/registry/migrations-store.js.map +1 -0
  96. package/dist/registry/migrations-store.test.js +163 -0
  97. package/dist/registry/migrations-store.test.js.map +1 -0
  98. package/dist/registry/migrations-types.js +25 -0
  99. package/dist/registry/migrations-types.js.map +1 -0
  100. package/dist/registry/project-meta.js +84 -0
  101. package/dist/registry/project-meta.js.map +1 -0
  102. package/dist/registry/registry-items.js +354 -0
  103. package/dist/registry/registry-items.js.map +1 -0
  104. package/dist/registry/registry-items.test.js +99 -0
  105. package/dist/registry/registry-items.test.js.map +1 -0
  106. package/dist/registry/registry-store.js +232 -0
  107. package/dist/registry/registry-store.js.map +1 -0
  108. package/dist/registry/registry-store.test.js +136 -0
  109. package/dist/registry/registry-store.test.js.map +1 -0
  110. package/dist/registry/registry-types.js +18 -0
  111. package/dist/registry/registry-types.js.map +1 -0
  112. package/dist/registry/registry-types.test.js +146 -0
  113. package/dist/registry/registry-types.test.js.map +1 -0
  114. package/dist/registry/render-content-source-files.js +158 -0
  115. package/dist/registry/render-content-source-files.js.map +1 -0
  116. package/dist/registry/render-multi-source.js +296 -0
  117. package/dist/registry/render-multi-source.js.map +1 -0
  118. package/dist/registry/render-multi-source.test.js +110 -0
  119. package/dist/registry/render-multi-source.test.js.map +1 -0
  120. package/dist/registry/text-utils.js +42 -0
  121. package/dist/registry/text-utils.js.map +1 -0
  122. package/dist/registry/uninstall.js +250 -0
  123. package/dist/registry/uninstall.js.map +1 -0
  124. package/dist/registry/uninstall.test.js +264 -0
  125. package/dist/registry/uninstall.test.js.map +1 -0
  126. package/dist/registry/update.js +280 -0
  127. package/dist/registry/update.js.map +1 -0
  128. package/dist/registry/update.test.js +229 -0
  129. package/dist/registry/update.test.js.map +1 -0
  130. package/dist/render.js +549 -0
  131. package/dist/render.js.map +1 -0
  132. package/dist/render.test.js +414 -0
  133. package/dist/render.test.js.map +1 -0
  134. package/dist/templates/.dev.vars.example.tmpl +32 -0
  135. package/dist/templates/.gitignore.tmpl +58 -0
  136. package/dist/templates/README.md.tmpl +417 -0
  137. package/dist/templates/app/[slug]/page.tsx.tmpl +55 -0
  138. package/dist/templates/app/admin/account/page.tsx.tmpl +18 -0
  139. package/dist/templates/app/admin/content-models/page.tsx.tmpl +6 -0
  140. package/dist/templates/app/admin/layout.tsx.tmpl +90 -0
  141. package/dist/templates/app/admin/loading.tsx.tmpl +6 -0
  142. package/dist/templates/app/admin/page.tsx.tmpl +17 -0
  143. package/dist/templates/app/api/auth/google/callback/route.ts.tmpl +3 -0
  144. package/dist/templates/app/api/auth/google/route.ts.tmpl +3 -0
  145. package/dist/templates/app/api/auth/verify-email/route.ts.tmpl +3 -0
  146. package/dist/templates/app/api/auth/viewer/route.ts.tmpl +3 -0
  147. package/dist/templates/app/api/health/route.ts.tmpl +3 -0
  148. package/dist/templates/app/api/{{contentSourceId}}/[slug]/route.ts.tmpl +27 -0
  149. package/dist/templates/app/api/{{contentSourceId}}/route.ts.tmpl +18 -0
  150. package/dist/templates/app/globals.css.tmpl +109 -0
  151. package/dist/templates/app/layout.tsx.tmpl +56 -0
  152. package/dist/templates/app/login/page.tsx.tmpl +154 -0
  153. package/dist/templates/app/page.fallback.tsx.tmpl +31 -0
  154. package/dist/templates/app/page.tsx.tmpl +42 -0
  155. package/dist/templates/app/register/page.tsx.tmpl +138 -0
  156. package/dist/templates/app/{{contentSourceListPath}}/[slug]/page.tsx.tmpl +113 -0
  157. package/dist/templates/app/{{contentSourceListPath}}/page.tsx.tmpl +74 -0
  158. package/dist/templates/components/content/post-card.tsx.tmpl +80 -0
  159. package/dist/templates/components/notion-blocks.tsx.tmpl +668 -0
  160. package/dist/templates/components/page-blocks/feature-grid-block.tsx.tmpl +68 -0
  161. package/dist/templates/components/page-blocks/hero-block.tsx.tmpl +73 -0
  162. package/dist/templates/components/page-blocks/latest-posts-block.tsx.tmpl +59 -0
  163. package/dist/templates/components/page-blocks/story-block.tsx.tmpl +70 -0
  164. package/dist/templates/components/page-blocks.fallback.tsx.tmpl +17 -0
  165. package/dist/templates/components/page-blocks.tsx.tmpl +32 -0
  166. package/dist/templates/components/search/search-dialog.tsx.tmpl +171 -0
  167. package/dist/templates/components/site/locale-switcher.tsx.tmpl +65 -0
  168. package/dist/templates/components/site/site-footer.tsx.tmpl +106 -0
  169. package/dist/templates/components/site/site-header.tsx.tmpl +80 -0
  170. package/dist/templates/components/site/site-shell.tsx.tmpl +20 -0
  171. package/dist/templates/components/site/theme-bootstrap.tsx.tmpl +51 -0
  172. package/dist/templates/components/theme-provider.tsx.tmpl +14 -0
  173. package/dist/templates/components/theme-toggle.tsx.tmpl +38 -0
  174. package/dist/templates/components/ui/accordion.tsx.tmpl +56 -0
  175. package/dist/templates/components/ui/alert.tsx.tmpl +59 -0
  176. package/dist/templates/components/ui/aspect-ratio.tsx.tmpl +8 -0
  177. package/dist/templates/components/ui/avatar.tsx.tmpl +44 -0
  178. package/dist/templates/components/ui/badge.tsx.tmpl +33 -0
  179. package/dist/templates/components/ui/button.tsx.tmpl +56 -0
  180. package/dist/templates/components/ui/card.tsx.tmpl +61 -0
  181. package/dist/templates/components/ui/checkbox.tsx.tmpl +28 -0
  182. package/dist/templates/components/ui/dialog.tsx.tmpl +104 -0
  183. package/dist/templates/components/ui/dropdown-menu.tsx.tmpl +183 -0
  184. package/dist/templates/components/ui/input.tsx.tmpl +21 -0
  185. package/dist/templates/components/ui/label.tsx.tmpl +25 -0
  186. package/dist/templates/components/ui/popover.tsx.tmpl +30 -0
  187. package/dist/templates/components/ui/radio-group.tsx.tmpl +44 -0
  188. package/dist/templates/components/ui/select.tsx.tmpl +150 -0
  189. package/dist/templates/components/ui/separator.tsx.tmpl +30 -0
  190. package/dist/templates/components/ui/sheet.tsx.tmpl +125 -0
  191. package/dist/templates/components/ui/skeleton.tsx.tmpl +15 -0
  192. package/dist/templates/components/ui/sonner.tsx.tmpl +30 -0
  193. package/dist/templates/components/ui/switch.tsx.tmpl +29 -0
  194. package/dist/templates/components/ui/table.tsx.tmpl +107 -0
  195. package/dist/templates/components/ui/tabs.tsx.tmpl +55 -0
  196. package/dist/templates/components/ui/textarea.tsx.tmpl +24 -0
  197. package/dist/templates/components/ui/tooltip.tsx.tmpl +30 -0
  198. package/dist/templates/components.json.tmpl +21 -0
  199. package/dist/templates/env.d.ts.tmpl +32 -0
  200. package/dist/templates/lib/admin/actions.ts.tmpl +43 -0
  201. package/dist/templates/lib/admin/context.tsx.tmpl +209 -0
  202. package/dist/templates/lib/admin/nav.ts.tmpl +23 -0
  203. package/dist/templates/lib/auth.config.fallback.ts.tmpl +10 -0
  204. package/dist/templates/lib/auth.config.ts.tmpl +45 -0
  205. package/dist/templates/lib/blocks/translations.ts.tmpl +44 -0
  206. package/dist/templates/lib/blog/translations.ts.tmpl +52 -0
  207. package/dist/templates/lib/content/models.ts.tmpl +53 -0
  208. package/dist/templates/lib/i18n/config.ts.tmpl +18 -0
  209. package/dist/templates/lib/i18n/index.ts.tmpl +1 -0
  210. package/dist/templates/lib/locale-contract/built-in.ts.tmpl +19 -0
  211. package/dist/templates/lib/locale-contract/index.ts.tmpl +3 -0
  212. package/dist/templates/lib/locale-contract/paths.ts.tmpl +29 -0
  213. package/dist/templates/lib/pages/model.ts.tmpl +16 -0
  214. package/dist/templates/lib/pages/source.ts.tmpl +566 -0
  215. package/dist/templates/lib/pages/translations.ts.tmpl +34 -0
  216. package/dist/templates/lib/search/config.fallback.ts.tmpl +11 -0
  217. package/dist/templates/lib/search/config.ts.tmpl +25 -0
  218. package/dist/templates/lib/site/config.ts.tmpl +120 -0
  219. package/dist/templates/lib/site/request-env.ts.tmpl +71 -0
  220. package/dist/templates/lib/site/settings.fallback.ts.tmpl +21 -0
  221. package/dist/templates/lib/site/settings.ts.tmpl +320 -0
  222. package/dist/templates/lib/site/translations.ts.tmpl +30 -0
  223. package/dist/templates/lib/utils.ts.tmpl +9 -0
  224. package/dist/templates/migrations/0001_init.sql.tmpl +57 -0
  225. package/dist/templates/migrations/0002_admin_seed.sql.tmpl +30 -0
  226. package/dist/templates/migrations/0003_search_index.sql.tmpl +29 -0
  227. package/dist/templates/next.config.ts.tmpl +18 -0
  228. package/dist/templates/package.json.tmpl +40 -0
  229. package/dist/templates/shims/cloudflare-workers-empty.mjs +4 -0
  230. package/dist/templates/shims/next-headers-empty.mjs +4 -0
  231. package/dist/templates/tests/smoke.test.ts.tmpl +83 -0
  232. package/dist/templates/tsconfig.json.tmpl +31 -0
  233. package/dist/templates/vite.config.ts.tmpl +53 -0
  234. package/dist/templates/vitest.config.ts.tmpl +13 -0
  235. package/dist/templates/worker/index.ts.tmpl +52 -0
  236. package/dist/templates/wrangler.jsonc.tmpl +44 -0
  237. package/dist/ui-presets.js +60 -0
  238. package/dist/ui-presets.js.map +1 -0
  239. package/package.json +60 -0
@@ -0,0 +1,280 @@
1
+ // packages/create-notionx-app/src/registry/update.ts
2
+ //
3
+ // `notionx update` entry point. v2 protocol.
4
+ //
5
+ // What this does:
6
+ // 1. Read `.notionx/registry.json`.
7
+ // 2. Walk the installed manifest, compare versions to the
8
+ // catalog.
9
+ // 3. For each upgradable item, build a `UpdatePlan` (pure) and
10
+ // write **one set of payload files** per chain hop:
11
+ // - `.notionx/migrations/NNNN_<item>_<from>_<to>.notion-diff.json`
12
+ // - `.notionx/migrations/NNNN_<item>_<from>_<to>.d1.sql`
13
+ // - `.notionx/migrations/_meta.json` (always rewritten)
14
+ // 4. **Never** touch Notion or D1 directly. The user runs the
15
+ // migration by hand (or via the future `notionx migrate`
16
+ // command).
17
+ // 5. Re-render `lib/content/models.ts` so the registry stays
18
+ // in sync with the new catalog shape.
19
+ //
20
+ // Codemods (TS transformations) and `user`-owned file re-renders
21
+ // are scaffolded in PR 4 but not yet active; the planner already
22
+ // classifies them and `applyUpdate` records them in the
23
+ // `UpdatePlan` so the CLI can report them.
24
+ import { mkdir, writeFile } from "node:fs/promises";
25
+ import path from "node:path";
26
+ import { loadRegistry } from "./load-registry.js";
27
+ import { buildUpdatePlan } from "./migration-planner.js";
28
+ import { appendMigration, emptyMeta, MIGRATIONS_META, readMigrationsMeta, writeMigrationPayload, } from "./migrations-store.js";
29
+ import { renderContentSourceFiles } from "./render-content-source-files.js";
30
+ import { readProjectMeta } from "./project-meta.js";
31
+ export async function applyUpdate(input) {
32
+ const { projectDir, templatesDir, catalogItems } = input;
33
+ const loaded = await loadRegistry(projectDir);
34
+ const manifest = loaded.manifest;
35
+ const applied = (await readMigrationsMeta(projectDir)) ?? emptyMeta();
36
+ // Resolve scope before the planner sees anything: filtering
37
+ // here keeps the planner pure (it still takes plain arrays)
38
+ // and lets us surface a friendly error for unknown item ids.
39
+ const scope = input.scope ?? { kind: "all" };
40
+ const installed = filterInstalledByScope(manifest.installed, scope);
41
+ const catalogItemsScoped = filterCatalogByScope(catalogItems, scope, manifest);
42
+ // Project meta for token rendering. We reuse the same helper
43
+ // install.ts uses — read package.json to get the project name.
44
+ const project = await readProjectMeta(projectDir, manifest);
45
+ const plan = buildUpdatePlan({
46
+ installed,
47
+ catalogItems: catalogItemsScoped,
48
+ appliedMigrations: applied.history,
49
+ });
50
+ // Group steps by (itemId, fromV, toV) hop. We assume the
51
+ // planner emits at most one hop per item (single-hop rule).
52
+ // PR 4 keeps that constraint explicit; multi-hop will be a
53
+ // small extension.
54
+ const hops = new Map();
55
+ for (const step of [...plan.additive, ...plan.destructive]) {
56
+ const key = `${step.itemId}@${itemVersionById(manifest.installed, step.itemId)}`;
57
+ let hop = hops.get(key);
58
+ if (!hop) {
59
+ const fromV = itemVersionById(manifest.installed, step.itemId);
60
+ const toV = itemTargetVersion(catalogItems, step.itemId);
61
+ hop = { itemId: step.itemId, fromV, toV, additive: [], destructive: [] };
62
+ hops.set(key, hop);
63
+ }
64
+ if (plan.additive.includes(step))
65
+ hop.additive.push(step);
66
+ else
67
+ hop.destructive.push(step);
68
+ }
69
+ const wroteFiles = [];
70
+ let sequence;
71
+ const followup = [];
72
+ const rerenderedFiles = [];
73
+ if (input.dryRun) {
74
+ return {
75
+ plans: plan,
76
+ wroteFiles,
77
+ wroteManifest: false,
78
+ rerenderedFiles,
79
+ followup,
80
+ };
81
+ }
82
+ // Write the per-hop payload files. We always do additive
83
+ // + destructive in the same migration (one seq, multiple
84
+ // payload files) so the user's bookkeeping is "one
85
+ // migration per item version".
86
+ for (const hop of hops.values()) {
87
+ if (hop.additive.length === 0 && hop.destructive.length === 0)
88
+ continue;
89
+ const slug = `${hop.itemId}_${hop.fromV}_to_${hop.toV}`;
90
+ // Notion diff (if any notion-* steps).
91
+ const notionSteps = [...hop.additive, ...hop.destructive].filter((s) => s.kind === "notion-field-add" ||
92
+ s.kind === "notion-field-rename" ||
93
+ s.kind === "notion-field-deprecate");
94
+ if (notionSteps.length > 0) {
95
+ const filename = `${slug}.notion-diff.json`;
96
+ const payload = JSON.stringify({ itemId: hop.itemId, fromV: hop.fromV, toV: hop.toV, steps: notionSteps }, null, 2);
97
+ await writeMigrationPayload(projectDir, filename, `${payload}\n`);
98
+ wroteFiles.push(filename);
99
+ followup.push(`Apply Notion diff by running the steps in ${filename} (manually or via Notion API).`);
100
+ }
101
+ // D1 SQL (if any d1-* steps, including d1-migration-file refs).
102
+ const d1Steps = [...hop.additive, ...hop.destructive].filter((s) => s.kind === "d1-table-create" ||
103
+ s.kind === "d1-table-alter" ||
104
+ s.kind === "d1-migration-file");
105
+ if (d1Steps.length > 0) {
106
+ const filename = `${slug}.d1.sql`;
107
+ const sql = d1Steps
108
+ .map((s) => {
109
+ if (s.kind === "d1-table-create" || s.kind === "d1-table-alter") {
110
+ return `-- ${s.itemId}: ${s.kind} ${s.tableName}\n${s.sql}`;
111
+ }
112
+ if (s.kind === "d1-migration-file") {
113
+ return `-- ${s.itemId}: d1-migration-file (apply the SQL in ${s.file})`;
114
+ }
115
+ return "";
116
+ })
117
+ .filter(Boolean)
118
+ .join("\n\n");
119
+ await writeMigrationPayload(projectDir, filename, `${sql}\n`);
120
+ wroteFiles.push(filename);
121
+ followup.push(`Apply D1 SQL with: wrangler d1 migrations apply <DB_NAME> --remote`);
122
+ }
123
+ // Env vars (if any env-add steps).
124
+ const envSteps = [...hop.additive, ...hop.destructive].filter((s) => s.kind === "env-add");
125
+ if (envSteps.length > 0) {
126
+ const filename = `${slug}.env.json`;
127
+ const payload = JSON.stringify({
128
+ itemId: hop.itemId,
129
+ fromV: hop.fromV,
130
+ toV: hop.toV,
131
+ vars: envSteps.map((s) => s.kind === "env-add"
132
+ ? {
133
+ name: s.name,
134
+ ...(s.default !== undefined ? { default: s.default } : {}),
135
+ ...(s.secret !== undefined ? { secret: s.secret } : {}),
136
+ }
137
+ : null),
138
+ }, null, 2);
139
+ await writeMigrationPayload(projectDir, filename, `${payload}\n`);
140
+ wroteFiles.push(filename);
141
+ for (const s of envSteps) {
142
+ if (s.kind !== "env-add")
143
+ continue;
144
+ const hint = s.secret
145
+ ? `Set secret ${s.name} with: wrangler secret put ${s.name}`
146
+ : `Add ${s.name} to your .dev.vars and wrangler.jsonc vars`;
147
+ followup.push(hint);
148
+ }
149
+ }
150
+ // Config merge (if any config-merge steps).
151
+ const configSteps = [...hop.additive, ...hop.destructive].filter((s) => s.kind === "config-merge");
152
+ if (configSteps.length > 0) {
153
+ const filename = `${slug}.config-merge.json`;
154
+ const payload = JSON.stringify({
155
+ itemId: hop.itemId,
156
+ fromV: hop.fromV,
157
+ toV: hop.toV,
158
+ merges: configSteps.map((s) => s.kind === "config-merge"
159
+ ? { file: s.file, json: s.json }
160
+ : null),
161
+ }, null, 2);
162
+ await writeMigrationPayload(projectDir, filename, `${payload}\n`);
163
+ wroteFiles.push(filename);
164
+ followup.push(`Merge config changes from ${filename} into the referenced files (deep-merge each entry's json into the target file).`);
165
+ }
166
+ // Append the migration entry to _meta.json. **The sequence
167
+ // number is whatever `appendMigration` assigns** (the
168
+ // canonical nextSequence from the directory). The payload
169
+ // filenames use the **un-padded** version pair as a slug, so
170
+ // they're stable across replays of the same hop.
171
+ const fileRef = pickMigrationFileRef(slug, {
172
+ notion: notionSteps.length > 0,
173
+ d1: d1Steps.length > 0,
174
+ env: envSteps.length > 0,
175
+ config: configSteps.length > 0,
176
+ });
177
+ const entry = await appendMigration(projectDir, {
178
+ itemId: hop.itemId,
179
+ itemKind: "content-source", // refined in PR 4.5 from the catalog
180
+ label: `${hop.itemId} ${hop.fromV}->${hop.toV}`,
181
+ file: fileRef,
182
+ applied: false,
183
+ });
184
+ sequence = entry.sequence;
185
+ wroteFiles.push(MIGRATIONS_META);
186
+ }
187
+ // Re-render every declared file for any installed item whose
188
+ // version moved (so bridges, pages, and API routes all stay in
189
+ // sync with the catalog version bump). We *don't* re-render
190
+ // when no hops were generated — the user hasn't moved versions,
191
+ // so nothing changed.
192
+ if (hops.size > 0) {
193
+ for (const item of installed) {
194
+ const catalog = catalogItems.find((c) => c.id === item.id);
195
+ if (!catalog)
196
+ continue;
197
+ // Skip items that didn't move versions.
198
+ if (catalog.version === item.version)
199
+ continue;
200
+ const rendered = await renderContentSourceFiles({
201
+ projectDir,
202
+ templatesDir,
203
+ item: catalog,
204
+ installed: manifest.installed,
205
+ project,
206
+ });
207
+ for (const f of rendered) {
208
+ await mkdir(path.dirname(f.absolutePath), { recursive: true });
209
+ await writeFile(f.absolutePath, f.content, "utf8");
210
+ rerenderedFiles.push(f.projectRelativePath);
211
+ }
212
+ }
213
+ }
214
+ // The registry's `installed[].version` field is **never** bumped
215
+ // by `applyUpdate`. The bump only happens after the user
216
+ // confirms they applied the migration by running
217
+ // `notionx migrate --mark-applied <seq>`. This is what
218
+ // guarantees the migration is safe to retry: if the user
219
+ // aborts mid-way, the next `notionx update` will detect
220
+ // they're still on the old version and re-emit the same plan.
221
+ //
222
+ // We still re-render the bridge files (worker/index.ts,
223
+ // models.ts, etc.) so the *source code* is in sync with what
224
+ // the *next applied* migration will produce. The user can
225
+ // ship that code immediately; the migration itself is what
226
+ // backfills their data.
227
+ return {
228
+ plans: plan,
229
+ ...(sequence !== undefined ? { sequence } : {}),
230
+ wroteFiles,
231
+ wroteManifest: false,
232
+ rerenderedFiles,
233
+ followup,
234
+ };
235
+ }
236
+ // ---- internals ----
237
+ function itemVersionById(installed, id) {
238
+ return installed.find((i) => i.id === id)?.version ?? 0;
239
+ }
240
+ function itemTargetVersion(catalog, id) {
241
+ return catalog.find((c) => c.id === id)?.version ?? 0;
242
+ }
243
+ /**
244
+ * Pick the `MigrationFileRef` for the migration entry. Priority
245
+ * order matches the payload-writing blocks above. Falls back to
246
+ * `d1-sql` when no payload file was written (e.g. ts-codemod-only
247
+ * hops) so the entry always has a valid `file` field — the
248
+ * pre-existing behaviour.
249
+ */
250
+ function pickMigrationFileRef(slug, present) {
251
+ if (present.notion)
252
+ return { kind: "notion-diff", filename: `${slug}.notion-diff.json` };
253
+ if (present.d1)
254
+ return { kind: "d1-sql", filename: `${slug}.d1.sql` };
255
+ if (present.env)
256
+ return { kind: "env", filename: `${slug}.env.json` };
257
+ if (present.config)
258
+ return { kind: "config-merge", filename: `${slug}.config-merge.json` };
259
+ return { kind: "d1-sql", filename: `${slug}.d1.sql` };
260
+ }
261
+ // ---- scope helpers ----
262
+ function filterInstalledByScope(installed, scope) {
263
+ if (scope.kind === "all")
264
+ return installed.slice();
265
+ const match = installed.find((i) => i.id === scope.itemId);
266
+ if (!match) {
267
+ throw new Error(`Cannot update "${scope.itemId}": not installed. Run \`notionx diff\` to see installed items.`);
268
+ }
269
+ return [match];
270
+ }
271
+ function filterCatalogByScope(catalog, scope, _manifest) {
272
+ if (scope.kind === "all")
273
+ return catalog.slice();
274
+ const match = catalog.find((c) => c.id === scope.itemId);
275
+ if (!match) {
276
+ throw new Error(`Cannot update "${scope.itemId}": not present in the official catalog.`);
277
+ }
278
+ return [match];
279
+ }
280
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/registry/update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,229 @@
1
+ // packages/create-notionx-app/src/registry/update.test.ts
2
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
6
+ import { resolveTemplatesDir } from "../render.js";
7
+ import { REGISTRY_SCHEMA_V2 } from "./registry-types.js";
8
+ import { applyUpdate } from "./update.js";
9
+ const blogV2 = {
10
+ id: "blog",
11
+ kind: "content-source",
12
+ version: 2,
13
+ source: { kind: "official", name: "@notionx/official" },
14
+ publishedAt: "2026-06-15T00:00:00.000Z",
15
+ params: { contentSourceId: "blog" },
16
+ files: [
17
+ { path: "app/blog/page.tsx", ownership: "user" },
18
+ ],
19
+ capabilities: {
20
+ envVars: ["NOTION_BLOG_DATA_SOURCE_ID"],
21
+ },
22
+ migrations: [
23
+ {
24
+ from: "blog@1",
25
+ to: "blog@2",
26
+ steps: [
27
+ {
28
+ kind: "notion-field-add",
29
+ source: "NOTION_BLOG_DATA_SOURCE_ID",
30
+ property: "Author",
31
+ type: "people",
32
+ },
33
+ {
34
+ kind: "d1-table-create",
35
+ name: "blog_authors",
36
+ sql: "CREATE TABLE blog_authors (id INTEGER PRIMARY KEY, name TEXT NOT NULL);",
37
+ },
38
+ ],
39
+ },
40
+ ],
41
+ };
42
+ const blogV1 = {
43
+ ...blogV2,
44
+ version: 1,
45
+ migrations: [],
46
+ };
47
+ async function seedProject(projectDir, catalogItems, installed) {
48
+ await writeFile(path.join(projectDir, "package.json"), JSON.stringify({
49
+ name: "demo",
50
+ version: "0.0.0",
51
+ private: true,
52
+ dependencies: { "@notionx/core": "^2.0.0" },
53
+ }), "utf8");
54
+ await mkdir(path.join(projectDir, ".notionx"), { recursive: true });
55
+ await writeFile(path.join(projectDir, ".notionx/registry.json"), JSON.stringify({
56
+ $schema: REGISTRY_SCHEMA_V2,
57
+ projectKind: "notionx",
58
+ scaffoldVersion: "2.0.0",
59
+ notionxCore: "^2.0.0",
60
+ compat: { mode: "v2-native" },
61
+ registries: {},
62
+ installed,
63
+ managedFiles: { platform: ["package.json"], bridge: [], user: [] },
64
+ }), "utf8");
65
+ // Inject a fake catalog by writing a tiny catalog module that
66
+ // applyUpdate reads via the `catalog` param.
67
+ return { catalog: catalogItems };
68
+ }
69
+ describe("applyUpdate", () => {
70
+ let dir;
71
+ let templatesDir;
72
+ beforeEach(async () => {
73
+ dir = await mkdtemp(path.join(os.tmpdir(), "notionx-update-"));
74
+ await mkdir(path.join(dir, ".notionx"), { recursive: true });
75
+ templatesDir = await resolveTemplatesDir();
76
+ });
77
+ afterEach(async () => {
78
+ await rm(dir, { recursive: true, force: true });
79
+ });
80
+ it("generates a migration file + _meta entry, without modifying the data source", async () => {
81
+ const { catalog } = await seedProject(dir, [blogV2], [
82
+ {
83
+ id: "blog",
84
+ kind: "content-source",
85
+ version: 1,
86
+ source: { kind: "official", name: "@notionx/official" },
87
+ params: { contentSourceId: "blog" },
88
+ installedAt: "2026-06-10T00:00:00.000Z",
89
+ },
90
+ ]);
91
+ const summary = await applyUpdate({
92
+ projectDir: dir,
93
+ templatesDir,
94
+ catalogItems: catalog,
95
+ });
96
+ expect(summary.plans.additive.length).toBeGreaterThan(0);
97
+ expect(summary.wroteFiles).toContain("blog_1_to_2.notion-diff.json");
98
+ expect(summary.wroteFiles).toContain("blog_1_to_2.d1.sql");
99
+ expect(summary.wroteFiles).toContain("_meta.json");
100
+ // The Notion diff was written but the Notion data source was
101
+ // not touched (we don't have a network call here).
102
+ const notionDiffPath = path.join(dir, ".notionx/migrations/blog_1_to_2.notion-diff.json");
103
+ const diff = JSON.parse(await readFile(notionDiffPath, "utf8"));
104
+ expect(diff.steps).toEqual(expect.arrayContaining([
105
+ expect.objectContaining({ kind: "notion-field-add", property: "Author" }),
106
+ ]));
107
+ // The D1 SQL file was written
108
+ const sql = await readFile(path.join(dir, ".notionx/migrations/blog_1_to_2.d1.sql"), "utf8");
109
+ expect(sql).toContain("CREATE TABLE blog_authors");
110
+ // _meta.json is updated
111
+ const meta = JSON.parse(await readFile(path.join(dir, ".notionx/migrations/_meta.json"), "utf8"));
112
+ expect(meta.nextSequence).toBe(2);
113
+ expect(meta.history).toHaveLength(1);
114
+ expect(meta.history[0]?.label).toBe("blog 1->2");
115
+ });
116
+ it("is idempotent: a second call with the same catalog produces no new files", async () => {
117
+ const { catalog } = await seedProject(dir, [blogV2], [
118
+ {
119
+ id: "blog",
120
+ kind: "content-source",
121
+ version: 1,
122
+ source: { kind: "official", name: "@notionx/official" },
123
+ params: { contentSourceId: "blog" },
124
+ installedAt: "2026-06-10T00:00:00.000Z",
125
+ },
126
+ ]);
127
+ const first = await applyUpdate({
128
+ projectDir: dir,
129
+ templatesDir,
130
+ catalogItems: catalog,
131
+ });
132
+ expect(first.wroteFiles.length).toBeGreaterThan(0);
133
+ const second = await applyUpdate({
134
+ projectDir: dir,
135
+ templatesDir,
136
+ catalogItems: catalog,
137
+ });
138
+ // Second run: no new payloads written, but _meta.json still
139
+ // gets re-written (the planner sees the same set).
140
+ expect(second.plans.additive).toEqual([]);
141
+ expect(second.plans.destructive).toEqual([]);
142
+ expect(second.plans.noop.length).toBeGreaterThan(0);
143
+ });
144
+ it("skips items already at the catalog version", async () => {
145
+ const { catalog } = await seedProject(dir, [blogV2], [
146
+ {
147
+ id: "blog",
148
+ kind: "content-source",
149
+ version: 2,
150
+ source: { kind: "official", name: "@notionx/official" },
151
+ params: { contentSourceId: "blog" },
152
+ installedAt: "2026-06-10T00:00:00.000Z",
153
+ },
154
+ ]);
155
+ const summary = await applyUpdate({
156
+ projectDir: dir,
157
+ templatesDir,
158
+ catalogItems: catalog,
159
+ });
160
+ expect(summary.wroteFiles).toEqual([]);
161
+ expect(summary.plans.additive).toEqual([]);
162
+ expect(summary.plans.destructive).toEqual([]);
163
+ });
164
+ it("blocks downgrades: installed v2 + catalog v1 produces no plan", async () => {
165
+ const { catalog } = await seedProject(dir, [blogV1], [
166
+ {
167
+ id: "blog",
168
+ kind: "content-source",
169
+ version: 2,
170
+ source: { kind: "official", name: "@notionx/official" },
171
+ params: { contentSourceId: "blog" },
172
+ installedAt: "2026-06-10T00:00:00.000Z",
173
+ },
174
+ ]);
175
+ const summary = await applyUpdate({
176
+ projectDir: dir,
177
+ templatesDir,
178
+ catalogItems: catalog,
179
+ });
180
+ expect(summary.plans.additive).toEqual([]);
181
+ expect(summary.plans.destructive).toEqual([]);
182
+ });
183
+ it("batches additive + destructive into the same migration file (one seq, multiple payloads)", async () => {
184
+ const blogV3 = {
185
+ ...blogV2,
186
+ version: 3,
187
+ migrations: [
188
+ {
189
+ from: "blog@1",
190
+ to: "blog@3",
191
+ steps: [
192
+ {
193
+ kind: "notion-field-add",
194
+ source: "NOTION_BLOG_DATA_SOURCE_ID",
195
+ property: "Author",
196
+ type: "people",
197
+ },
198
+ {
199
+ kind: "notion-field-rename",
200
+ source: "NOTION_BLOG_DATA_SOURCE_ID",
201
+ from: "Eyebrow",
202
+ to: "Subheadline",
203
+ },
204
+ ],
205
+ },
206
+ ],
207
+ };
208
+ const { catalog } = await seedProject(dir, [blogV3], [
209
+ {
210
+ id: "blog",
211
+ kind: "content-source",
212
+ version: 1,
213
+ source: { kind: "official", name: "@notionx/official" },
214
+ params: { contentSourceId: "blog" },
215
+ installedAt: "2026-06-10T00:00:00.000Z",
216
+ },
217
+ ]);
218
+ const summary = await applyUpdate({
219
+ projectDir: dir,
220
+ templatesDir,
221
+ catalogItems: catalog,
222
+ });
223
+ // One additive, one destructive, one seq, two payload files
224
+ expect(summary.plans.additive).toHaveLength(1);
225
+ expect(summary.plans.destructive).toHaveLength(1);
226
+ expect(summary.wroteFiles).toContain("blog_1_to_3.notion-diff.json");
227
+ });
228
+ });
229
+ //# sourceMappingURL=update.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.test.js","sourceRoot":"","sources":["../../src/registry/update.test.ts"],"names":[],"mappings":"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"}