@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,217 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/install.ts
|
|
2
|
+
//
|
|
3
|
+
// Core `notionx add <id>` logic. v1 of this module wires the
|
|
4
|
+
// minimal subset needed to make `notionx add docs` a working
|
|
5
|
+
// command; richer behaviour (Notion schema sync, codemods,
|
|
6
|
+
// file-content merge for `user`-owned files) lives in PR 4.
|
|
7
|
+
//
|
|
8
|
+
// The contract:
|
|
9
|
+
// 1. Read `.notionx/registry.json`.
|
|
10
|
+
// 2. Reject if the item is already installed, or if a
|
|
11
|
+
// `requires` dependency is missing.
|
|
12
|
+
// 3. Render the new item's files (using the project templates
|
|
13
|
+
// directory, which the CLI looks up next to its own package).
|
|
14
|
+
// 4. Re-render `lib/content/models.ts` so the new source shows
|
|
15
|
+
// up in `contentSources` / `managedContentSources`.
|
|
16
|
+
// 5. Write the new `registry.json` and a human-readable followup
|
|
17
|
+
// list (Notion env vars to set, D1 migrations to apply).
|
|
18
|
+
//
|
|
19
|
+
// Everything is pure async + returns a summary object; the CLI
|
|
20
|
+
// layer is responsible for printing the summary.
|
|
21
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
import { getOfficialItem, listOfficialItems } from "./registry-items.js";
|
|
24
|
+
import { loadRegistry } from "./load-registry.js";
|
|
25
|
+
import { renderContentSourceFiles } from "./render-content-source-files.js";
|
|
26
|
+
import { writeRegistryManifest } from "./registry-store.js";
|
|
27
|
+
import { readProjectMeta, rerenderModelsFile, } from "./project-meta.js";
|
|
28
|
+
export class InstallError extends Error {
|
|
29
|
+
code;
|
|
30
|
+
constructor(message, code) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.code = code;
|
|
33
|
+
this.name = "InstallError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Install a registry item into the project at `projectDir`.
|
|
38
|
+
*
|
|
39
|
+
* Throws `InstallError` on the common failure modes so the CLI
|
|
40
|
+
* can print a stable, human-readable error.
|
|
41
|
+
*/
|
|
42
|
+
export async function installItem(input) {
|
|
43
|
+
const { projectDir, templatesDir, itemId } = input;
|
|
44
|
+
const item = getOfficialItem(itemId);
|
|
45
|
+
if (!item) {
|
|
46
|
+
throw new InstallError(`Unknown registry item "${itemId}". Run \`notionx add --list\` to see available items.`, "unknown-item");
|
|
47
|
+
}
|
|
48
|
+
const finalItem = input.params
|
|
49
|
+
? { ...item, params: { ...item.params, ...input.params } }
|
|
50
|
+
: item;
|
|
51
|
+
// Load the current registry.
|
|
52
|
+
const loaded = await loadRegistry(projectDir);
|
|
53
|
+
const manifest = loaded.manifest;
|
|
54
|
+
// Idempotency: reject re-installing the same id. `notionx update`
|
|
55
|
+
// handles version upgrades; `notionx add` is for new items.
|
|
56
|
+
if (manifest.installed.some((i) => i.id === finalItem.id)) {
|
|
57
|
+
throw new InstallError(`"${finalItem.id}" is already installed in this project. ` +
|
|
58
|
+
`Use \`notionx update ${finalItem.id}\` to upgrade it, ` +
|
|
59
|
+
`or \`notionx remove ${finalItem.id}\` to uninstall.`, "already-installed");
|
|
60
|
+
}
|
|
61
|
+
// Dependency check: every `requires` entry must be satisfied by
|
|
62
|
+
// something already installed. We use simple semver-equality
|
|
63
|
+
// (only ">=X" today); PR 4 will add a `semver.satisfies` check
|
|
64
|
+
// for ranges.
|
|
65
|
+
for (const req of finalItem.requires ?? []) {
|
|
66
|
+
const dep = manifest.installed.find((i) => i.id === req.id);
|
|
67
|
+
if (!dep) {
|
|
68
|
+
throw new InstallError(`"${finalItem.id}" requires "${req.id}" to be installed first. ` +
|
|
69
|
+
`Run \`notionx add ${req.id}\` and try again.`, "missing-requirement");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Compute the new installed record. We snapshot the rendered
|
|
73
|
+
// file paths so `notionx remove --purge` can delete the exact
|
|
74
|
+
// set that was written (no heuristic path matching).
|
|
75
|
+
const installed = {
|
|
76
|
+
id: finalItem.id,
|
|
77
|
+
kind: finalItem.kind,
|
|
78
|
+
version: finalItem.version,
|
|
79
|
+
source: finalItem.source,
|
|
80
|
+
params: finalItem.params,
|
|
81
|
+
installedAt: new Date().toISOString(),
|
|
82
|
+
};
|
|
83
|
+
// The list of "currently installed" used for token rendering
|
|
84
|
+
// is the existing list **plus** the new item (in the same
|
|
85
|
+
// alphabetical order so generated diffs are stable).
|
|
86
|
+
const installedForRender = [
|
|
87
|
+
...manifest.installed,
|
|
88
|
+
installed,
|
|
89
|
+
].sort((a, b) => a.id.localeCompare(b.id));
|
|
90
|
+
const project = await readProjectMeta(projectDir, manifest);
|
|
91
|
+
// For feature-module items, the install flips the manifest flag
|
|
92
|
+
// to `true` so `rerenderModelsFile` includes the corresponding
|
|
93
|
+
// internal singleton source. For content-source items, the
|
|
94
|
+
// flags are unchanged.
|
|
95
|
+
const internalSourcesForRender = computeInternalSourcesForInstall(manifest, finalItem);
|
|
96
|
+
// Render the new files (currently: just the list page).
|
|
97
|
+
const rendered = await renderContentSourceFiles({
|
|
98
|
+
projectDir,
|
|
99
|
+
templatesDir,
|
|
100
|
+
item: finalItem,
|
|
101
|
+
installed: installedForRender,
|
|
102
|
+
project,
|
|
103
|
+
internalSources: internalSourcesForRender,
|
|
104
|
+
});
|
|
105
|
+
// Re-render `lib/content/models.ts` so the new source is
|
|
106
|
+
// registered in `contentSources` / `managedContentSources`.
|
|
107
|
+
const modelsResult = await rerenderModelsFile({
|
|
108
|
+
projectDir,
|
|
109
|
+
templatesDir,
|
|
110
|
+
project,
|
|
111
|
+
installed: installedForRender,
|
|
112
|
+
internalSources: internalSourcesForRender,
|
|
113
|
+
});
|
|
114
|
+
// Snapshot the rendered file paths on the InstalledItem so
|
|
115
|
+
// `notionx remove --purge` can delete the exact set later.
|
|
116
|
+
installed.files = rendered.map((f) => f.projectRelativePath);
|
|
117
|
+
const followup = buildFollowupTasks(finalItem, manifest);
|
|
118
|
+
if (input.dryRun) {
|
|
119
|
+
return {
|
|
120
|
+
item: finalItem,
|
|
121
|
+
installed,
|
|
122
|
+
files: rendered.map((f) => ({
|
|
123
|
+
projectRelativePath: f.projectRelativePath,
|
|
124
|
+
ownership: f.ownership,
|
|
125
|
+
existed: f.existed,
|
|
126
|
+
})),
|
|
127
|
+
rerenderedModels: modelsResult.wrote,
|
|
128
|
+
wroteManifest: false,
|
|
129
|
+
followup,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// Write the rendered files.
|
|
133
|
+
for (const file of rendered) {
|
|
134
|
+
await mkdir(path.dirname(file.absolutePath), { recursive: true });
|
|
135
|
+
await writeFile(file.absolutePath, file.content, "utf8");
|
|
136
|
+
}
|
|
137
|
+
// Update the manifest: add the new InstalledItem, the
|
|
138
|
+
// `user`/`bridge` files to `managedFiles`, and flip the
|
|
139
|
+
// feature flag (if this is a feature-module item).
|
|
140
|
+
const nextManifest = {
|
|
141
|
+
...manifest,
|
|
142
|
+
installed: installedForRender,
|
|
143
|
+
managedFiles: mergeManagedFilesForInstall(manifest, finalItem),
|
|
144
|
+
...applyFeatureFlag(manifest, finalItem, true),
|
|
145
|
+
};
|
|
146
|
+
await writeRegistryManifest(projectDir, nextManifest);
|
|
147
|
+
return {
|
|
148
|
+
item: finalItem,
|
|
149
|
+
installed,
|
|
150
|
+
files: rendered.map((f) => ({
|
|
151
|
+
projectRelativePath: f.projectRelativePath,
|
|
152
|
+
ownership: f.ownership,
|
|
153
|
+
existed: f.existed,
|
|
154
|
+
})),
|
|
155
|
+
rerenderedModels: modelsResult.wrote,
|
|
156
|
+
wroteManifest: true,
|
|
157
|
+
followup,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// ---- internals ----
|
|
161
|
+
function buildFollowupTasks(item, _manifest) {
|
|
162
|
+
const out = [];
|
|
163
|
+
for (const env of item.capabilities.envVars ?? []) {
|
|
164
|
+
out.push(`Set \`${env}\` in .dev.vars (see Notion data source for the id).`);
|
|
165
|
+
}
|
|
166
|
+
for (const ds of item.capabilities.notionDataSources ?? []) {
|
|
167
|
+
out.push(`Create the matching Notion data source and set \`${ds}\` in .dev.vars.`);
|
|
168
|
+
}
|
|
169
|
+
if ((item.capabilities.d1Tables ?? []).length > 0) {
|
|
170
|
+
out.push(`Run \`wrangler d1 migrations apply <DB_NAME> --remote\` to create the new tables.`);
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
function mergeManagedFilesForInstall(manifest, item) {
|
|
175
|
+
const user = new Set(manifest.managedFiles.user);
|
|
176
|
+
const bridge = new Set(manifest.managedFiles.bridge);
|
|
177
|
+
const platform = new Set(manifest.managedFiles.platform);
|
|
178
|
+
for (const file of item.files) {
|
|
179
|
+
if (file.ownership === "user")
|
|
180
|
+
user.add(file.path);
|
|
181
|
+
else if (file.ownership === "bridge")
|
|
182
|
+
bridge.add(file.path);
|
|
183
|
+
else
|
|
184
|
+
platform.add(file.path);
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
platform: [...platform].sort(),
|
|
188
|
+
bridge: [...bridge].sort(),
|
|
189
|
+
user: [...user].sort(),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Compute the `internalSources` flags to pass to the renderers
|
|
194
|
+
* during install. For feature-module items, the flag being
|
|
195
|
+
* installed flips to `true` so the generated `models.ts` includes
|
|
196
|
+
* the corresponding internal singleton source. For other kinds,
|
|
197
|
+
* the flags are unchanged from the manifest.
|
|
198
|
+
*/
|
|
199
|
+
function computeInternalSourcesForInstall(manifest, item) {
|
|
200
|
+
const siteSettings = item.featureFlag === "enableSiteSettings"
|
|
201
|
+
? true
|
|
202
|
+
: manifest.enableSiteSettings;
|
|
203
|
+
const blocks = item.featureFlag === "enableBlocks" ? true : manifest.enableBlocks;
|
|
204
|
+
return { siteSettings, blocks };
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Return a partial manifest patch that flips the feature flag
|
|
208
|
+
* controlled by `item` to `value`. Returns `{}` for items without
|
|
209
|
+
* a `featureFlag` (content-source / platform-extension).
|
|
210
|
+
*/
|
|
211
|
+
function applyFeatureFlag(_manifest, item, value) {
|
|
212
|
+
if (!item.featureFlag)
|
|
213
|
+
return {};
|
|
214
|
+
return { [item.featureFlag]: value };
|
|
215
|
+
}
|
|
216
|
+
export { listOfficialItems };
|
|
217
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/registry/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/install.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 { InstallError, installItem } from "./install.js";
|
|
10
|
+
import { REGISTRY_SCHEMA_V2 } from "./registry-types.js";
|
|
11
|
+
async function writePackageJson(projectDir, name, deps = {}) {
|
|
12
|
+
await writeFile(path.join(projectDir, "package.json"), JSON.stringify({
|
|
13
|
+
name,
|
|
14
|
+
version: "0.0.0",
|
|
15
|
+
private: true,
|
|
16
|
+
dependencies: { "@notionx/core": "^2.0.0", ...deps },
|
|
17
|
+
}), "utf8");
|
|
18
|
+
}
|
|
19
|
+
async function writeV2Manifest(projectDir, installed = [
|
|
20
|
+
{
|
|
21
|
+
id: "blog",
|
|
22
|
+
kind: "content-source",
|
|
23
|
+
version: 1,
|
|
24
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
25
|
+
params: { contentSourceId: "blog" },
|
|
26
|
+
installedAt: "2026-06-10T00:00:00.000Z",
|
|
27
|
+
},
|
|
28
|
+
], managedFiles = {}) {
|
|
29
|
+
await mkdir(path.join(projectDir, ".notionx"), { recursive: true });
|
|
30
|
+
await writeFile(path.join(projectDir, ".notionx/registry.json"), JSON.stringify({
|
|
31
|
+
$schema: REGISTRY_SCHEMA_V2,
|
|
32
|
+
projectKind: "notionx",
|
|
33
|
+
scaffoldVersion: "2.0.0",
|
|
34
|
+
notionxCore: "^2.0.0",
|
|
35
|
+
compat: { mode: "v2-native" },
|
|
36
|
+
registries: {},
|
|
37
|
+
installed,
|
|
38
|
+
managedFiles: {
|
|
39
|
+
platform: managedFiles.platform ?? ["package.json"],
|
|
40
|
+
bridge: managedFiles.bridge ?? ["lib/notionx/content-registry.ts"],
|
|
41
|
+
user: managedFiles.user ?? ["lib/content/models.ts", "app/blog/page.tsx"],
|
|
42
|
+
},
|
|
43
|
+
}), "utf8");
|
|
44
|
+
}
|
|
45
|
+
describe("installItem", () => {
|
|
46
|
+
let dir;
|
|
47
|
+
let templatesDir;
|
|
48
|
+
beforeEach(async () => {
|
|
49
|
+
dir = await mkdtemp(path.join(os.tmpdir(), "notionx-install-"));
|
|
50
|
+
await mkdir(path.join(dir, ".notionx"), { recursive: true });
|
|
51
|
+
templatesDir = await resolveTemplatesDir();
|
|
52
|
+
});
|
|
53
|
+
afterEach(async () => {
|
|
54
|
+
await rm(dir, { recursive: true, force: true });
|
|
55
|
+
});
|
|
56
|
+
it("installs docs into a v2 project, writing all content source files and updating the manifest", async () => {
|
|
57
|
+
await writePackageJson(dir, "demo");
|
|
58
|
+
await writeV2Manifest(dir);
|
|
59
|
+
const summary = await installItem({
|
|
60
|
+
projectDir: dir,
|
|
61
|
+
templatesDir,
|
|
62
|
+
itemId: "docs",
|
|
63
|
+
});
|
|
64
|
+
expect(summary.item.id).toBe("docs");
|
|
65
|
+
expect(summary.wroteManifest).toBe(true);
|
|
66
|
+
expect(summary.rerenderedModels).toBe(true);
|
|
67
|
+
expect(summary.files.map((f) => f.projectRelativePath)).toEqual([
|
|
68
|
+
"app/docs/page.tsx",
|
|
69
|
+
"app/docs/[slug]/page.tsx",
|
|
70
|
+
"app/api/docs/route.ts",
|
|
71
|
+
"app/api/docs/[slug]/route.ts",
|
|
72
|
+
]);
|
|
73
|
+
// The list page landed on disk
|
|
74
|
+
const listPath = path.join(dir, "app/docs/page.tsx");
|
|
75
|
+
expect(existsSync(listPath)).toBe(true);
|
|
76
|
+
const content = await fs.readFile(listPath, "utf8");
|
|
77
|
+
// The list page references the new content source
|
|
78
|
+
expect(content).toContain('"docs"');
|
|
79
|
+
expect(content).toContain("/docs");
|
|
80
|
+
// The detail page also landed
|
|
81
|
+
expect(existsSync(path.join(dir, "app/docs/[slug]/page.tsx"))).toBe(true);
|
|
82
|
+
// API routes landed
|
|
83
|
+
expect(existsSync(path.join(dir, "app/api/docs/route.ts"))).toBe(true);
|
|
84
|
+
expect(existsSync(path.join(dir, "app/api/docs/[slug]/route.ts"))).toBe(true);
|
|
85
|
+
// The manifest was updated
|
|
86
|
+
const manifestRaw = await fs.readFile(path.join(dir, ".notionx/registry.json"), "utf8");
|
|
87
|
+
const manifest = JSON.parse(manifestRaw);
|
|
88
|
+
expect(manifest.installed.map((i) => i.id).sort()).toEqual([
|
|
89
|
+
"blog",
|
|
90
|
+
"docs",
|
|
91
|
+
]);
|
|
92
|
+
// InstalledItem stores the rendered file list
|
|
93
|
+
const docsRecord = manifest.installed.find((i) => i.id === "docs");
|
|
94
|
+
expect(docsRecord?.files).toEqual([
|
|
95
|
+
"app/docs/page.tsx",
|
|
96
|
+
"app/docs/[slug]/page.tsx",
|
|
97
|
+
"app/api/docs/route.ts",
|
|
98
|
+
"app/api/docs/[slug]/route.ts",
|
|
99
|
+
]);
|
|
100
|
+
});
|
|
101
|
+
it("rejects re-installing an item that is already present", async () => {
|
|
102
|
+
await writePackageJson(dir, "demo");
|
|
103
|
+
await writeV2Manifest(dir);
|
|
104
|
+
await expect(installItem({ projectDir: dir, templatesDir, itemId: "blog" })).rejects.toThrow(/already installed/);
|
|
105
|
+
});
|
|
106
|
+
it("returns a followup list mentioning the NOTION_DOCS_DATA_SOURCE_ID env var", async () => {
|
|
107
|
+
await writePackageJson(dir, "demo");
|
|
108
|
+
await writeV2Manifest(dir);
|
|
109
|
+
const summary = await installItem({
|
|
110
|
+
projectDir: dir,
|
|
111
|
+
templatesDir,
|
|
112
|
+
itemId: "docs",
|
|
113
|
+
});
|
|
114
|
+
const joined = summary.followup.join("\n");
|
|
115
|
+
expect(joined).toContain("NOTION_DOCS_DATA_SOURCE_ID");
|
|
116
|
+
});
|
|
117
|
+
it("rejects unknown item ids with the unknown-item code", async () => {
|
|
118
|
+
await writePackageJson(dir, "demo");
|
|
119
|
+
await writeV2Manifest(dir);
|
|
120
|
+
try {
|
|
121
|
+
await installItem({
|
|
122
|
+
projectDir: dir,
|
|
123
|
+
templatesDir,
|
|
124
|
+
itemId: "nonexistent",
|
|
125
|
+
});
|
|
126
|
+
throw new Error("expected installItem to throw");
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
expect(err).toBeInstanceOf(InstallError);
|
|
130
|
+
expect(err.code).toBe("unknown-item");
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
it("dry-run does not write any file or update the manifest", async () => {
|
|
134
|
+
await writePackageJson(dir, "demo");
|
|
135
|
+
await writeV2Manifest(dir);
|
|
136
|
+
const summary = await installItem({
|
|
137
|
+
projectDir: dir,
|
|
138
|
+
templatesDir,
|
|
139
|
+
itemId: "docs",
|
|
140
|
+
dryRun: true,
|
|
141
|
+
});
|
|
142
|
+
expect(summary.wroteManifest).toBe(false);
|
|
143
|
+
expect(summary.files.map((f) => f.projectRelativePath)).toEqual([
|
|
144
|
+
"app/docs/page.tsx",
|
|
145
|
+
"app/docs/[slug]/page.tsx",
|
|
146
|
+
"app/api/docs/route.ts",
|
|
147
|
+
"app/api/docs/[slug]/route.ts",
|
|
148
|
+
]);
|
|
149
|
+
expect(existsSync(path.join(dir, "app/docs/page.tsx"))).toBe(false);
|
|
150
|
+
// Manifest unchanged
|
|
151
|
+
const manifestRaw = await fs.readFile(path.join(dir, ".notionx/registry.json"), "utf8");
|
|
152
|
+
const manifest = JSON.parse(manifestRaw);
|
|
153
|
+
expect(manifest.installed).toHaveLength(1);
|
|
154
|
+
expect(manifest.installed[0]?.id).toBe("blog");
|
|
155
|
+
});
|
|
156
|
+
it("preserves existing content sources when re-rendering models.ts", async () => {
|
|
157
|
+
await writePackageJson(dir, "demo");
|
|
158
|
+
await writeV2Manifest(dir);
|
|
159
|
+
await installItem({ projectDir: dir, templatesDir, itemId: "docs" });
|
|
160
|
+
const modelsPath = path.join(dir, "lib/content/models.ts");
|
|
161
|
+
const models = await fs.readFile(modelsPath, "utf8");
|
|
162
|
+
expect(models).toContain("blogSource");
|
|
163
|
+
expect(models).toContain("docsSource");
|
|
164
|
+
expect(models).toContain("siteSettingsSource");
|
|
165
|
+
expect(models).toContain("blocksSource");
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=install.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.test.js","sourceRoot":"","sources":["../../src/registry/install.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/load-registry.ts
|
|
2
|
+
//
|
|
3
|
+
// The single entry point for reading a project's registry state.
|
|
4
|
+
//
|
|
5
|
+
// Behaviour:
|
|
6
|
+
// - If `.notionx/registry.json` exists, read it directly.
|
|
7
|
+
// - Else, throw — the directory is not a notionx project.
|
|
8
|
+
import { readRegistryManifest, REGISTRY_FILE } from "./registry-store.js";
|
|
9
|
+
/**
|
|
10
|
+
* Load a project's registry. Returns the `RegistryManifest` plus a
|
|
11
|
+
* `managedFiles` snapshot (typed view of the manifest's `managedFiles`
|
|
12
|
+
* block).
|
|
13
|
+
*
|
|
14
|
+
* Throws when no `registry.json` exists in the directory.
|
|
15
|
+
*/
|
|
16
|
+
export async function loadRegistry(projectDir) {
|
|
17
|
+
const manifest = await readRegistryManifest(projectDir);
|
|
18
|
+
if (manifest === null) {
|
|
19
|
+
throw new Error(`No Notionx project state found in ${projectDir}. ` +
|
|
20
|
+
`Expected ${REGISTRY_FILE}.`);
|
|
21
|
+
}
|
|
22
|
+
return { manifest, managedFiles: manifest.managedFiles };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=load-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-registry.js","sourceRoot":"","sources":["../../src/registry/load-registry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,EAAE;AACF,iEAAiE;AACjE,EAAE;AACF,aAAa;AACb,4DAA4D;AAC5D,4DAA4D;AAE5D,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG1E;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAkB;IACnD,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACxD,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,qCAAqC,UAAU,IAAI;YACjD,YAAY,aAAa,GAAG,CAC/B,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/load-registry.test.ts
|
|
2
|
+
import { mkdir, mkdtemp, 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 { loadRegistry } from "./load-registry.js";
|
|
7
|
+
import { REGISTRY_FILE } from "./registry-store.js";
|
|
8
|
+
import { REGISTRY_SCHEMA_V2 } from "./registry-types.js";
|
|
9
|
+
describe("loadRegistry", () => {
|
|
10
|
+
let dir;
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
dir = await mkdtemp(path.join(os.tmpdir(), "notionx-load-"));
|
|
13
|
+
await mkdir(path.join(dir, ".notionx"), { recursive: true });
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await rm(dir, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
it("throws when no registry.json exists", async () => {
|
|
19
|
+
await expect(loadRegistry(dir)).rejects.toThrow(/registry\.json/);
|
|
20
|
+
});
|
|
21
|
+
it("reads a v2 manifest directly", async () => {
|
|
22
|
+
await writeFile(path.join(dir, REGISTRY_FILE), JSON.stringify({
|
|
23
|
+
$schema: REGISTRY_SCHEMA_V2,
|
|
24
|
+
projectKind: "notionx",
|
|
25
|
+
projectName: "demo",
|
|
26
|
+
scaffoldVersion: "1.0.0",
|
|
27
|
+
notionxCore: "^2.0.0",
|
|
28
|
+
defaultLocale: "en",
|
|
29
|
+
supportedLocales: ["en"],
|
|
30
|
+
enableSiteSettings: true,
|
|
31
|
+
enableBlocks: true,
|
|
32
|
+
enableAuth: true,
|
|
33
|
+
enableAdmin: true,
|
|
34
|
+
enablePages: true,
|
|
35
|
+
enableSearch: true,
|
|
36
|
+
contentSource: {
|
|
37
|
+
id: "blog",
|
|
38
|
+
title: "Blog",
|
|
39
|
+
fields: [{ key: "title", notionName: "Title" }],
|
|
40
|
+
},
|
|
41
|
+
compat: { mode: "v2-native" },
|
|
42
|
+
registries: {},
|
|
43
|
+
installed: [],
|
|
44
|
+
managedFiles: { platform: [], bridge: [], user: [] },
|
|
45
|
+
}), "utf8");
|
|
46
|
+
const result = await loadRegistry(dir);
|
|
47
|
+
expect(result.manifest.$schema).toBe(REGISTRY_SCHEMA_V2);
|
|
48
|
+
expect(result.manifest.projectName).toBe("demo");
|
|
49
|
+
expect(result.managedFiles.platform).toEqual([]);
|
|
50
|
+
});
|
|
51
|
+
it("throws on schema mismatch", async () => {
|
|
52
|
+
await writeFile(path.join(dir, REGISTRY_FILE), JSON.stringify({
|
|
53
|
+
$schema: "https://example.com/wrong.json",
|
|
54
|
+
projectKind: "notionx",
|
|
55
|
+
}), "utf8");
|
|
56
|
+
await expect(loadRegistry(dir)).rejects.toThrow(/unknown schema/);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=load-registry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-registry.test.js","sourceRoot":"","sources":["../../src/registry/load-registry.test.ts"],"names":[],"mappings":"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"}
|