@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.
- package/README.md +139 -0
- package/dist/answers.js +332 -0
- package/dist/answers.js.map +1 -0
- package/dist/cli-notionx.js +388 -0
- package/dist/cli-notionx.js.map +1 -0
- package/dist/cli-notionx.test.js +277 -0
- package/dist/cli-notionx.test.js.map +1 -0
- package/dist/diff.js +40 -0
- package/dist/diff.js.map +1 -0
- package/dist/diff.test.js +90 -0
- package/dist/diff.test.js.map +1 -0
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -0
- package/dist/locale-add/apply.js +39 -0
- package/dist/locale-add/apply.js.map +1 -0
- package/dist/locale-add/format.js +38 -0
- package/dist/locale-add/format.js.map +1 -0
- package/dist/locale-add/list.js +44 -0
- package/dist/locale-add/list.js.map +1 -0
- package/dist/locale-add/list.test.js +45 -0
- package/dist/locale-add/list.test.js.map +1 -0
- package/dist/locale-add/plan.js +128 -0
- package/dist/locale-add/plan.js.map +1 -0
- package/dist/locale-add/validate.js +46 -0
- package/dist/locale-add/validate.js.map +1 -0
- package/dist/metadata.js +41 -0
- package/dist/metadata.js.map +1 -0
- package/dist/notion-translation-sources/apply.js +61 -0
- package/dist/notion-translation-sources/apply.js.map +1 -0
- package/dist/notion-translation-sources/index.js +3 -0
- package/dist/notion-translation-sources/index.js.map +1 -0
- package/dist/notion-translation-sources/plan.js +33 -0
- package/dist/notion-translation-sources/plan.js.map +1 -0
- package/dist/notionx-source.js +142 -0
- package/dist/notionx-source.js.map +1 -0
- package/dist/notionx-source.test.js +144 -0
- package/dist/notionx-source.test.js.map +1 -0
- package/dist/password.js +18 -0
- package/dist/password.js.map +1 -0
- package/dist/presets.js +83 -0
- package/dist/presets.js.map +1 -0
- package/dist/presets.test.js +50 -0
- package/dist/presets.test.js.map +1 -0
- package/dist/prompt.js +218 -0
- package/dist/prompt.js.map +1 -0
- package/dist/provision/cloudflare.js +236 -0
- package/dist/provision/cloudflare.js.map +1 -0
- package/dist/provision/dependencies.js +219 -0
- package/dist/provision/dependencies.js.map +1 -0
- package/dist/provision/index.js +681 -0
- package/dist/provision/index.js.map +1 -0
- package/dist/provision/index.test.js +54 -0
- package/dist/provision/index.test.js.map +1 -0
- package/dist/provision/inspect.js +109 -0
- package/dist/provision/inspect.js.map +1 -0
- package/dist/provision/inspect.test.js +75 -0
- package/dist/provision/inspect.test.js.map +1 -0
- package/dist/provision/notion.js +1981 -0
- package/dist/provision/notion.js.map +1 -0
- package/dist/provision/notion.test.js +542 -0
- package/dist/provision/notion.test.js.map +1 -0
- package/dist/provision/ntn-credentials.js +198 -0
- package/dist/provision/ntn-credentials.js.map +1 -0
- package/dist/provision/options.js +15 -0
- package/dist/provision/options.js.map +1 -0
- package/dist/provision/password-hash.js +78 -0
- package/dist/provision/password-hash.js.map +1 -0
- package/dist/provision/prompts.js +115 -0
- package/dist/provision/prompts.js.map +1 -0
- package/dist/provision/repair.js +48 -0
- package/dist/provision/repair.js.map +1 -0
- package/dist/provision/repair.test.js +141 -0
- package/dist/provision/repair.test.js.map +1 -0
- package/dist/provision/shell.js +84 -0
- package/dist/provision/shell.js.map +1 -0
- package/dist/provision/wire.js +78 -0
- package/dist/provision/wire.js.map +1 -0
- package/dist/registry/doctor.js +181 -0
- package/dist/registry/doctor.js.map +1 -0
- package/dist/registry/doctor.test.js +180 -0
- package/dist/registry/doctor.test.js.map +1 -0
- package/dist/registry/install.js +217 -0
- package/dist/registry/install.js.map +1 -0
- package/dist/registry/install.test.js +168 -0
- package/dist/registry/install.test.js.map +1 -0
- package/dist/registry/load-registry.js +24 -0
- package/dist/registry/load-registry.js.map +1 -0
- package/dist/registry/load-registry.test.js +59 -0
- package/dist/registry/load-registry.test.js.map +1 -0
- package/dist/registry/migration-planner.js +204 -0
- package/dist/registry/migration-planner.js.map +1 -0
- package/dist/registry/migration-planner.test.js +340 -0
- package/dist/registry/migration-planner.test.js.map +1 -0
- package/dist/registry/migrations-store.js +125 -0
- package/dist/registry/migrations-store.js.map +1 -0
- package/dist/registry/migrations-store.test.js +163 -0
- package/dist/registry/migrations-store.test.js.map +1 -0
- package/dist/registry/migrations-types.js +25 -0
- package/dist/registry/migrations-types.js.map +1 -0
- package/dist/registry/project-meta.js +84 -0
- package/dist/registry/project-meta.js.map +1 -0
- package/dist/registry/registry-items.js +354 -0
- package/dist/registry/registry-items.js.map +1 -0
- package/dist/registry/registry-items.test.js +99 -0
- package/dist/registry/registry-items.test.js.map +1 -0
- package/dist/registry/registry-store.js +232 -0
- package/dist/registry/registry-store.js.map +1 -0
- package/dist/registry/registry-store.test.js +136 -0
- package/dist/registry/registry-store.test.js.map +1 -0
- package/dist/registry/registry-types.js +18 -0
- package/dist/registry/registry-types.js.map +1 -0
- package/dist/registry/registry-types.test.js +146 -0
- package/dist/registry/registry-types.test.js.map +1 -0
- package/dist/registry/render-content-source-files.js +158 -0
- package/dist/registry/render-content-source-files.js.map +1 -0
- package/dist/registry/render-multi-source.js +296 -0
- package/dist/registry/render-multi-source.js.map +1 -0
- package/dist/registry/render-multi-source.test.js +110 -0
- package/dist/registry/render-multi-source.test.js.map +1 -0
- package/dist/registry/text-utils.js +42 -0
- package/dist/registry/text-utils.js.map +1 -0
- package/dist/registry/uninstall.js +250 -0
- package/dist/registry/uninstall.js.map +1 -0
- package/dist/registry/uninstall.test.js +264 -0
- package/dist/registry/uninstall.test.js.map +1 -0
- package/dist/registry/update.js +280 -0
- package/dist/registry/update.js.map +1 -0
- package/dist/registry/update.test.js +229 -0
- package/dist/registry/update.test.js.map +1 -0
- package/dist/render.js +549 -0
- package/dist/render.js.map +1 -0
- package/dist/render.test.js +414 -0
- package/dist/render.test.js.map +1 -0
- package/dist/templates/.dev.vars.example.tmpl +32 -0
- package/dist/templates/.gitignore.tmpl +58 -0
- package/dist/templates/README.md.tmpl +417 -0
- package/dist/templates/app/[slug]/page.tsx.tmpl +55 -0
- package/dist/templates/app/admin/account/page.tsx.tmpl +18 -0
- package/dist/templates/app/admin/content-models/page.tsx.tmpl +6 -0
- package/dist/templates/app/admin/layout.tsx.tmpl +90 -0
- package/dist/templates/app/admin/loading.tsx.tmpl +6 -0
- package/dist/templates/app/admin/page.tsx.tmpl +17 -0
- package/dist/templates/app/api/auth/google/callback/route.ts.tmpl +3 -0
- package/dist/templates/app/api/auth/google/route.ts.tmpl +3 -0
- package/dist/templates/app/api/auth/verify-email/route.ts.tmpl +3 -0
- package/dist/templates/app/api/auth/viewer/route.ts.tmpl +3 -0
- package/dist/templates/app/api/health/route.ts.tmpl +3 -0
- package/dist/templates/app/api/{{contentSourceId}}/[slug]/route.ts.tmpl +27 -0
- package/dist/templates/app/api/{{contentSourceId}}/route.ts.tmpl +18 -0
- package/dist/templates/app/globals.css.tmpl +109 -0
- package/dist/templates/app/layout.tsx.tmpl +56 -0
- package/dist/templates/app/login/page.tsx.tmpl +154 -0
- package/dist/templates/app/page.fallback.tsx.tmpl +31 -0
- package/dist/templates/app/page.tsx.tmpl +42 -0
- package/dist/templates/app/register/page.tsx.tmpl +138 -0
- package/dist/templates/app/{{contentSourceListPath}}/[slug]/page.tsx.tmpl +113 -0
- package/dist/templates/app/{{contentSourceListPath}}/page.tsx.tmpl +74 -0
- package/dist/templates/components/content/post-card.tsx.tmpl +80 -0
- package/dist/templates/components/notion-blocks.tsx.tmpl +668 -0
- package/dist/templates/components/page-blocks/feature-grid-block.tsx.tmpl +68 -0
- package/dist/templates/components/page-blocks/hero-block.tsx.tmpl +73 -0
- package/dist/templates/components/page-blocks/latest-posts-block.tsx.tmpl +59 -0
- package/dist/templates/components/page-blocks/story-block.tsx.tmpl +70 -0
- package/dist/templates/components/page-blocks.fallback.tsx.tmpl +17 -0
- package/dist/templates/components/page-blocks.tsx.tmpl +32 -0
- package/dist/templates/components/search/search-dialog.tsx.tmpl +171 -0
- package/dist/templates/components/site/locale-switcher.tsx.tmpl +65 -0
- package/dist/templates/components/site/site-footer.tsx.tmpl +106 -0
- package/dist/templates/components/site/site-header.tsx.tmpl +80 -0
- package/dist/templates/components/site/site-shell.tsx.tmpl +20 -0
- package/dist/templates/components/site/theme-bootstrap.tsx.tmpl +51 -0
- package/dist/templates/components/theme-provider.tsx.tmpl +14 -0
- package/dist/templates/components/theme-toggle.tsx.tmpl +38 -0
- package/dist/templates/components/ui/accordion.tsx.tmpl +56 -0
- package/dist/templates/components/ui/alert.tsx.tmpl +59 -0
- package/dist/templates/components/ui/aspect-ratio.tsx.tmpl +8 -0
- package/dist/templates/components/ui/avatar.tsx.tmpl +44 -0
- package/dist/templates/components/ui/badge.tsx.tmpl +33 -0
- package/dist/templates/components/ui/button.tsx.tmpl +56 -0
- package/dist/templates/components/ui/card.tsx.tmpl +61 -0
- package/dist/templates/components/ui/checkbox.tsx.tmpl +28 -0
- package/dist/templates/components/ui/dialog.tsx.tmpl +104 -0
- package/dist/templates/components/ui/dropdown-menu.tsx.tmpl +183 -0
- package/dist/templates/components/ui/input.tsx.tmpl +21 -0
- package/dist/templates/components/ui/label.tsx.tmpl +25 -0
- package/dist/templates/components/ui/popover.tsx.tmpl +30 -0
- package/dist/templates/components/ui/radio-group.tsx.tmpl +44 -0
- package/dist/templates/components/ui/select.tsx.tmpl +150 -0
- package/dist/templates/components/ui/separator.tsx.tmpl +30 -0
- package/dist/templates/components/ui/sheet.tsx.tmpl +125 -0
- package/dist/templates/components/ui/skeleton.tsx.tmpl +15 -0
- package/dist/templates/components/ui/sonner.tsx.tmpl +30 -0
- package/dist/templates/components/ui/switch.tsx.tmpl +29 -0
- package/dist/templates/components/ui/table.tsx.tmpl +107 -0
- package/dist/templates/components/ui/tabs.tsx.tmpl +55 -0
- package/dist/templates/components/ui/textarea.tsx.tmpl +24 -0
- package/dist/templates/components/ui/tooltip.tsx.tmpl +30 -0
- package/dist/templates/components.json.tmpl +21 -0
- package/dist/templates/env.d.ts.tmpl +32 -0
- package/dist/templates/lib/admin/actions.ts.tmpl +43 -0
- package/dist/templates/lib/admin/context.tsx.tmpl +209 -0
- package/dist/templates/lib/admin/nav.ts.tmpl +23 -0
- package/dist/templates/lib/auth.config.fallback.ts.tmpl +10 -0
- package/dist/templates/lib/auth.config.ts.tmpl +45 -0
- package/dist/templates/lib/blocks/translations.ts.tmpl +44 -0
- package/dist/templates/lib/blog/translations.ts.tmpl +52 -0
- package/dist/templates/lib/content/models.ts.tmpl +53 -0
- package/dist/templates/lib/i18n/config.ts.tmpl +18 -0
- package/dist/templates/lib/i18n/index.ts.tmpl +1 -0
- package/dist/templates/lib/locale-contract/built-in.ts.tmpl +19 -0
- package/dist/templates/lib/locale-contract/index.ts.tmpl +3 -0
- package/dist/templates/lib/locale-contract/paths.ts.tmpl +29 -0
- package/dist/templates/lib/pages/model.ts.tmpl +16 -0
- package/dist/templates/lib/pages/source.ts.tmpl +566 -0
- package/dist/templates/lib/pages/translations.ts.tmpl +34 -0
- package/dist/templates/lib/search/config.fallback.ts.tmpl +11 -0
- package/dist/templates/lib/search/config.ts.tmpl +25 -0
- package/dist/templates/lib/site/config.ts.tmpl +120 -0
- package/dist/templates/lib/site/request-env.ts.tmpl +71 -0
- package/dist/templates/lib/site/settings.fallback.ts.tmpl +21 -0
- package/dist/templates/lib/site/settings.ts.tmpl +320 -0
- package/dist/templates/lib/site/translations.ts.tmpl +30 -0
- package/dist/templates/lib/utils.ts.tmpl +9 -0
- package/dist/templates/migrations/0001_init.sql.tmpl +57 -0
- package/dist/templates/migrations/0002_admin_seed.sql.tmpl +30 -0
- package/dist/templates/migrations/0003_search_index.sql.tmpl +29 -0
- package/dist/templates/next.config.ts.tmpl +18 -0
- package/dist/templates/package.json.tmpl +40 -0
- package/dist/templates/shims/cloudflare-workers-empty.mjs +4 -0
- package/dist/templates/shims/next-headers-empty.mjs +4 -0
- package/dist/templates/tests/smoke.test.ts.tmpl +83 -0
- package/dist/templates/tsconfig.json.tmpl +31 -0
- package/dist/templates/vite.config.ts.tmpl +53 -0
- package/dist/templates/vitest.config.ts.tmpl +13 -0
- package/dist/templates/worker/index.ts.tmpl +52 -0
- package/dist/templates/wrangler.jsonc.tmpl +44 -0
- package/dist/ui-presets.js +60 -0
- package/dist/ui-presets.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/uninstall.ts
|
|
2
|
+
//
|
|
3
|
+
// Core `notionx remove <id>` logic.
|
|
4
|
+
//
|
|
5
|
+
// Contract (mirrors `install.ts`):
|
|
6
|
+
// 1. Read `.notionx/registry.json`.
|
|
7
|
+
// 2. Reject if the item is not installed.
|
|
8
|
+
// 3. Refuse to remove an item that other items still depend on
|
|
9
|
+
// (e.g. can't remove `docs` if `search` requires it).
|
|
10
|
+
// 4. Re-render `lib/content/models.ts` without the removed item.
|
|
11
|
+
// 5. Update `registry.json` (drop the item; clear its file
|
|
12
|
+
// entries from `managedFiles`).
|
|
13
|
+
// 6. For `content-source` items: by default, do NOT delete the
|
|
14
|
+
// source's files from disk. Pass `purge: true` to delete the
|
|
15
|
+
// files recorded on `InstalledItem.files` at install time.
|
|
16
|
+
// 7. For `feature-module` items: render each file's
|
|
17
|
+
// `fallbackTemplate` to the same `path` (overwriting the
|
|
18
|
+
// Notion-backed version) so downstream importers keep
|
|
19
|
+
// compiling. Files without a `fallbackTemplate` are left on
|
|
20
|
+
// disk unless `purge: true` is passed.
|
|
21
|
+
// 8. Flip the item's `featureFlag` to `false` in the manifest
|
|
22
|
+
// (feature-module items only).
|
|
23
|
+
// 9. Never touch Notion or D1 data — surface cleanup as followup.
|
|
24
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
import { getOfficialItem } from "./registry-items.js";
|
|
27
|
+
import { loadRegistry } from "./load-registry.js";
|
|
28
|
+
import { writeRegistryManifest } from "./registry-store.js";
|
|
29
|
+
import { readProjectMeta, rerenderModelsFile, } from "./project-meta.js";
|
|
30
|
+
export class UninstallError extends Error {
|
|
31
|
+
code;
|
|
32
|
+
constructor(message, code) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.code = code;
|
|
35
|
+
this.name = "UninstallError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Uninstall a registry item from the project at `projectDir`.
|
|
40
|
+
*
|
|
41
|
+
* Throws `UninstallError` on the common failure modes.
|
|
42
|
+
*/
|
|
43
|
+
export async function uninstallItem(input) {
|
|
44
|
+
const { projectDir, templatesDir, itemId } = input;
|
|
45
|
+
const loaded = await loadRegistry(projectDir);
|
|
46
|
+
const manifest = loaded.manifest;
|
|
47
|
+
const installed = manifest.installed.find((i) => i.id === itemId);
|
|
48
|
+
if (!installed) {
|
|
49
|
+
throw new UninstallError(`"${itemId}" is not installed in this project. ` +
|
|
50
|
+
`Run \`notionx add ${itemId}\` to install it.`, "not-installed");
|
|
51
|
+
}
|
|
52
|
+
// Look up the catalog item to access `featureFlag` and
|
|
53
|
+
// `fallbackTemplate` metadata. The `InstalledItem` snapshot
|
|
54
|
+
// doesn't carry these — they live on the catalog `RegistryItem`.
|
|
55
|
+
const catalogItem = getOfficialItem(itemId);
|
|
56
|
+
// Refuse to remove an item that is `requires`d by something
|
|
57
|
+
// else still installed. The user must remove the dependent
|
|
58
|
+
// items first (e.g. `notionx remove search` before
|
|
59
|
+
// `notionx remove docs`). The `requires` list lives on the
|
|
60
|
+
// catalog's `RegistryItem`, not on `InstalledItem` — we look
|
|
61
|
+
// it up by id at check time.
|
|
62
|
+
const blockers = manifest.installed.filter((i) => {
|
|
63
|
+
const catalog = getOfficialItem(i.id);
|
|
64
|
+
if (!catalog)
|
|
65
|
+
return false;
|
|
66
|
+
return (catalog.requires ?? []).some((req) => req.id === itemId);
|
|
67
|
+
});
|
|
68
|
+
if (blockers.length > 0) {
|
|
69
|
+
const names = blockers.map((b) => b.id).join(", ");
|
|
70
|
+
throw new UninstallError(`Cannot remove "${itemId}" — required by: ${names}. ` +
|
|
71
|
+
`Remove those first.`, "still-required");
|
|
72
|
+
}
|
|
73
|
+
// The exact file list to purge: prefer the snapshot stored on
|
|
74
|
+
// `InstalledItem.files` (accurate). Fall back to an empty list
|
|
75
|
+
// for items installed before the `files` field existed.
|
|
76
|
+
const purgeable = installed.files ?? [];
|
|
77
|
+
// Compute the next manifest: drop the item, drop its file
|
|
78
|
+
// entries from `managedFiles`, and flip the feature flag to
|
|
79
|
+
// `false` if this is a feature-module item.
|
|
80
|
+
const nextManifest = {
|
|
81
|
+
...manifest,
|
|
82
|
+
installed: manifest.installed.filter((i) => i.id !== itemId),
|
|
83
|
+
managedFiles: clearItemFromManagedFiles(manifest, installed),
|
|
84
|
+
...applyFeatureFlagForUninstall(catalogItem),
|
|
85
|
+
};
|
|
86
|
+
// Compute the `internalSources` flags to pass to the renderers.
|
|
87
|
+
// For feature-module items, the flag being uninstalled flips to
|
|
88
|
+
// `false` so the generated `models.ts` drops the corresponding
|
|
89
|
+
// internal singleton source. For other kinds, the flags are
|
|
90
|
+
// unchanged from the (already-updated) nextManifest.
|
|
91
|
+
const internalSourcesForRender = {
|
|
92
|
+
siteSettings: nextManifest.enableSiteSettings,
|
|
93
|
+
blocks: nextManifest.enableBlocks,
|
|
94
|
+
};
|
|
95
|
+
// Re-render `lib/content/models.ts` to drop the source from
|
|
96
|
+
// `contentSources` / `managedContentSources` (and, for
|
|
97
|
+
// feature-module items, the internal singleton source).
|
|
98
|
+
const project = await readProjectMeta(projectDir, manifest);
|
|
99
|
+
const modelsResult = await rerenderModelsFile({
|
|
100
|
+
projectDir,
|
|
101
|
+
templatesDir,
|
|
102
|
+
project,
|
|
103
|
+
installed: nextManifest.installed,
|
|
104
|
+
internalSources: internalSourcesForRender,
|
|
105
|
+
});
|
|
106
|
+
// For feature-module items, render the fallback templates to
|
|
107
|
+
// the same paths so downstream importers keep compiling. The
|
|
108
|
+
// fallback list is computed up-front so dry-run can report it.
|
|
109
|
+
const fallbackFiles = catalogItem
|
|
110
|
+
? collectFallbackFiles(catalogItem)
|
|
111
|
+
: [];
|
|
112
|
+
const fallbackRenderedFiles = [];
|
|
113
|
+
const followup = buildFollowupTasks(installed, blockers, input.purge ?? false, catalogItem);
|
|
114
|
+
if (input.dryRun) {
|
|
115
|
+
return {
|
|
116
|
+
removedItem: installed,
|
|
117
|
+
rerenderedModels: modelsResult.wrote,
|
|
118
|
+
wroteManifest: false,
|
|
119
|
+
deletedFiles: [],
|
|
120
|
+
purgeableFiles: purgeable,
|
|
121
|
+
fallbackRenderedFiles: fallbackFiles.map((f) => f.path),
|
|
122
|
+
followup,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// Render fallback templates for feature-module items.
|
|
126
|
+
if (fallbackFiles.length > 0) {
|
|
127
|
+
const tokens = buildFallbackTokens(project);
|
|
128
|
+
for (const file of fallbackFiles) {
|
|
129
|
+
const tplAbs = path.join(templatesDir, file.fallbackTemplate);
|
|
130
|
+
let tpl;
|
|
131
|
+
try {
|
|
132
|
+
tpl = await readFile(tplAbs, "utf8");
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Fallback template missing — skip silently (file stays
|
|
136
|
+
// as-is on disk; user can hand-edit if needed).
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const rendered = renderTemplate(tpl, tokens);
|
|
140
|
+
const destAbs = path.join(projectDir, file.path);
|
|
141
|
+
await mkdir(path.dirname(destAbs), { recursive: true });
|
|
142
|
+
await writeFile(destAbs, rendered, "utf8");
|
|
143
|
+
fallbackRenderedFiles.push(file.path);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Delete files from disk if `--purge` was passed.
|
|
147
|
+
const deletedFiles = [];
|
|
148
|
+
if (input.purge) {
|
|
149
|
+
for (const relPath of purgeable) {
|
|
150
|
+
const absPath = path.join(projectDir, relPath);
|
|
151
|
+
try {
|
|
152
|
+
await rm(absPath, { recursive: true, force: true });
|
|
153
|
+
deletedFiles.push(relPath);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// File may have been manually deleted already — skip.
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
await writeRegistryManifest(projectDir, nextManifest);
|
|
161
|
+
return {
|
|
162
|
+
removedItem: installed,
|
|
163
|
+
rerenderedModels: modelsResult.wrote,
|
|
164
|
+
wroteManifest: true,
|
|
165
|
+
deletedFiles,
|
|
166
|
+
purgeableFiles: purgeable,
|
|
167
|
+
fallbackRenderedFiles,
|
|
168
|
+
followup,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// ---- internals ----
|
|
172
|
+
function clearItemFromManagedFiles(manifest, installed) {
|
|
173
|
+
// Use the authoritative file list recorded on `InstalledItem.files`
|
|
174
|
+
// at install time. The old path-heuristic (`/${itemId}/`) missed
|
|
175
|
+
// files whose paths don't contain the item id as a path segment
|
|
176
|
+
// (e.g. `migrations/0003_search_index.sql` for the `search` item).
|
|
177
|
+
const itemFiles = new Set(installed.files ?? []);
|
|
178
|
+
const filterPath = (p) => !itemFiles.has(p);
|
|
179
|
+
return {
|
|
180
|
+
platform: manifest.managedFiles.platform.filter(filterPath),
|
|
181
|
+
bridge: manifest.managedFiles.bridge.filter(filterPath),
|
|
182
|
+
user: manifest.managedFiles.user.filter(filterPath),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Return a partial manifest patch that flips the feature flag
|
|
187
|
+
* controlled by `item` to `false`. Returns `{}` for items without
|
|
188
|
+
* a `featureFlag` (content-source / platform-extension / unknown).
|
|
189
|
+
*/
|
|
190
|
+
function applyFeatureFlagForUninstall(item) {
|
|
191
|
+
if (!item || !item.featureFlag)
|
|
192
|
+
return {};
|
|
193
|
+
return { [item.featureFlag]: false };
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Collect the files on `item` that declare a `fallbackTemplate`.
|
|
197
|
+
* These are the files that get overwritten with the fallback
|
|
198
|
+
* content during uninstall (instead of being deleted).
|
|
199
|
+
*/
|
|
200
|
+
function collectFallbackFiles(item) {
|
|
201
|
+
const out = [];
|
|
202
|
+
for (const file of item.files) {
|
|
203
|
+
if (file.fallbackTemplate) {
|
|
204
|
+
out.push({ path: file.path, fallbackTemplate: file.fallbackTemplate });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Build the minimal token map used by fallback templates. Fallback
|
|
211
|
+
* templates are intentionally simple (they return static content)
|
|
212
|
+
* so they only need the basic project tokens — no content-source
|
|
213
|
+
* or internal-source tokens.
|
|
214
|
+
*/
|
|
215
|
+
function buildFallbackTokens(project) {
|
|
216
|
+
return {
|
|
217
|
+
projectName: project.projectName,
|
|
218
|
+
projectNameLower: project.projectName.toLowerCase(),
|
|
219
|
+
defaultLocale: project.defaultLocale,
|
|
220
|
+
supportedLocales: project.supportedLocales.join(", "),
|
|
221
|
+
supportedLocalesJson: JSON.stringify(project.supportedLocales),
|
|
222
|
+
notionxSource: project.notionxSource,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function renderTemplate(input, tokens) {
|
|
226
|
+
return input.replace(/\{\{\s*([a-zA-Z][a-zA-Z0-9_]*)\s*\}\}/g, (full, key) => {
|
|
227
|
+
const value = tokens[key];
|
|
228
|
+
if (typeof value === "string")
|
|
229
|
+
return value;
|
|
230
|
+
return full;
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
function buildFollowupTasks(item, blockers, purged, catalogItem) {
|
|
234
|
+
const out = [];
|
|
235
|
+
const isFeatureModule = catalogItem?.kind === "feature-module";
|
|
236
|
+
if (isFeatureModule) {
|
|
237
|
+
out.push(`The fallback version of "${item.id}" is now active. ` +
|
|
238
|
+
`Re-add with \`notionx add ${item.id}\` to restore the Notion-backed version.`);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
out.push(`The data source for "${item.id}" in Notion is untouched. ` +
|
|
242
|
+
`Re-add with \`notionx add ${item.id}\` to wire it back, or ` +
|
|
243
|
+
`manually archive the Notion data source.`);
|
|
244
|
+
}
|
|
245
|
+
if (!purged && blockers.length === 0) {
|
|
246
|
+
out.push(`Run \`notionx remove --purge ${item.id}\` to also delete the generated files.`);
|
|
247
|
+
}
|
|
248
|
+
return out;
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=uninstall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/registry/uninstall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/uninstall.test.ts
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
8
|
+
import { resolveTemplatesDir } from "../render.js";
|
|
9
|
+
import { installItem } from "./install.js";
|
|
10
|
+
import { REGISTRY_SCHEMA_V2 } from "./registry-types.js";
|
|
11
|
+
import { UninstallError, uninstallItem } from "./uninstall.js";
|
|
12
|
+
async function writePackageJson(projectDir, name) {
|
|
13
|
+
await writeFile(path.join(projectDir, "package.json"), JSON.stringify({
|
|
14
|
+
name,
|
|
15
|
+
version: "0.0.0",
|
|
16
|
+
private: true,
|
|
17
|
+
dependencies: { "@notionx/core": "^2.0.0" },
|
|
18
|
+
}), "utf8");
|
|
19
|
+
}
|
|
20
|
+
async function writeV2ManifestWith(projectDir, installed, managedFiles = {}, overrides = {}) {
|
|
21
|
+
await mkdir(path.join(projectDir, ".notionx"), { recursive: true });
|
|
22
|
+
await writeFile(path.join(projectDir, ".notionx/registry.json"), JSON.stringify({
|
|
23
|
+
$schema: REGISTRY_SCHEMA_V2,
|
|
24
|
+
projectKind: "notionx",
|
|
25
|
+
projectName: "demo",
|
|
26
|
+
scaffoldVersion: "2.0.0",
|
|
27
|
+
notionxCore: "^2.0.0",
|
|
28
|
+
defaultLocale: "en",
|
|
29
|
+
supportedLocales: ["en"],
|
|
30
|
+
enableSiteSettings: true,
|
|
31
|
+
enableBlocks: true,
|
|
32
|
+
enableSearch: true,
|
|
33
|
+
contentSource: {
|
|
34
|
+
id: "blog",
|
|
35
|
+
title: "Blog",
|
|
36
|
+
fields: [],
|
|
37
|
+
},
|
|
38
|
+
compat: { mode: "v2-native" },
|
|
39
|
+
registries: {},
|
|
40
|
+
installed,
|
|
41
|
+
managedFiles: {
|
|
42
|
+
platform: managedFiles.platform ?? ["package.json"],
|
|
43
|
+
bridge: managedFiles.bridge ?? [],
|
|
44
|
+
user: managedFiles.user ?? [],
|
|
45
|
+
},
|
|
46
|
+
...overrides,
|
|
47
|
+
}), "utf8");
|
|
48
|
+
}
|
|
49
|
+
describe("uninstallItem", () => {
|
|
50
|
+
let dir;
|
|
51
|
+
let templatesDir;
|
|
52
|
+
beforeEach(async () => {
|
|
53
|
+
dir = await mkdtemp(path.join(os.tmpdir(), "notionx-uninstall-"));
|
|
54
|
+
await mkdir(path.join(dir, ".notionx"), { recursive: true });
|
|
55
|
+
templatesDir = await resolveTemplatesDir();
|
|
56
|
+
});
|
|
57
|
+
afterEach(async () => {
|
|
58
|
+
await rm(dir, { recursive: true, force: true });
|
|
59
|
+
});
|
|
60
|
+
it("removes docs from a v2 project and updates the manifest + models.ts", async () => {
|
|
61
|
+
await writePackageJson(dir, "demo");
|
|
62
|
+
await writeV2ManifestWith(dir, [
|
|
63
|
+
{
|
|
64
|
+
id: "blog",
|
|
65
|
+
kind: "content-source",
|
|
66
|
+
version: 1,
|
|
67
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
68
|
+
params: { contentSourceId: "blog" },
|
|
69
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: "docs",
|
|
73
|
+
kind: "content-source",
|
|
74
|
+
version: 1,
|
|
75
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
76
|
+
params: { contentSourceId: "docs", basePath: "/docs" },
|
|
77
|
+
installedAt: "2026-06-10T08:00:00.000Z",
|
|
78
|
+
},
|
|
79
|
+
]);
|
|
80
|
+
const summary = await uninstallItem({
|
|
81
|
+
projectDir: dir,
|
|
82
|
+
templatesDir,
|
|
83
|
+
itemId: "docs",
|
|
84
|
+
});
|
|
85
|
+
expect(summary.removedItem.id).toBe("docs");
|
|
86
|
+
expect(summary.wroteManifest).toBe(true);
|
|
87
|
+
expect(summary.rerenderedModels).toBe(true);
|
|
88
|
+
const manifestRaw = await fs.readFile(path.join(dir, ".notionx/registry.json"), "utf8");
|
|
89
|
+
const manifest = JSON.parse(manifestRaw);
|
|
90
|
+
expect(manifest.installed.map((i) => i.id)).toEqual(["blog"]);
|
|
91
|
+
const models = await fs.readFile(path.join(dir, "lib/content/models.ts"), "utf8");
|
|
92
|
+
expect(models).toContain("blogSource");
|
|
93
|
+
expect(models).not.toContain("docsSource");
|
|
94
|
+
});
|
|
95
|
+
it("rejects removing an item that is not installed", async () => {
|
|
96
|
+
await writePackageJson(dir, "demo");
|
|
97
|
+
await writeV2ManifestWith(dir, [
|
|
98
|
+
{
|
|
99
|
+
id: "blog",
|
|
100
|
+
kind: "content-source",
|
|
101
|
+
version: 1,
|
|
102
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
103
|
+
params: { contentSourceId: "blog" },
|
|
104
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
105
|
+
},
|
|
106
|
+
]);
|
|
107
|
+
try {
|
|
108
|
+
await uninstallItem({ projectDir: dir, templatesDir, itemId: "docs" });
|
|
109
|
+
throw new Error("expected uninstallItem to throw");
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
expect(err).toBeInstanceOf(UninstallError);
|
|
113
|
+
expect(err.code).toBe("not-installed");
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
it("round-trip: install docs, then remove docs, leaves blog intact", async () => {
|
|
117
|
+
await writePackageJson(dir, "demo");
|
|
118
|
+
await writeV2ManifestWith(dir, [
|
|
119
|
+
{
|
|
120
|
+
id: "blog",
|
|
121
|
+
kind: "content-source",
|
|
122
|
+
version: 1,
|
|
123
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
124
|
+
params: { contentSourceId: "blog" },
|
|
125
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
126
|
+
},
|
|
127
|
+
]);
|
|
128
|
+
await installItem({ projectDir: dir, templatesDir, itemId: "docs" });
|
|
129
|
+
expect(existsSync(path.join(dir, "app/docs/page.tsx"))).toBe(true);
|
|
130
|
+
const summary = await uninstallItem({
|
|
131
|
+
projectDir: dir,
|
|
132
|
+
templatesDir,
|
|
133
|
+
itemId: "docs",
|
|
134
|
+
});
|
|
135
|
+
expect(summary.removedItem.id).toBe("docs");
|
|
136
|
+
const manifestRaw = await fs.readFile(path.join(dir, ".notionx/registry.json"), "utf8");
|
|
137
|
+
const manifest = JSON.parse(manifestRaw);
|
|
138
|
+
expect(manifest.installed.map((i) => i.id)).toEqual(["blog"]);
|
|
139
|
+
// The Notion data source is *not* touched; the followup
|
|
140
|
+
// mentions how to clean it up manually.
|
|
141
|
+
const joined = summary.followup.join("\n");
|
|
142
|
+
expect(joined).toContain("Notion");
|
|
143
|
+
});
|
|
144
|
+
it("dry-run does not write the manifest", async () => {
|
|
145
|
+
await writePackageJson(dir, "demo");
|
|
146
|
+
await writeV2ManifestWith(dir, [
|
|
147
|
+
{
|
|
148
|
+
id: "blog",
|
|
149
|
+
kind: "content-source",
|
|
150
|
+
version: 1,
|
|
151
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
152
|
+
params: { contentSourceId: "blog" },
|
|
153
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: "docs",
|
|
157
|
+
kind: "content-source",
|
|
158
|
+
version: 1,
|
|
159
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
160
|
+
params: { contentSourceId: "docs", basePath: "/docs" },
|
|
161
|
+
installedAt: "2026-06-10T08:00:00.000Z",
|
|
162
|
+
},
|
|
163
|
+
]);
|
|
164
|
+
const summary = await uninstallItem({
|
|
165
|
+
projectDir: dir,
|
|
166
|
+
templatesDir,
|
|
167
|
+
itemId: "docs",
|
|
168
|
+
dryRun: true,
|
|
169
|
+
});
|
|
170
|
+
expect(summary.wroteManifest).toBe(false);
|
|
171
|
+
// Manifest is unchanged
|
|
172
|
+
const manifestRaw = await fs.readFile(path.join(dir, ".notionx/registry.json"), "utf8");
|
|
173
|
+
const manifest = JSON.parse(manifestRaw);
|
|
174
|
+
expect(manifest.installed.map((i) => i.id).sort()).toEqual([
|
|
175
|
+
"blog",
|
|
176
|
+
"docs",
|
|
177
|
+
]);
|
|
178
|
+
});
|
|
179
|
+
it("feature-module: uninstalling site-settings renders fallback + flips flag", async () => {
|
|
180
|
+
await writePackageJson(dir, "demo");
|
|
181
|
+
await writeV2ManifestWith(dir, [
|
|
182
|
+
{
|
|
183
|
+
id: "blog",
|
|
184
|
+
kind: "content-source",
|
|
185
|
+
version: 1,
|
|
186
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
187
|
+
params: { contentSourceId: "blog" },
|
|
188
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
id: "site-settings",
|
|
192
|
+
kind: "feature-module",
|
|
193
|
+
version: 1,
|
|
194
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
195
|
+
params: {},
|
|
196
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
197
|
+
files: ["lib/site/settings.ts"],
|
|
198
|
+
},
|
|
199
|
+
], {
|
|
200
|
+
bridge: ["lib/site/settings.ts"],
|
|
201
|
+
});
|
|
202
|
+
const summary = await uninstallItem({
|
|
203
|
+
projectDir: dir,
|
|
204
|
+
templatesDir,
|
|
205
|
+
itemId: "site-settings",
|
|
206
|
+
});
|
|
207
|
+
expect(summary.removedItem.id).toBe("site-settings");
|
|
208
|
+
expect(summary.fallbackRenderedFiles).toContain("lib/site/settings.ts");
|
|
209
|
+
expect(summary.deletedFiles).toEqual([]);
|
|
210
|
+
// The manifest flag should be flipped to false.
|
|
211
|
+
const manifestRaw = await fs.readFile(path.join(dir, ".notionx/registry.json"), "utf8");
|
|
212
|
+
const manifest = JSON.parse(manifestRaw);
|
|
213
|
+
expect(manifest.installed.map((i) => i.id)).toEqual(["blog"]);
|
|
214
|
+
expect(manifest.enableSiteSettings).toBe(false);
|
|
215
|
+
// models.ts should no longer declare siteSettingsSource.
|
|
216
|
+
const models = await fs.readFile(path.join(dir, "lib/content/models.ts"), "utf8");
|
|
217
|
+
expect(models).not.toContain('export const siteSettingsSource');
|
|
218
|
+
expect(models).not.toContain('"site-settings"');
|
|
219
|
+
// The fallback file should be rendered (it returns the
|
|
220
|
+
// fallback site config directly).
|
|
221
|
+
const settings = await fs.readFile(path.join(dir, "lib/site/settings.ts"), "utf8");
|
|
222
|
+
expect(settings).toContain("fallbackSiteConfig");
|
|
223
|
+
// Followup should mention the fallback is active.
|
|
224
|
+
const joined = summary.followup.join("\n");
|
|
225
|
+
expect(joined).toContain("fallback");
|
|
226
|
+
});
|
|
227
|
+
it("feature-module: dry-run reports fallback files without writing", async () => {
|
|
228
|
+
await writePackageJson(dir, "demo");
|
|
229
|
+
await writeV2ManifestWith(dir, [
|
|
230
|
+
{
|
|
231
|
+
id: "blog",
|
|
232
|
+
kind: "content-source",
|
|
233
|
+
version: 1,
|
|
234
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
235
|
+
params: { contentSourceId: "blog" },
|
|
236
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
id: "blocks",
|
|
240
|
+
kind: "feature-module",
|
|
241
|
+
version: 1,
|
|
242
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
243
|
+
params: {},
|
|
244
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
245
|
+
files: ["components/page-blocks.tsx"],
|
|
246
|
+
},
|
|
247
|
+
], {
|
|
248
|
+
bridge: ["components/page-blocks.tsx"],
|
|
249
|
+
});
|
|
250
|
+
const summary = await uninstallItem({
|
|
251
|
+
projectDir: dir,
|
|
252
|
+
templatesDir,
|
|
253
|
+
itemId: "blocks",
|
|
254
|
+
dryRun: true,
|
|
255
|
+
});
|
|
256
|
+
expect(summary.wroteManifest).toBe(false);
|
|
257
|
+
expect(summary.fallbackRenderedFiles).toContain("components/page-blocks.tsx");
|
|
258
|
+
// Manifest unchanged.
|
|
259
|
+
const manifestRaw = await fs.readFile(path.join(dir, ".notionx/registry.json"), "utf8");
|
|
260
|
+
const manifest = JSON.parse(manifestRaw);
|
|
261
|
+
expect(manifest.enableBlocks).toBe(true);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
//# sourceMappingURL=uninstall.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstall.test.js","sourceRoot":"","sources":["../../src/registry/uninstall.test.ts"],"names":[],"mappings":"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"}
|