@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
package/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# @notionx/create-notionx-app
|
|
2
|
+
|
|
3
|
+
Scaffold a new [vinext](https://github.com/digwis/nextion) project that consumes
|
|
4
|
+
[`@notionx/core`](https://www.npmjs.com/package/@notionx/core). The generated
|
|
5
|
+
project runs on **Cloudflare Workers + D1 + R2**, ships a single
|
|
6
|
+
**Notion-backed** content source, and comes pre-wired with auth, admin, and
|
|
7
|
+
health routes — all from one command.
|
|
8
|
+
|
|
9
|
+
> **TL;DR**
|
|
10
|
+
> ```bash
|
|
11
|
+
> npx @notionx/create-notionx-app my-app
|
|
12
|
+
> cd my-app
|
|
13
|
+
> pnpm install
|
|
14
|
+
> pnpm dev
|
|
15
|
+
> ```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
### One command, one question
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @notionx/create-notionx-app my-app
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The CLI asks exactly two things — your **project name** and a final
|
|
28
|
+
**confirmation**. Everything else (locale, content-source shape, etc.) uses
|
|
29
|
+
sensible defaults that you can edit in the generated project.
|
|
30
|
+
|
|
31
|
+
### Skip prompts entirely
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx @notionx/create-notionx-app my-app --yes
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Custom install location
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx @notionx/create-notionx-app ./projects/my-app
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Pin a specific `@notionx/core` version
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# In a published project (no monorepo workspace):
|
|
47
|
+
npx @notionx/create-notionx-app my-app --notionx-source "^0.1.0"
|
|
48
|
+
|
|
49
|
+
# In a monorepo that also hosts the @notionx/core source:
|
|
50
|
+
npx @notionx/create-notionx-app my-app \
|
|
51
|
+
--notionx-source "link:../vinext-monorepo/packages/notionx"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## What gets generated
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
my-app/
|
|
58
|
+
├── app/ # App-Router pages
|
|
59
|
+
│ ├── page.tsx # landing page
|
|
60
|
+
│ ├── login/page.tsx # email/password login
|
|
61
|
+
│ └── api/ # health + auth endpoints
|
|
62
|
+
├── worker/index.ts # createNotionxWorker + vinext fallthrough
|
|
63
|
+
├── lib/ # site/auth/admin/content config
|
|
64
|
+
├── components/ui/ # shadcn/ui primitives
|
|
65
|
+
├── migrations/0001_init.sql # auth schema
|
|
66
|
+
├── wrangler.jsonc # D1 + KV + R2 + Assets bindings
|
|
67
|
+
├── .dev.vars.example # secret keys placeholder
|
|
68
|
+
└── package.json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Interactive provisioning
|
|
72
|
+
|
|
73
|
+
When the CLI finishes writing files, it offers to provision your
|
|
74
|
+
**Cloudflare**, **Notion**, **Turnstile**, **Resend**, and **Google OAuth**
|
|
75
|
+
accounts in one shot. If you accept, it will:
|
|
76
|
+
|
|
77
|
+
1. Verify your `wrangler` login (and offer to install it / upgrade to v4 if not)
|
|
78
|
+
2. Create the **D1** database, **KV** namespace, and **R2** bucket
|
|
79
|
+
3. Patch `wrangler.jsonc` and `.dev.vars` with the resulting IDs
|
|
80
|
+
4. Apply D1 migrations to your local Miniflare store
|
|
81
|
+
5. Create a **Notion** data source with seeded sample pages
|
|
82
|
+
6. Optionally configure **Turnstile**, **Resend**, and **Google OAuth**
|
|
83
|
+
|
|
84
|
+
If you decline, the project is fully scaffolded but you'll need to wire
|
|
85
|
+
resources manually — see the README generated inside the project.
|
|
86
|
+
|
|
87
|
+
## Adding a locale
|
|
88
|
+
|
|
89
|
+
The generated project supports a multilingual foundation out of the box
|
|
90
|
+
(blog, pages, blocks, and site settings each get a `base + translations`
|
|
91
|
+
pattern in Notion). To enable an additional locale on an existing
|
|
92
|
+
project, see the `Multilingual foundation` section in the generated
|
|
93
|
+
project README for the full flow:
|
|
94
|
+
|
|
95
|
+
- `npx notionx locale add <locale>` — dry run
|
|
96
|
+
- `npx notionx locale add <locale> --apply` — writes scaffold metadata
|
|
97
|
+
and the locale config (no Notion calls)
|
|
98
|
+
- `npx notionx locale add <locale> --with-notion --apply [--copy-from <locale>]`
|
|
99
|
+
— provisions the four translation data sources in Notion and pushes
|
|
100
|
+
the resulting data source ids as worker secrets
|
|
101
|
+
|
|
102
|
+
The command refuses to remove or overwrite existing locales. Re-running
|
|
103
|
+
with the same locale is a no-op (the validator returns
|
|
104
|
+
"already in supportedLocales").
|
|
105
|
+
|
|
106
|
+
## Requirements
|
|
107
|
+
|
|
108
|
+
- **Node.js 22+** (`node --version`)
|
|
109
|
+
- **pnpm 9+** for the generated project (`npm install -g pnpm`)
|
|
110
|
+
- A **Cloudflare** account (free tier is fine) — only needed if you accept provisioning
|
|
111
|
+
- A **Notion** integration token — same
|
|
112
|
+
|
|
113
|
+
## Flags
|
|
114
|
+
|
|
115
|
+
| Flag | Description |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `[target-dir]` | Output directory (positional, default: `./<project-name>`) |
|
|
118
|
+
| `--project-name <name>` | Project name (kebab/lower case). Other settings use defaults. |
|
|
119
|
+
| `--target-dir <dir>` | Output directory (default: `./<project-name>`) |
|
|
120
|
+
| `--notionx-source <spec>` | `@notionx/core` dependency value (default: `workspace:*`) |
|
|
121
|
+
| `-y`, `--yes` | Skip the confirmation prompt |
|
|
122
|
+
| `-h`, `--help` | Print help |
|
|
123
|
+
|
|
124
|
+
## What is `@notionx/core`?
|
|
125
|
+
|
|
126
|
+
The runtime framework. New projects get it as a dependency; the generated
|
|
127
|
+
code uses:
|
|
128
|
+
|
|
129
|
+
- `createNotionxWorker(...)` — the Cloudflare Worker entry
|
|
130
|
+
- `defineContentSource(...)` — a Notion-backed content source
|
|
131
|
+
- `createAuth(authConfig)` — email/password + OAuth login
|
|
132
|
+
- `AdminExtension` — server-rendered admin shell
|
|
133
|
+
- `WorkerOptions` — wrangler bindings, secrets, image transforms
|
|
134
|
+
|
|
135
|
+
Repository: <https://github.com/digwis/nextion/tree/main/packages/notionx>
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT © [zhaofilms](https://github.com/digwis/nextion)
|
package/dist/answers.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
// packages/create-notionx-app/src/answers.ts
|
|
2
|
+
//
|
|
3
|
+
// Build an `Answers` object either from the interactive prompt or
|
|
4
|
+
// from CLI flags. The CLI flow exists so the scaffolder can run in
|
|
5
|
+
// CI / non-TTY smoke tests where `@clack/prompts` would just hang.
|
|
6
|
+
import * as p from "@clack/prompts";
|
|
7
|
+
import { generateRandomPassword } from "./password.js";
|
|
8
|
+
import { FALLBACK_NOTIONX_SOURCE, resolveNotionxSource } from "./notionx-source.js";
|
|
9
|
+
const DEFAULT_FIELDS = "Name, Slug, Description, Published, Date, Tags, Cover";
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a boolean feature flag from CLI overrides or a
|
|
12
|
+
* `CREATE_NOTIONX_NO_*` env var. Defaults to `true` (feature on).
|
|
13
|
+
*/
|
|
14
|
+
function resolveFlag(override, envVar) {
|
|
15
|
+
if (override !== undefined)
|
|
16
|
+
return override;
|
|
17
|
+
const v = process.env[envVar];
|
|
18
|
+
if (v) {
|
|
19
|
+
const lower = v.toLowerCase();
|
|
20
|
+
if (lower === "1" || lower === "true" || lower === "yes") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
function parseLocales(value) {
|
|
27
|
+
return value
|
|
28
|
+
.split(/[,\s]+/)
|
|
29
|
+
.map((s) => s.trim())
|
|
30
|
+
.filter((s) => s.length > 0);
|
|
31
|
+
}
|
|
32
|
+
function toCamelCase(name) {
|
|
33
|
+
const cleaned = name.replace(/[^a-zA-Z0-9 ]/g, " ").trim();
|
|
34
|
+
if (!cleaned)
|
|
35
|
+
return "field";
|
|
36
|
+
const parts = cleaned.split(/\s+/);
|
|
37
|
+
const [first, ...rest] = parts;
|
|
38
|
+
return (first.toLowerCase() +
|
|
39
|
+
rest.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(""));
|
|
40
|
+
}
|
|
41
|
+
function buildFields(raw) {
|
|
42
|
+
const names = parseLocales(raw);
|
|
43
|
+
const seen = new Set();
|
|
44
|
+
const out = [];
|
|
45
|
+
for (const name of names.length ? names : ["Name"]) {
|
|
46
|
+
const key = toCamelCase(name);
|
|
47
|
+
if (seen.has(key))
|
|
48
|
+
continue;
|
|
49
|
+
seen.add(key);
|
|
50
|
+
out.push({ key, notionName: name });
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
function parseArgs(argv) {
|
|
55
|
+
const out = {};
|
|
56
|
+
for (let i = 2; i < argv.length; i++) {
|
|
57
|
+
// Accept both `--flag value` and `--flag=value` (the latter is
|
|
58
|
+
// what pnpm/npx pass through when forwarding CLI args). The
|
|
59
|
+
// `i += consumed` pattern at the end of the loop is what keeps
|
|
60
|
+
// us in sync with whichever form the caller used — using `i++`
|
|
61
|
+
// inside each case was wrong because it would also advance past
|
|
62
|
+
// the next flag when the value was supplied inline.
|
|
63
|
+
let arg = argv[i];
|
|
64
|
+
let inlineValue;
|
|
65
|
+
const eq = arg.indexOf("=");
|
|
66
|
+
if (eq > 0) {
|
|
67
|
+
inlineValue = arg.slice(eq + 1);
|
|
68
|
+
arg = arg.slice(0, eq);
|
|
69
|
+
}
|
|
70
|
+
const next = argv[i + 1];
|
|
71
|
+
let consumed = 0;
|
|
72
|
+
const takeNext = (value) => {
|
|
73
|
+
if (inlineValue !== undefined) {
|
|
74
|
+
// Inline `--flag=value` form. No extra argv to consume.
|
|
75
|
+
return inlineValue;
|
|
76
|
+
}
|
|
77
|
+
if (value === undefined) {
|
|
78
|
+
throw new Error(`Flag ${arg} requires a value`);
|
|
79
|
+
}
|
|
80
|
+
// Space-separated `--flag value` form. We consumed `value`
|
|
81
|
+
// from the next argv position, so the loop's i++ must skip
|
|
82
|
+
// it. Mark that for the loop step at the bottom.
|
|
83
|
+
consumed = 1;
|
|
84
|
+
return value;
|
|
85
|
+
};
|
|
86
|
+
switch (arg) {
|
|
87
|
+
case "--project-name":
|
|
88
|
+
out.projectName = takeNext(next);
|
|
89
|
+
break;
|
|
90
|
+
case "--target-dir":
|
|
91
|
+
out.targetDir = takeNext(next);
|
|
92
|
+
break;
|
|
93
|
+
case "--default-locale":
|
|
94
|
+
out.defaultLocale = takeNext(next);
|
|
95
|
+
break;
|
|
96
|
+
case "--supported-locales":
|
|
97
|
+
out.supportedLocales = takeNext(next);
|
|
98
|
+
break;
|
|
99
|
+
case "--content-id":
|
|
100
|
+
out.contentId = takeNext(next);
|
|
101
|
+
break;
|
|
102
|
+
case "--content-title":
|
|
103
|
+
out.contentTitle = takeNext(next);
|
|
104
|
+
break;
|
|
105
|
+
case "--fields":
|
|
106
|
+
out.fields = takeNext(next);
|
|
107
|
+
break;
|
|
108
|
+
case "--notionx-source":
|
|
109
|
+
out.notionxSource = takeNext(next);
|
|
110
|
+
break;
|
|
111
|
+
case "--admin-email":
|
|
112
|
+
out.adminEmail = takeNext(next);
|
|
113
|
+
break;
|
|
114
|
+
case "--admin-password":
|
|
115
|
+
out.adminPassword = takeNext(next);
|
|
116
|
+
break;
|
|
117
|
+
case "--notion-parent-page":
|
|
118
|
+
out.notionParentPage = takeNext(next);
|
|
119
|
+
break;
|
|
120
|
+
case "--notion-seed-count":
|
|
121
|
+
out.notionSeedCount = Number(takeNext(next));
|
|
122
|
+
break;
|
|
123
|
+
case "-y":
|
|
124
|
+
case "--yes":
|
|
125
|
+
out.yes = true;
|
|
126
|
+
break;
|
|
127
|
+
case "-h":
|
|
128
|
+
case "--help":
|
|
129
|
+
printHelp();
|
|
130
|
+
process.exit(0);
|
|
131
|
+
break;
|
|
132
|
+
default:
|
|
133
|
+
if (arg.startsWith("-")) {
|
|
134
|
+
throw new Error(`Unknown flag: ${arg}`);
|
|
135
|
+
}
|
|
136
|
+
// First positional arg is the target dir.
|
|
137
|
+
if (!out.targetDir) {
|
|
138
|
+
out.targetDir = arg;
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
i += consumed;
|
|
143
|
+
}
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
function printHelp() {
|
|
147
|
+
console.log(`@notionx/create-notionx-app — scaffold a new vinext project
|
|
148
|
+
|
|
149
|
+
Usage:
|
|
150
|
+
@notionx/create-notionx-app [target-dir] [flags]
|
|
151
|
+
|
|
152
|
+
Flags:
|
|
153
|
+
--project-name <name> Project name (kebab/lower case).
|
|
154
|
+
Other settings use sensible defaults
|
|
155
|
+
(locale=en, content source=blog, etc.).
|
|
156
|
+
--target-dir <dir> Output directory (default: ./<project-name>)
|
|
157
|
+
--default-locale <locale> Fallback/current language (default: en).
|
|
158
|
+
--supported-locales <list> Comma/space separated renderable locales.
|
|
159
|
+
The default locale is always included.
|
|
160
|
+
--notionx-source <spec> Override the @notionx/core dep value
|
|
161
|
+
(default: "^0.1.2" — the published
|
|
162
|
+
npm version). For in-monorepo dev,
|
|
163
|
+
pass "workspace:*" (requires the
|
|
164
|
+
target dir to live inside a pnpm
|
|
165
|
+
workspace that has @notionx/core
|
|
166
|
+
listed), or "file:../path/to/core".
|
|
167
|
+
--admin-email <addr> Email granted the admin role (required).
|
|
168
|
+
--admin-password <pwd> Optional initial password for the admin
|
|
169
|
+
account (≥8 chars, letters + digits).
|
|
170
|
+
If omitted, a random one is generated
|
|
171
|
+
and printed at the end.
|
|
172
|
+
--notion-parent-page <id> 32-char hex page id under which the
|
|
173
|
+
content database is created. Requires
|
|
174
|
+
a resolvable Notion token (run
|
|
175
|
+
"ntn login" first, or set
|
|
176
|
+
NOTION_API_TOKEN). Skip to leave
|
|
177
|
+
Notion provisioning for later.
|
|
178
|
+
--notion-seed-count <n> Number of sample blog pages to seed into the
|
|
179
|
+
new database (default 3, 0 to skip).
|
|
180
|
+
-y, --yes Skip the confirmation prompt
|
|
181
|
+
-h, --help Print this help
|
|
182
|
+
`);
|
|
183
|
+
}
|
|
184
|
+
function applyDefaults(overrides, argv) {
|
|
185
|
+
const projectName = overrides.projectName ?? "my-vinext-app";
|
|
186
|
+
// Only treat `argv[2]` as a positional `target-dir` argument when
|
|
187
|
+
// it doesn't look like a flag. Without this guard, calls like
|
|
188
|
+
// `cli --project-name=foo` would land `argv[2]` =
|
|
189
|
+
// `"--project-name=foo"` into the target dir, which is a confusing
|
|
190
|
+
// user-visible failure.
|
|
191
|
+
const positionalTargetDir = argv[2] && !argv[2].startsWith("-") ? argv[2] : undefined;
|
|
192
|
+
const targetDir = overrides.targetDir ?? positionalTargetDir ?? `./${projectName}`;
|
|
193
|
+
const defaultLocale = overrides.defaultLocale ?? "en";
|
|
194
|
+
const supportedLocales = parseLocales(overrides.supportedLocales ?? defaultLocale);
|
|
195
|
+
const contentId = overrides.contentId ?? "blog";
|
|
196
|
+
const contentTitle = overrides.contentTitle ?? contentId.charAt(0).toUpperCase() + contentId.slice(1);
|
|
197
|
+
const fields = buildFields(overrides.fields ?? DEFAULT_FIELDS);
|
|
198
|
+
// Admin email/password resolution for the non-interactive path:
|
|
199
|
+
// 1. CLI flag (--admin-email / --admin-password)
|
|
200
|
+
// 2. Env var (CREATE_NOTIONX_ADMIN_EMAIL / _PASSWORD)
|
|
201
|
+
// 3. Sensible placeholder + random password (printed at the end)
|
|
202
|
+
const adminEmail = overrides.adminEmail ??
|
|
203
|
+
process.env.CREATE_NOTIONX_ADMIN_EMAIL ??
|
|
204
|
+
"admin@example.com";
|
|
205
|
+
const generatedPassword = generateRandomPassword();
|
|
206
|
+
const adminPassword = overrides.adminPassword ??
|
|
207
|
+
process.env.CREATE_NOTIONX_ADMIN_PASSWORD ??
|
|
208
|
+
generatedPassword;
|
|
209
|
+
const generatedAdminPassword = adminPassword === generatedPassword ? generatedPassword : undefined;
|
|
210
|
+
// Notion parent page resolution: CLI flag, env var, or skip.
|
|
211
|
+
// The seed count defaults to 3 — the explicit "0" string the user
|
|
212
|
+
// can pass to skip seeding.
|
|
213
|
+
const notionParentPage = overrides.notionParentPage ??
|
|
214
|
+
process.env.CREATE_NOTIONX_NOTION_PARENT_PAGE ??
|
|
215
|
+
"";
|
|
216
|
+
const notionSeedCount = overrides.notionSeedCount ??
|
|
217
|
+
(process.env.CREATE_NOTIONX_NOTION_SEED_COUNT !== undefined
|
|
218
|
+
? Number(process.env.CREATE_NOTIONX_NOTION_SEED_COUNT)
|
|
219
|
+
: 3);
|
|
220
|
+
// `enableSiteSettings` defaults to true. `CREATE_NOTIONX_NO_SITE_SETTINGS`
|
|
221
|
+
// is the env-var mirror of `--no-site-settings`; truthy values
|
|
222
|
+
// (1/true/yes) opt out, anything else falls through to the default.
|
|
223
|
+
let enableSiteSettings = true;
|
|
224
|
+
if (overrides.enableSiteSettings !== undefined) {
|
|
225
|
+
enableSiteSettings = overrides.enableSiteSettings;
|
|
226
|
+
}
|
|
227
|
+
else if (process.env.CREATE_NOTIONX_NO_SITE_SETTINGS) {
|
|
228
|
+
const v = process.env.CREATE_NOTIONX_NO_SITE_SETTINGS.toLowerCase();
|
|
229
|
+
if (v === "1" || v === "true" || v === "yes") {
|
|
230
|
+
enableSiteSettings = false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// `enableBlocks` mirrors `enableSiteSettings` for the reusable
|
|
234
|
+
// page-blocks feature. Same env-var convention.
|
|
235
|
+
let enableBlocks = true;
|
|
236
|
+
if (overrides.enableBlocks !== undefined) {
|
|
237
|
+
enableBlocks = overrides.enableBlocks;
|
|
238
|
+
}
|
|
239
|
+
else if (process.env.CREATE_NOTIONX_NO_BLOCKS) {
|
|
240
|
+
const v = process.env.CREATE_NOTIONX_NO_BLOCKS.toLowerCase();
|
|
241
|
+
if (v === "1" || v === "true" || v === "yes") {
|
|
242
|
+
enableBlocks = false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// `enableAuth` / `enableAdmin` / `enablePages` follow the same
|
|
246
|
+
// pattern. Each defaults to true; the `CREATE_NOTIONX_NO_*` env
|
|
247
|
+
// var (or the `--no-*` CLI flag via overrides) opts out.
|
|
248
|
+
const enableAuth = resolveFlag(overrides.enableAuth, "CREATE_NOTIONX_NO_AUTH");
|
|
249
|
+
let enableAdmin = resolveFlag(overrides.enableAdmin, "CREATE_NOTIONX_NO_ADMIN");
|
|
250
|
+
let enablePages = resolveFlag(overrides.enablePages, "CREATE_NOTIONX_NO_PAGES");
|
|
251
|
+
const enableSearch = resolveFlag(overrides.enableSearch, "CREATE_NOTIONX_NO_SEARCH");
|
|
252
|
+
// Enforce dependency constraints: admin requires auth, pages
|
|
253
|
+
// requires blocks. If a dependency is disabled, the dependent
|
|
254
|
+
// feature is forced off regardless of the user's explicit flag.
|
|
255
|
+
if (!enableAuth && enableAdmin) {
|
|
256
|
+
enableAdmin = false;
|
|
257
|
+
}
|
|
258
|
+
if (!enableBlocks && enablePages) {
|
|
259
|
+
enablePages = false;
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
projectName,
|
|
263
|
+
targetDir,
|
|
264
|
+
defaultLocale,
|
|
265
|
+
supportedLocales: supportedLocales.length
|
|
266
|
+
? Array.from(new Set([defaultLocale, ...supportedLocales]))
|
|
267
|
+
: [defaultLocale],
|
|
268
|
+
notionxSource: overrides.notionxSource ?? FALLBACK_NOTIONX_SOURCE,
|
|
269
|
+
contentSource: {
|
|
270
|
+
id: contentId,
|
|
271
|
+
title: contentTitle,
|
|
272
|
+
fields,
|
|
273
|
+
},
|
|
274
|
+
adminEmail: adminEmail.toLowerCase(),
|
|
275
|
+
adminPassword,
|
|
276
|
+
notionParentPage,
|
|
277
|
+
notionSeedCount,
|
|
278
|
+
enableSiteSettings,
|
|
279
|
+
enableBlocks,
|
|
280
|
+
enableAuth,
|
|
281
|
+
enableAdmin,
|
|
282
|
+
enablePages,
|
|
283
|
+
enableSearch,
|
|
284
|
+
// Carry the random password (if any) so the CLI can echo it to
|
|
285
|
+
// stdout once at the very end of the run. Never persisted to disk
|
|
286
|
+
// and never sent to the database — only the hash lands in D1.
|
|
287
|
+
...(generatedAdminPassword
|
|
288
|
+
? { _generatedAdminPassword: generatedAdminPassword }
|
|
289
|
+
: {}),
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Entry point. Resolves answers from CLI flags first; falls back to
|
|
294
|
+
* the interactive prompt when the user did not pass `--yes` and
|
|
295
|
+
* didn't supply the project name on the command line.
|
|
296
|
+
*/
|
|
297
|
+
export async function gatherAnswers(argv = process.argv) {
|
|
298
|
+
const cli = parseArgs(argv);
|
|
299
|
+
// Resolve the `notionxSource` semver *before* handing the overrides
|
|
300
|
+
// off to `applyDefaults`. The default reads the live version from
|
|
301
|
+
// the npm registry (so freshly-installed scaffolds always match the
|
|
302
|
+
// latest published package without the user passing
|
|
303
|
+
// `--notionx-source`). When the target lives inside the `notionx`
|
|
304
|
+
// monorepo (e.g. `notionx/apps/<name>`), we short-circuit to
|
|
305
|
+
// `workspace:*` so the generated project links against the local
|
|
306
|
+
// `packages/notionx` checkout via pnpm workspace symlinks — this
|
|
307
|
+
// is the scaffolder author's fast path for iterating on `core`.
|
|
308
|
+
// The network call has a 5s timeout and falls back to a hardcoded
|
|
309
|
+
// caret range if the registry is unreachable — we never want a
|
|
310
|
+
// scaffolder to hang because npm is down.
|
|
311
|
+
const positionalTargetDir = argv[2] && !argv[2].startsWith("-") ? argv[2] : undefined;
|
|
312
|
+
const probeTargetDir = cli.targetDir ?? positionalTargetDir ?? `./${cli.projectName ?? "notionx-app"}`;
|
|
313
|
+
const notionxSource = await resolveNotionxSource(cli.notionxSource, probeTargetDir);
|
|
314
|
+
// If `--yes` was passed, or the caller supplied at least a project
|
|
315
|
+
// name (everything else has sensible defaults), build answers
|
|
316
|
+
// without ever invoking the prompt.
|
|
317
|
+
if (cli.yes || cli.projectName) {
|
|
318
|
+
return applyDefaults({ ...cli, notionxSource }, argv);
|
|
319
|
+
}
|
|
320
|
+
// Otherwise run the interactive prompt. If the env says we're a
|
|
321
|
+
// TTY-less pipe, abort with a friendly hint instead of hanging.
|
|
322
|
+
if (!process.stdin.isTTY) {
|
|
323
|
+
p.log.warn("No TTY detected. Pass --project-name <name> (or --yes) to run non-interactively. See --help.");
|
|
324
|
+
p.outro("Aborting.");
|
|
325
|
+
throw new Error("non-interactive without flags");
|
|
326
|
+
}
|
|
327
|
+
// Re-export the prompt function lazily to keep this module small.
|
|
328
|
+
const { prompt } = await import("./prompt.js");
|
|
329
|
+
return prompt(argv, { notionxSource });
|
|
330
|
+
}
|
|
331
|
+
export { applyDefaults, parseArgs, parseLocales, buildFields, toCamelCase };
|
|
332
|
+
//# sourceMappingURL=answers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answers.js","sourceRoot":"","sources":["../src/answers.ts"],"names":[],"mappings":"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"}
|