@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,232 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/registry-store.ts
|
|
2
|
+
//
|
|
3
|
+
// Read / write `.notionx/registry.json` atomically.
|
|
4
|
+
//
|
|
5
|
+
// Why atomic: a partial write would leave the project un-loadable on
|
|
6
|
+
// the next `notionx` command. We write to `<file>.tmp` first, then
|
|
7
|
+
// `rename` into place — `rename` is atomic on POSIX filesystems.
|
|
8
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { REGISTRY_SCHEMA_V2, } from "./registry-types.js";
|
|
11
|
+
/**
|
|
12
|
+
* Canonical location of the v2 manifest, relative to a project root.
|
|
13
|
+
* Kept as a constant so the CLI and the doctor agree on the path.
|
|
14
|
+
*/
|
|
15
|
+
export const REGISTRY_FILE = ".notionx/registry.json";
|
|
16
|
+
/**
|
|
17
|
+
* Read `registry.json` from `<projectDir>/.notionx/registry.json`.
|
|
18
|
+
*
|
|
19
|
+
* Returns `null` when the file does not exist. Throws on parse errors
|
|
20
|
+
* or schema mismatches — we never want to silently load garbage.
|
|
21
|
+
*/
|
|
22
|
+
export async function readRegistryManifest(projectDir) {
|
|
23
|
+
const filePath = path.join(projectDir, REGISTRY_FILE);
|
|
24
|
+
let raw;
|
|
25
|
+
try {
|
|
26
|
+
raw = await readFile(filePath, "utf8");
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (isENOENT(err))
|
|
30
|
+
return null;
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
if (parsed.$schema !== REGISTRY_SCHEMA_V2) {
|
|
35
|
+
throw new Error(`Registry manifest at ${filePath} uses unknown schema "${parsed.$schema ?? "<missing>"}" (expected ${REGISTRY_SCHEMA_V2}).`);
|
|
36
|
+
}
|
|
37
|
+
return parsed;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Write the v2 manifest atomically.
|
|
41
|
+
*
|
|
42
|
+
* Strategy: write to `<file>.tmp` with `fsync` to make sure bytes hit
|
|
43
|
+
* disk, then `rename` over the target. If anything fails before the
|
|
44
|
+
* rename, the original `registry.json` (if any) is untouched.
|
|
45
|
+
*/
|
|
46
|
+
export async function writeRegistryManifest(projectDir, manifest) {
|
|
47
|
+
const target = path.join(projectDir, REGISTRY_FILE);
|
|
48
|
+
const tmp = `${target}.tmp`;
|
|
49
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
50
|
+
await writeFile(tmp, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
51
|
+
await rename(tmp, target);
|
|
52
|
+
}
|
|
53
|
+
function isENOENT(err) {
|
|
54
|
+
return (typeof err === "object" &&
|
|
55
|
+
err !== null &&
|
|
56
|
+
"code" in err &&
|
|
57
|
+
err.code === "ENOENT");
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build the initial `RegistryManifest` for a freshly scaffolded
|
|
61
|
+
* project. Called by `render.ts` at the end of `create-notionx-app`.
|
|
62
|
+
*
|
|
63
|
+
* The manifest records:
|
|
64
|
+
* - the scaffold version + core dependency range
|
|
65
|
+
* - the primary content source the user picked
|
|
66
|
+
* - the default managed-files ownership map
|
|
67
|
+
* - a single `InstalledItem` for the primary content source
|
|
68
|
+
*
|
|
69
|
+
* `notionx add` will append to `installed`; `notionx update` will
|
|
70
|
+
* bump `scaffoldVersion` and rewrite `managedFiles` as needed.
|
|
71
|
+
*/
|
|
72
|
+
export function buildInitialRegistryManifest(input) {
|
|
73
|
+
const officialSource = {
|
|
74
|
+
kind: "official",
|
|
75
|
+
name: "@notionx/official",
|
|
76
|
+
};
|
|
77
|
+
const primaryItem = {
|
|
78
|
+
id: input.contentSource.id,
|
|
79
|
+
kind: "content-source",
|
|
80
|
+
version: 1,
|
|
81
|
+
source: officialSource,
|
|
82
|
+
params: {
|
|
83
|
+
contentSourceId: input.contentSource.id,
|
|
84
|
+
...(input.contentSource.id === "blog"
|
|
85
|
+
? {}
|
|
86
|
+
: { basePath: `/${input.contentSource.id}` }),
|
|
87
|
+
},
|
|
88
|
+
installedAt: new Date().toISOString(),
|
|
89
|
+
};
|
|
90
|
+
// When the scaffold enables site-settings / blocks, register
|
|
91
|
+
// them as InstalledItem entries so `notionx remove` can find
|
|
92
|
+
// them. The file paths mirror the catalog declarations in
|
|
93
|
+
// `registry-items.ts` — kept in sync manually (the catalog is
|
|
94
|
+
// the source of truth; this is a snapshot for the manifest).
|
|
95
|
+
const installed = [primaryItem];
|
|
96
|
+
if (input.enableSiteSettings) {
|
|
97
|
+
installed.push({
|
|
98
|
+
id: "site-settings",
|
|
99
|
+
kind: "feature-module",
|
|
100
|
+
version: 1,
|
|
101
|
+
source: officialSource,
|
|
102
|
+
params: {},
|
|
103
|
+
installedAt: new Date().toISOString(),
|
|
104
|
+
files: ["lib/site/settings.ts"],
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (input.enableBlocks) {
|
|
108
|
+
installed.push({
|
|
109
|
+
id: "blocks",
|
|
110
|
+
kind: "feature-module",
|
|
111
|
+
version: 1,
|
|
112
|
+
source: officialSource,
|
|
113
|
+
params: {},
|
|
114
|
+
installedAt: new Date().toISOString(),
|
|
115
|
+
files: [
|
|
116
|
+
"components/page-blocks.tsx",
|
|
117
|
+
"components/page-blocks/hero-block.tsx",
|
|
118
|
+
"components/page-blocks/feature-grid-block.tsx",
|
|
119
|
+
"components/page-blocks/story-block.tsx",
|
|
120
|
+
"components/page-blocks/latest-posts-block.tsx",
|
|
121
|
+
],
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (input.enableAuth) {
|
|
125
|
+
installed.push({
|
|
126
|
+
id: "auth",
|
|
127
|
+
kind: "feature-module",
|
|
128
|
+
version: 1,
|
|
129
|
+
source: officialSource,
|
|
130
|
+
params: {},
|
|
131
|
+
installedAt: new Date().toISOString(),
|
|
132
|
+
files: [
|
|
133
|
+
"lib/auth.config.ts",
|
|
134
|
+
"app/api/auth/google/route.ts",
|
|
135
|
+
"app/api/auth/google/callback/route.ts",
|
|
136
|
+
"app/api/auth/verify-email/route.ts",
|
|
137
|
+
"app/api/auth/viewer/route.ts",
|
|
138
|
+
"app/login/page.tsx",
|
|
139
|
+
"app/register/page.tsx",
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (input.enableAdmin) {
|
|
144
|
+
installed.push({
|
|
145
|
+
id: "admin",
|
|
146
|
+
kind: "feature-module",
|
|
147
|
+
version: 1,
|
|
148
|
+
source: officialSource,
|
|
149
|
+
params: {},
|
|
150
|
+
installedAt: new Date().toISOString(),
|
|
151
|
+
files: [
|
|
152
|
+
"app/admin/layout.tsx",
|
|
153
|
+
"app/admin/page.tsx",
|
|
154
|
+
"app/admin/loading.tsx",
|
|
155
|
+
"app/admin/account/page.tsx",
|
|
156
|
+
"app/admin/content-models/page.tsx",
|
|
157
|
+
"lib/admin/nav.ts",
|
|
158
|
+
"lib/admin/actions.ts",
|
|
159
|
+
"lib/admin/context.tsx",
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
if (input.enablePages) {
|
|
164
|
+
installed.push({
|
|
165
|
+
id: "pages",
|
|
166
|
+
kind: "feature-module",
|
|
167
|
+
version: 1,
|
|
168
|
+
source: officialSource,
|
|
169
|
+
params: {},
|
|
170
|
+
installedAt: new Date().toISOString(),
|
|
171
|
+
files: [
|
|
172
|
+
"lib/pages/model.ts",
|
|
173
|
+
"lib/pages/source.ts",
|
|
174
|
+
"app/[slug]/page.tsx",
|
|
175
|
+
"app/page.tsx",
|
|
176
|
+
],
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
if (input.enableSearch) {
|
|
180
|
+
installed.push({
|
|
181
|
+
id: "search",
|
|
182
|
+
kind: "feature-module",
|
|
183
|
+
version: 1,
|
|
184
|
+
source: officialSource,
|
|
185
|
+
params: {},
|
|
186
|
+
installedAt: new Date().toISOString(),
|
|
187
|
+
files: [
|
|
188
|
+
"lib/search/config.ts",
|
|
189
|
+
"components/search/search-dialog.tsx",
|
|
190
|
+
"migrations/0003_search_index.sql",
|
|
191
|
+
],
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
installed.sort((a, b) => a.id.localeCompare(b.id));
|
|
195
|
+
return {
|
|
196
|
+
$schema: REGISTRY_SCHEMA_V2,
|
|
197
|
+
projectKind: "notionx",
|
|
198
|
+
projectName: input.projectName,
|
|
199
|
+
scaffoldVersion: input.scaffoldVersion,
|
|
200
|
+
notionxCore: input.notionxCore,
|
|
201
|
+
defaultLocale: input.defaultLocale,
|
|
202
|
+
supportedLocales: [...input.supportedLocales],
|
|
203
|
+
enableSiteSettings: input.enableSiteSettings,
|
|
204
|
+
enableBlocks: input.enableBlocks,
|
|
205
|
+
enableAuth: input.enableAuth,
|
|
206
|
+
enableAdmin: input.enableAdmin,
|
|
207
|
+
enablePages: input.enablePages,
|
|
208
|
+
enableSearch: input.enableSearch,
|
|
209
|
+
contentSource: {
|
|
210
|
+
id: input.contentSource.id,
|
|
211
|
+
title: input.contentSource.title,
|
|
212
|
+
fields: input.contentSource.fields.map((f) => ({
|
|
213
|
+
key: f.key,
|
|
214
|
+
notionName: f.notionName,
|
|
215
|
+
})),
|
|
216
|
+
},
|
|
217
|
+
compat: { mode: "v2-native" },
|
|
218
|
+
registries: {
|
|
219
|
+
"@notionx/official": {
|
|
220
|
+
url: input.officialRegistryUrl ??
|
|
221
|
+
"https://registry.notionx.dev/official.json",
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
installed,
|
|
225
|
+
managedFiles: {
|
|
226
|
+
platform: [...input.managedFiles.platform],
|
|
227
|
+
bridge: [...input.managedFiles.bridge],
|
|
228
|
+
user: [...input.managedFiles.user],
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=registry-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-store.js","sourceRoot":"","sources":["../../src/registry/registry-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/registry-store.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 { REGISTRY_SCHEMA_V2 } from "./registry-types.js";
|
|
7
|
+
import { readRegistryManifest, REGISTRY_FILE, writeRegistryManifest, } from "./registry-store.js";
|
|
8
|
+
describe("registry-store", () => {
|
|
9
|
+
let dir;
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
dir = await mkdtemp(path.join(os.tmpdir(), "notionx-registry-store-"));
|
|
12
|
+
});
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await rm(dir, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
it("exposes the canonical .notionx/registry.json path", () => {
|
|
17
|
+
expect(REGISTRY_FILE).toBe(".notionx/registry.json");
|
|
18
|
+
});
|
|
19
|
+
it("returns null when registry.json does not exist", async () => {
|
|
20
|
+
const result = await readRegistryManifest(dir);
|
|
21
|
+
expect(result).toBeNull();
|
|
22
|
+
});
|
|
23
|
+
it("rejects a manifest that does not match the v2 schema URL", async () => {
|
|
24
|
+
// Intentionally construct a manifest with the wrong schema URL
|
|
25
|
+
// to verify the loader rejects it. We use `as unknown as` to
|
|
26
|
+
// bypass the literal-type narrowing — this fixture is *meant*
|
|
27
|
+
// to violate the type.
|
|
28
|
+
const manifest = {
|
|
29
|
+
$schema: "https://example.com/wrong-schema.json",
|
|
30
|
+
projectKind: "notionx",
|
|
31
|
+
projectName: "demo",
|
|
32
|
+
scaffoldVersion: "1.0.0",
|
|
33
|
+
notionxCore: "^2.0.0",
|
|
34
|
+
defaultLocale: "en",
|
|
35
|
+
supportedLocales: ["en"],
|
|
36
|
+
enableSiteSettings: true,
|
|
37
|
+
enableBlocks: true,
|
|
38
|
+
enableAuth: true,
|
|
39
|
+
enableAdmin: true,
|
|
40
|
+
enablePages: true,
|
|
41
|
+
enableSearch: true,
|
|
42
|
+
contentSource: {
|
|
43
|
+
id: "blog",
|
|
44
|
+
title: "Blog",
|
|
45
|
+
fields: [{ key: "title", notionName: "Title" }],
|
|
46
|
+
},
|
|
47
|
+
compat: { mode: "v2-native" },
|
|
48
|
+
registries: {},
|
|
49
|
+
installed: [],
|
|
50
|
+
managedFiles: { platform: [], bridge: [], user: [] },
|
|
51
|
+
};
|
|
52
|
+
await mkdir(path.join(dir, ".notionx"), { recursive: true });
|
|
53
|
+
await writeFile(path.join(dir, REGISTRY_FILE), JSON.stringify(manifest), "utf8");
|
|
54
|
+
await expect(readRegistryManifest(dir)).rejects.toThrow(/v2/);
|
|
55
|
+
});
|
|
56
|
+
it("round-trips a valid manifest through write + read", async () => {
|
|
57
|
+
const manifest = {
|
|
58
|
+
$schema: REGISTRY_SCHEMA_V2,
|
|
59
|
+
projectKind: "notionx",
|
|
60
|
+
projectName: "demo",
|
|
61
|
+
scaffoldVersion: "1.0.0",
|
|
62
|
+
notionxCore: "^2.0.0",
|
|
63
|
+
defaultLocale: "en",
|
|
64
|
+
supportedLocales: ["en"],
|
|
65
|
+
enableSiteSettings: true,
|
|
66
|
+
enableBlocks: true,
|
|
67
|
+
enableAuth: true,
|
|
68
|
+
enableAdmin: true,
|
|
69
|
+
enablePages: true,
|
|
70
|
+
enableSearch: true,
|
|
71
|
+
contentSource: {
|
|
72
|
+
id: "blog",
|
|
73
|
+
title: "Blog",
|
|
74
|
+
fields: [{ key: "title", notionName: "Title" }],
|
|
75
|
+
},
|
|
76
|
+
compat: { mode: "v2-native" },
|
|
77
|
+
registries: {
|
|
78
|
+
"@notionx/official": {
|
|
79
|
+
url: "https://registry.notionx.dev/official.json",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
installed: [
|
|
83
|
+
{
|
|
84
|
+
id: "blog",
|
|
85
|
+
kind: "content-source",
|
|
86
|
+
version: 1,
|
|
87
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
88
|
+
params: { contentSourceId: "blog" },
|
|
89
|
+
installedAt: "2026-06-10T08:00:00.000Z",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
managedFiles: {
|
|
93
|
+
platform: ["package.json", "wrangler.jsonc"],
|
|
94
|
+
bridge: ["worker/index.ts"],
|
|
95
|
+
user: ["app/page.tsx", "lib/content/models.ts"],
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
await writeRegistryManifest(dir, manifest);
|
|
99
|
+
const read = await readRegistryManifest(dir);
|
|
100
|
+
expect(read).toEqual(manifest);
|
|
101
|
+
});
|
|
102
|
+
it("uses an atomic write (write to .tmp, then rename)", async () => {
|
|
103
|
+
const manifest = {
|
|
104
|
+
$schema: REGISTRY_SCHEMA_V2,
|
|
105
|
+
projectKind: "notionx",
|
|
106
|
+
projectName: "demo",
|
|
107
|
+
scaffoldVersion: "1.0.0",
|
|
108
|
+
notionxCore: "^2.0.0",
|
|
109
|
+
defaultLocale: "en",
|
|
110
|
+
supportedLocales: ["en"],
|
|
111
|
+
enableSiteSettings: true,
|
|
112
|
+
enableBlocks: true,
|
|
113
|
+
enableAuth: true,
|
|
114
|
+
enableAdmin: true,
|
|
115
|
+
enablePages: true,
|
|
116
|
+
enableSearch: true,
|
|
117
|
+
contentSource: {
|
|
118
|
+
id: "blog",
|
|
119
|
+
title: "Blog",
|
|
120
|
+
fields: [{ key: "title", notionName: "Title" }],
|
|
121
|
+
},
|
|
122
|
+
compat: { mode: "v2-native" },
|
|
123
|
+
registries: {},
|
|
124
|
+
installed: [],
|
|
125
|
+
managedFiles: { platform: [], bridge: [], user: [] },
|
|
126
|
+
};
|
|
127
|
+
await writeRegistryManifest(dir, manifest);
|
|
128
|
+
// No leftover .tmp file
|
|
129
|
+
const entries = await readFile(path.join(dir, REGISTRY_FILE), "utf8");
|
|
130
|
+
expect(entries).toContain(REGISTRY_SCHEMA_V2);
|
|
131
|
+
// Final file is valid JSON
|
|
132
|
+
const parsed = JSON.parse(entries);
|
|
133
|
+
expect(parsed.$schema).toBe(REGISTRY_SCHEMA_V2);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
//# sourceMappingURL=registry-store.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-store.test.js","sourceRoot":"","sources":["../../src/registry/registry-store.test.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAElE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EAAE,kBAAkB,EAAyB,MAAM,qBAAqB,CAAC;AAChF,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAE7B,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,GAAW,CAAC;IAChB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,yBAAyB,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,+DAA+D;QAC/D,6DAA6D;QAC7D,8DAA8D;QAC9D,uBAAuB;QACvB,MAAM,QAAQ,GAAG;YACf,OAAO,EAAE,uCAAuC;YAChD,WAAW,EAAE,SAAkB;YAC/B,WAAW,EAAE,MAAM;YACnB,eAAe,EAAE,OAAO;YACxB,WAAW,EAAE,QAAQ;YACrB,aAAa,EAAE,IAAI;YACnB,gBAAgB,EAAE,CAAC,IAAI,CAAC;YACxB,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE;gBACb,EAAE,EAAE,MAAM;gBACV,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;aAChD;YACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAoB,EAAE;YACtC,UAAU,EAAE,EAAE;YACd,SAAS,EAAE,EAAE;YACb,YAAY,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;SACtB,CAAC;QACjC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAC7B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EACxB,MAAM,CACP,CAAC;QAEF,MAAM,MAAM,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,QAAQ,GAAqB;YACjC,OAAO,EAAE,kBAAkB;YAC3B,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,MAAM;YACnB,eAAe,EAAE,OAAO;YACxB,WAAW,EAAE,QAAQ;YACrB,aAAa,EAAE,IAAI;YACnB,gBAAgB,EAAE,CAAC,IAAI,CAAC;YACxB,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE;gBACb,EAAE,EAAE,MAAM;gBACV,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;aAChD;YACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;YAC7B,UAAU,EAAE;gBACV,mBAAmB,EAAE;oBACnB,GAAG,EAAE,4CAA4C;iBAClD;aACF;YACD,SAAS,EAAE;gBACT;oBACE,EAAE,EAAE,MAAM;oBACV,IAAI,EAAE,gBAAgB;oBACtB,OAAO,EAAE,CAAC;oBACV,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,mBAAmB,EAAE;oBACvD,MAAM,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE;oBACnC,WAAW,EAAE,0BAA0B;iBACxC;aACF;YACD,YAAY,EAAE;gBACZ,QAAQ,EAAE,CAAC,cAAc,EAAE,gBAAgB,CAAC;gBAC5C,MAAM,EAAE,CAAC,iBAAiB,CAAC;gBAC3B,IAAI,EAAE,CAAC,cAAc,EAAE,uBAAuB,CAAC;aAChD;SACF,CAAC;QAEF,MAAM,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,QAAQ,GAAqB;YACjC,OAAO,EAAE,kBAAkB;YAC3B,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,MAAM;YACnB,eAAe,EAAE,OAAO;YACxB,WAAW,EAAE,QAAQ;YACrB,aAAa,EAAE,IAAI;YACnB,gBAAgB,EAAE,CAAC,IAAI,CAAC;YACxB,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE;gBACb,EAAE,EAAE,MAAM;gBACV,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;aAChD;YACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;YAC7B,UAAU,EAAE,EAAE;YACd,SAAS,EAAE,EAAE;YACb,YAAY,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;SACrD,CAAC;QAEF,MAAM,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAE3C,wBAAwB;QACxB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAC5B,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAC7B,MAAM,CACP,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QAE9C,2BAA2B;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAqB,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/registry-types.ts
|
|
2
|
+
//
|
|
3
|
+
// v2 Registry Protocol types — the single source of truth for everything
|
|
4
|
+
// a project has installed, what version, from which registry, and how
|
|
5
|
+
// to migrate when those things change.
|
|
6
|
+
//
|
|
7
|
+
// Design notes:
|
|
8
|
+
// - This file has **no runtime dependencies** on Node APIs or other
|
|
9
|
+
// modules in the package, so it can be imported from anywhere
|
|
10
|
+
// (including the compiled `dist/`) without pulling in fs/path/etc.
|
|
11
|
+
// - All shapes are JSON-serializable. The `registry.json` file is
|
|
12
|
+
// written verbatim from a `RegistryManifest`.
|
|
13
|
+
/**
|
|
14
|
+
* Schema URL baked into `registry.json` so future readers can detect
|
|
15
|
+
* "this manifest uses an older or newer protocol version".
|
|
16
|
+
*/
|
|
17
|
+
export const REGISTRY_SCHEMA_V2 = "https://notionx.dev/schemas/registry.v2.json";
|
|
18
|
+
//# sourceMappingURL=registry-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-types.js","sourceRoot":"","sources":["../../src/registry/registry-types.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,yEAAyE;AACzE,sEAAsE;AACtE,uCAAuC;AACvC,EAAE;AACF,gBAAgB;AAChB,oEAAoE;AACpE,gEAAgE;AAChE,qEAAqE;AACrE,kEAAkE;AAClE,gDAAgD;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAC7B,8CAAuD,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/registry/registry-types.test.ts
|
|
2
|
+
//
|
|
3
|
+
// Pure type-shape tests. No fs / no Node APIs. These exist to lock in
|
|
4
|
+
// the JSON shape we read/write on disk so a refactor that accidentally
|
|
5
|
+
// renames a field is caught immediately.
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { REGISTRY_SCHEMA_V2, } from "./registry-types.js";
|
|
8
|
+
/** Minimal valid manifest fixture with overridable fields. */
|
|
9
|
+
function fixture(overrides = {}) {
|
|
10
|
+
return {
|
|
11
|
+
$schema: REGISTRY_SCHEMA_V2,
|
|
12
|
+
projectKind: "notionx",
|
|
13
|
+
projectName: "demo",
|
|
14
|
+
scaffoldVersion: "1.0.0",
|
|
15
|
+
notionxCore: "^2.0.0",
|
|
16
|
+
defaultLocale: "en",
|
|
17
|
+
supportedLocales: ["en"],
|
|
18
|
+
enableSiteSettings: true,
|
|
19
|
+
enableBlocks: true,
|
|
20
|
+
enableAuth: true,
|
|
21
|
+
enableAdmin: true,
|
|
22
|
+
enablePages: true,
|
|
23
|
+
enableSearch: true,
|
|
24
|
+
contentSource: {
|
|
25
|
+
id: "blog",
|
|
26
|
+
title: "Blog",
|
|
27
|
+
fields: [{ key: "title", notionName: "Title" }],
|
|
28
|
+
},
|
|
29
|
+
compat: { mode: "v2-native" },
|
|
30
|
+
registries: {},
|
|
31
|
+
installed: [],
|
|
32
|
+
managedFiles: { platform: [], bridge: [], user: [] },
|
|
33
|
+
...overrides,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
describe("RegistryManifest", () => {
|
|
37
|
+
it("uses the v2 schema URL", () => {
|
|
38
|
+
const manifest = fixture({
|
|
39
|
+
registries: {
|
|
40
|
+
"@notionx/official": { url: "https://registry.notionx.dev/official.json" },
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
expect(manifest.$schema).toBe("https://notionx.dev/schemas/registry.v2.json");
|
|
44
|
+
});
|
|
45
|
+
it("supports the legacy-vinext compatibility marker", () => {
|
|
46
|
+
const manifest = fixture({
|
|
47
|
+
notionxCore: "workspace:*",
|
|
48
|
+
compat: { mode: "legacy-vinext" },
|
|
49
|
+
});
|
|
50
|
+
expect(manifest.compat.mode).toBe("legacy-vinext");
|
|
51
|
+
expect(manifest.notionxCore).toBe("workspace:*");
|
|
52
|
+
});
|
|
53
|
+
it("preserves extras through the round-trip", () => {
|
|
54
|
+
const manifest = fixture({
|
|
55
|
+
extras: { customBindingName: "D1_AUTH_DB" },
|
|
56
|
+
});
|
|
57
|
+
expect(manifest.extras?.customBindingName).toBe("D1_AUTH_DB");
|
|
58
|
+
});
|
|
59
|
+
it("stores projectName and contentSource from the scaffold flow", () => {
|
|
60
|
+
const manifest = fixture({
|
|
61
|
+
projectName: "my-site",
|
|
62
|
+
contentSource: {
|
|
63
|
+
id: "docs",
|
|
64
|
+
title: "Docs",
|
|
65
|
+
fields: [
|
|
66
|
+
{ key: "title", notionName: "Title" },
|
|
67
|
+
{ key: "slug", notionName: "Slug" },
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
expect(manifest.projectName).toBe("my-site");
|
|
72
|
+
expect(manifest.contentSource.id).toBe("docs");
|
|
73
|
+
expect(manifest.contentSource.fields).toHaveLength(2);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe("InstalledItem", () => {
|
|
77
|
+
it("captures the four fields the loader snapshots", () => {
|
|
78
|
+
const installed = {
|
|
79
|
+
id: "blog",
|
|
80
|
+
kind: "content-source",
|
|
81
|
+
version: 1,
|
|
82
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
83
|
+
params: { contentSourceId: "blog" },
|
|
84
|
+
installedAt: "2026-06-10T08:00:00.000Z",
|
|
85
|
+
};
|
|
86
|
+
expect(installed.id).toBe("blog");
|
|
87
|
+
expect(installed.kind).toBe("content-source");
|
|
88
|
+
expect(installed.source.kind).toBe("official");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("RegistryItem", () => {
|
|
92
|
+
it("models requires / supersedes / migrations as optional", () => {
|
|
93
|
+
const item = {
|
|
94
|
+
id: "search",
|
|
95
|
+
kind: "feature-module",
|
|
96
|
+
version: 1,
|
|
97
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
98
|
+
publishedAt: "2026-06-10T00:00:00.000Z",
|
|
99
|
+
params: { scope: "docs" },
|
|
100
|
+
files: [],
|
|
101
|
+
capabilities: {},
|
|
102
|
+
migrations: [],
|
|
103
|
+
};
|
|
104
|
+
expect(item.requires).toBeUndefined();
|
|
105
|
+
expect(item.supersedes).toBeUndefined();
|
|
106
|
+
expect(item.migrations).toEqual([]);
|
|
107
|
+
});
|
|
108
|
+
it("supports content-source items with notion data sources", () => {
|
|
109
|
+
const blog = {
|
|
110
|
+
id: "blog",
|
|
111
|
+
kind: "content-source",
|
|
112
|
+
version: 1,
|
|
113
|
+
source: { kind: "official", name: "@notionx/official" },
|
|
114
|
+
publishedAt: "2026-06-01T00:00:00.000Z",
|
|
115
|
+
params: { contentSourceId: "blog" },
|
|
116
|
+
files: [
|
|
117
|
+
{ path: "app/blog/page.tsx", ownership: "user" },
|
|
118
|
+
{ path: "lib/content/models.ts", ownership: "bridge" },
|
|
119
|
+
],
|
|
120
|
+
capabilities: {
|
|
121
|
+
publicRoutes: ["/blog", "/blog/[slug]"],
|
|
122
|
+
apiRoutes: ["/api/posts"],
|
|
123
|
+
envVars: ["NOTION_BLOG_DATA_SOURCE_ID"],
|
|
124
|
+
notionDataSources: ["NOTION_BLOG_DATA_SOURCE_ID"],
|
|
125
|
+
contentSourceIds: ["blog"],
|
|
126
|
+
},
|
|
127
|
+
migrations: [
|
|
128
|
+
{
|
|
129
|
+
from: "blog@1",
|
|
130
|
+
to: "blog@2",
|
|
131
|
+
steps: [
|
|
132
|
+
{
|
|
133
|
+
kind: "notion-field-add",
|
|
134
|
+
source: "NOTION_BLOG_DATA_SOURCE_ID",
|
|
135
|
+
property: "Author",
|
|
136
|
+
type: "people",
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
expect(blog.capabilities.contentSourceIds).toEqual(["blog"]);
|
|
143
|
+
expect(blog.migrations[0]?.steps[0]?.kind).toBe("notion-field-add");
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=registry-types.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-types.test.js","sourceRoot":"","sources":["../../src/registry/registry-types.test.ts"],"names":[],"mappings":"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"}
|