@notionx/create-notionx-app 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/README.md +139 -0
  2. package/dist/answers.js +332 -0
  3. package/dist/answers.js.map +1 -0
  4. package/dist/cli-notionx.js +388 -0
  5. package/dist/cli-notionx.js.map +1 -0
  6. package/dist/cli-notionx.test.js +277 -0
  7. package/dist/cli-notionx.test.js.map +1 -0
  8. package/dist/diff.js +40 -0
  9. package/dist/diff.js.map +1 -0
  10. package/dist/diff.test.js +90 -0
  11. package/dist/diff.test.js.map +1 -0
  12. package/dist/index.js +99 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/locale-add/apply.js +39 -0
  15. package/dist/locale-add/apply.js.map +1 -0
  16. package/dist/locale-add/format.js +38 -0
  17. package/dist/locale-add/format.js.map +1 -0
  18. package/dist/locale-add/list.js +44 -0
  19. package/dist/locale-add/list.js.map +1 -0
  20. package/dist/locale-add/list.test.js +45 -0
  21. package/dist/locale-add/list.test.js.map +1 -0
  22. package/dist/locale-add/plan.js +128 -0
  23. package/dist/locale-add/plan.js.map +1 -0
  24. package/dist/locale-add/validate.js +46 -0
  25. package/dist/locale-add/validate.js.map +1 -0
  26. package/dist/metadata.js +41 -0
  27. package/dist/metadata.js.map +1 -0
  28. package/dist/notion-translation-sources/apply.js +61 -0
  29. package/dist/notion-translation-sources/apply.js.map +1 -0
  30. package/dist/notion-translation-sources/index.js +3 -0
  31. package/dist/notion-translation-sources/index.js.map +1 -0
  32. package/dist/notion-translation-sources/plan.js +33 -0
  33. package/dist/notion-translation-sources/plan.js.map +1 -0
  34. package/dist/notionx-source.js +142 -0
  35. package/dist/notionx-source.js.map +1 -0
  36. package/dist/notionx-source.test.js +144 -0
  37. package/dist/notionx-source.test.js.map +1 -0
  38. package/dist/password.js +18 -0
  39. package/dist/password.js.map +1 -0
  40. package/dist/presets.js +83 -0
  41. package/dist/presets.js.map +1 -0
  42. package/dist/presets.test.js +50 -0
  43. package/dist/presets.test.js.map +1 -0
  44. package/dist/prompt.js +218 -0
  45. package/dist/prompt.js.map +1 -0
  46. package/dist/provision/cloudflare.js +236 -0
  47. package/dist/provision/cloudflare.js.map +1 -0
  48. package/dist/provision/dependencies.js +219 -0
  49. package/dist/provision/dependencies.js.map +1 -0
  50. package/dist/provision/index.js +681 -0
  51. package/dist/provision/index.js.map +1 -0
  52. package/dist/provision/index.test.js +54 -0
  53. package/dist/provision/index.test.js.map +1 -0
  54. package/dist/provision/inspect.js +109 -0
  55. package/dist/provision/inspect.js.map +1 -0
  56. package/dist/provision/inspect.test.js +75 -0
  57. package/dist/provision/inspect.test.js.map +1 -0
  58. package/dist/provision/notion.js +1981 -0
  59. package/dist/provision/notion.js.map +1 -0
  60. package/dist/provision/notion.test.js +542 -0
  61. package/dist/provision/notion.test.js.map +1 -0
  62. package/dist/provision/ntn-credentials.js +198 -0
  63. package/dist/provision/ntn-credentials.js.map +1 -0
  64. package/dist/provision/options.js +15 -0
  65. package/dist/provision/options.js.map +1 -0
  66. package/dist/provision/password-hash.js +78 -0
  67. package/dist/provision/password-hash.js.map +1 -0
  68. package/dist/provision/prompts.js +115 -0
  69. package/dist/provision/prompts.js.map +1 -0
  70. package/dist/provision/repair.js +48 -0
  71. package/dist/provision/repair.js.map +1 -0
  72. package/dist/provision/repair.test.js +141 -0
  73. package/dist/provision/repair.test.js.map +1 -0
  74. package/dist/provision/shell.js +84 -0
  75. package/dist/provision/shell.js.map +1 -0
  76. package/dist/provision/wire.js +78 -0
  77. package/dist/provision/wire.js.map +1 -0
  78. package/dist/registry/doctor.js +181 -0
  79. package/dist/registry/doctor.js.map +1 -0
  80. package/dist/registry/doctor.test.js +180 -0
  81. package/dist/registry/doctor.test.js.map +1 -0
  82. package/dist/registry/install.js +217 -0
  83. package/dist/registry/install.js.map +1 -0
  84. package/dist/registry/install.test.js +168 -0
  85. package/dist/registry/install.test.js.map +1 -0
  86. package/dist/registry/load-registry.js +24 -0
  87. package/dist/registry/load-registry.js.map +1 -0
  88. package/dist/registry/load-registry.test.js +59 -0
  89. package/dist/registry/load-registry.test.js.map +1 -0
  90. package/dist/registry/migration-planner.js +204 -0
  91. package/dist/registry/migration-planner.js.map +1 -0
  92. package/dist/registry/migration-planner.test.js +340 -0
  93. package/dist/registry/migration-planner.test.js.map +1 -0
  94. package/dist/registry/migrations-store.js +125 -0
  95. package/dist/registry/migrations-store.js.map +1 -0
  96. package/dist/registry/migrations-store.test.js +163 -0
  97. package/dist/registry/migrations-store.test.js.map +1 -0
  98. package/dist/registry/migrations-types.js +25 -0
  99. package/dist/registry/migrations-types.js.map +1 -0
  100. package/dist/registry/project-meta.js +84 -0
  101. package/dist/registry/project-meta.js.map +1 -0
  102. package/dist/registry/registry-items.js +354 -0
  103. package/dist/registry/registry-items.js.map +1 -0
  104. package/dist/registry/registry-items.test.js +99 -0
  105. package/dist/registry/registry-items.test.js.map +1 -0
  106. package/dist/registry/registry-store.js +232 -0
  107. package/dist/registry/registry-store.js.map +1 -0
  108. package/dist/registry/registry-store.test.js +136 -0
  109. package/dist/registry/registry-store.test.js.map +1 -0
  110. package/dist/registry/registry-types.js +18 -0
  111. package/dist/registry/registry-types.js.map +1 -0
  112. package/dist/registry/registry-types.test.js +146 -0
  113. package/dist/registry/registry-types.test.js.map +1 -0
  114. package/dist/registry/render-content-source-files.js +158 -0
  115. package/dist/registry/render-content-source-files.js.map +1 -0
  116. package/dist/registry/render-multi-source.js +296 -0
  117. package/dist/registry/render-multi-source.js.map +1 -0
  118. package/dist/registry/render-multi-source.test.js +110 -0
  119. package/dist/registry/render-multi-source.test.js.map +1 -0
  120. package/dist/registry/text-utils.js +42 -0
  121. package/dist/registry/text-utils.js.map +1 -0
  122. package/dist/registry/uninstall.js +250 -0
  123. package/dist/registry/uninstall.js.map +1 -0
  124. package/dist/registry/uninstall.test.js +264 -0
  125. package/dist/registry/uninstall.test.js.map +1 -0
  126. package/dist/registry/update.js +280 -0
  127. package/dist/registry/update.js.map +1 -0
  128. package/dist/registry/update.test.js +229 -0
  129. package/dist/registry/update.test.js.map +1 -0
  130. package/dist/render.js +549 -0
  131. package/dist/render.js.map +1 -0
  132. package/dist/render.test.js +414 -0
  133. package/dist/render.test.js.map +1 -0
  134. package/dist/templates/.dev.vars.example.tmpl +32 -0
  135. package/dist/templates/.gitignore.tmpl +58 -0
  136. package/dist/templates/README.md.tmpl +417 -0
  137. package/dist/templates/app/[slug]/page.tsx.tmpl +55 -0
  138. package/dist/templates/app/admin/account/page.tsx.tmpl +18 -0
  139. package/dist/templates/app/admin/content-models/page.tsx.tmpl +6 -0
  140. package/dist/templates/app/admin/layout.tsx.tmpl +90 -0
  141. package/dist/templates/app/admin/loading.tsx.tmpl +6 -0
  142. package/dist/templates/app/admin/page.tsx.tmpl +17 -0
  143. package/dist/templates/app/api/auth/google/callback/route.ts.tmpl +3 -0
  144. package/dist/templates/app/api/auth/google/route.ts.tmpl +3 -0
  145. package/dist/templates/app/api/auth/verify-email/route.ts.tmpl +3 -0
  146. package/dist/templates/app/api/auth/viewer/route.ts.tmpl +3 -0
  147. package/dist/templates/app/api/health/route.ts.tmpl +3 -0
  148. package/dist/templates/app/api/{{contentSourceId}}/[slug]/route.ts.tmpl +27 -0
  149. package/dist/templates/app/api/{{contentSourceId}}/route.ts.tmpl +18 -0
  150. package/dist/templates/app/globals.css.tmpl +109 -0
  151. package/dist/templates/app/layout.tsx.tmpl +56 -0
  152. package/dist/templates/app/login/page.tsx.tmpl +154 -0
  153. package/dist/templates/app/page.fallback.tsx.tmpl +31 -0
  154. package/dist/templates/app/page.tsx.tmpl +42 -0
  155. package/dist/templates/app/register/page.tsx.tmpl +138 -0
  156. package/dist/templates/app/{{contentSourceListPath}}/[slug]/page.tsx.tmpl +113 -0
  157. package/dist/templates/app/{{contentSourceListPath}}/page.tsx.tmpl +74 -0
  158. package/dist/templates/components/content/post-card.tsx.tmpl +80 -0
  159. package/dist/templates/components/notion-blocks.tsx.tmpl +668 -0
  160. package/dist/templates/components/page-blocks/feature-grid-block.tsx.tmpl +68 -0
  161. package/dist/templates/components/page-blocks/hero-block.tsx.tmpl +73 -0
  162. package/dist/templates/components/page-blocks/latest-posts-block.tsx.tmpl +59 -0
  163. package/dist/templates/components/page-blocks/story-block.tsx.tmpl +70 -0
  164. package/dist/templates/components/page-blocks.fallback.tsx.tmpl +17 -0
  165. package/dist/templates/components/page-blocks.tsx.tmpl +32 -0
  166. package/dist/templates/components/search/search-dialog.tsx.tmpl +171 -0
  167. package/dist/templates/components/site/locale-switcher.tsx.tmpl +65 -0
  168. package/dist/templates/components/site/site-footer.tsx.tmpl +106 -0
  169. package/dist/templates/components/site/site-header.tsx.tmpl +80 -0
  170. package/dist/templates/components/site/site-shell.tsx.tmpl +20 -0
  171. package/dist/templates/components/site/theme-bootstrap.tsx.tmpl +51 -0
  172. package/dist/templates/components/theme-provider.tsx.tmpl +14 -0
  173. package/dist/templates/components/theme-toggle.tsx.tmpl +38 -0
  174. package/dist/templates/components/ui/accordion.tsx.tmpl +56 -0
  175. package/dist/templates/components/ui/alert.tsx.tmpl +59 -0
  176. package/dist/templates/components/ui/aspect-ratio.tsx.tmpl +8 -0
  177. package/dist/templates/components/ui/avatar.tsx.tmpl +44 -0
  178. package/dist/templates/components/ui/badge.tsx.tmpl +33 -0
  179. package/dist/templates/components/ui/button.tsx.tmpl +56 -0
  180. package/dist/templates/components/ui/card.tsx.tmpl +61 -0
  181. package/dist/templates/components/ui/checkbox.tsx.tmpl +28 -0
  182. package/dist/templates/components/ui/dialog.tsx.tmpl +104 -0
  183. package/dist/templates/components/ui/dropdown-menu.tsx.tmpl +183 -0
  184. package/dist/templates/components/ui/input.tsx.tmpl +21 -0
  185. package/dist/templates/components/ui/label.tsx.tmpl +25 -0
  186. package/dist/templates/components/ui/popover.tsx.tmpl +30 -0
  187. package/dist/templates/components/ui/radio-group.tsx.tmpl +44 -0
  188. package/dist/templates/components/ui/select.tsx.tmpl +150 -0
  189. package/dist/templates/components/ui/separator.tsx.tmpl +30 -0
  190. package/dist/templates/components/ui/sheet.tsx.tmpl +125 -0
  191. package/dist/templates/components/ui/skeleton.tsx.tmpl +15 -0
  192. package/dist/templates/components/ui/sonner.tsx.tmpl +30 -0
  193. package/dist/templates/components/ui/switch.tsx.tmpl +29 -0
  194. package/dist/templates/components/ui/table.tsx.tmpl +107 -0
  195. package/dist/templates/components/ui/tabs.tsx.tmpl +55 -0
  196. package/dist/templates/components/ui/textarea.tsx.tmpl +24 -0
  197. package/dist/templates/components/ui/tooltip.tsx.tmpl +30 -0
  198. package/dist/templates/components.json.tmpl +21 -0
  199. package/dist/templates/env.d.ts.tmpl +32 -0
  200. package/dist/templates/lib/admin/actions.ts.tmpl +43 -0
  201. package/dist/templates/lib/admin/context.tsx.tmpl +209 -0
  202. package/dist/templates/lib/admin/nav.ts.tmpl +23 -0
  203. package/dist/templates/lib/auth.config.fallback.ts.tmpl +10 -0
  204. package/dist/templates/lib/auth.config.ts.tmpl +45 -0
  205. package/dist/templates/lib/blocks/translations.ts.tmpl +44 -0
  206. package/dist/templates/lib/blog/translations.ts.tmpl +52 -0
  207. package/dist/templates/lib/content/models.ts.tmpl +53 -0
  208. package/dist/templates/lib/i18n/config.ts.tmpl +18 -0
  209. package/dist/templates/lib/i18n/index.ts.tmpl +1 -0
  210. package/dist/templates/lib/locale-contract/built-in.ts.tmpl +19 -0
  211. package/dist/templates/lib/locale-contract/index.ts.tmpl +3 -0
  212. package/dist/templates/lib/locale-contract/paths.ts.tmpl +29 -0
  213. package/dist/templates/lib/pages/model.ts.tmpl +16 -0
  214. package/dist/templates/lib/pages/source.ts.tmpl +566 -0
  215. package/dist/templates/lib/pages/translations.ts.tmpl +34 -0
  216. package/dist/templates/lib/search/config.fallback.ts.tmpl +11 -0
  217. package/dist/templates/lib/search/config.ts.tmpl +25 -0
  218. package/dist/templates/lib/site/config.ts.tmpl +120 -0
  219. package/dist/templates/lib/site/request-env.ts.tmpl +71 -0
  220. package/dist/templates/lib/site/settings.fallback.ts.tmpl +21 -0
  221. package/dist/templates/lib/site/settings.ts.tmpl +320 -0
  222. package/dist/templates/lib/site/translations.ts.tmpl +30 -0
  223. package/dist/templates/lib/utils.ts.tmpl +9 -0
  224. package/dist/templates/migrations/0001_init.sql.tmpl +57 -0
  225. package/dist/templates/migrations/0002_admin_seed.sql.tmpl +30 -0
  226. package/dist/templates/migrations/0003_search_index.sql.tmpl +29 -0
  227. package/dist/templates/next.config.ts.tmpl +18 -0
  228. package/dist/templates/package.json.tmpl +40 -0
  229. package/dist/templates/shims/cloudflare-workers-empty.mjs +4 -0
  230. package/dist/templates/shims/next-headers-empty.mjs +4 -0
  231. package/dist/templates/tests/smoke.test.ts.tmpl +83 -0
  232. package/dist/templates/tsconfig.json.tmpl +31 -0
  233. package/dist/templates/vite.config.ts.tmpl +53 -0
  234. package/dist/templates/vitest.config.ts.tmpl +13 -0
  235. package/dist/templates/worker/index.ts.tmpl +52 -0
  236. package/dist/templates/wrangler.jsonc.tmpl +44 -0
  237. package/dist/ui-presets.js +60 -0
  238. package/dist/ui-presets.js.map +1 -0
  239. package/package.json +60 -0
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)
@@ -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":"AAAA,6CAA6C;AAC7C,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,mEAAmE;AAEnE,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAgEpF,MAAM,cAAc,GAAG,uDAAuD,CAAC;AAE/E;;;GAGG;AACH,SAAS,WAAW,CAClB,QAA6B,EAC7B,MAAc;IAEd,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC5C,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,CAAC;QACN,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9B,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK;SACT,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3D,IAAI,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC;IAC/B,OAAO,CACL,KAAK,CAAC,WAAW,EAAE;QACnB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CACjE,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAA0B,EAAE,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,+DAA+D;QAC/D,4DAA4D;QAC5D,+DAA+D;QAC/D,+DAA+D;QAC/D,gEAAgE;QAChE,oDAAoD;QACpD,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,WAA+B,CAAC;QACpC,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YACX,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAChC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzB,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,MAAM,QAAQ,GAAG,CAAC,KAAyB,EAAE,EAAE;YAC7C,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC9B,wDAAwD;gBACxD,OAAO,WAAW,CAAC;YACrB,CAAC;YACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,mBAAmB,CAAC,CAAC;YAClD,CAAC;YACD,2DAA2D;YAC3D,2DAA2D;YAC3D,iDAAiD;YACjD,QAAQ,GAAG,CAAC,CAAC;YACb,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QACF,QAAQ,GAAG,EAAE,CAAC;YACV,KAAK,gBAAgB;gBACnB,GAAG,CAAC,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACjC,MAAM;YACR,KAAK,cAAc;gBACjB,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC/B,MAAM;YACR,KAAK,kBAAkB;gBACrB,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACnC,MAAM;YACR,KAAK,qBAAqB;gBACxB,GAAG,CAAC,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACtC,MAAM;YACR,KAAK,cAAc;gBACjB,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC/B,MAAM;YACR,KAAK,iBAAiB;gBACpB,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAClC,MAAM;YACR,KAAK,UAAU;gBACb,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC5B,MAAM;YACR,KAAK,kBAAkB;gBACrB,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACnC,MAAM;YACR,KAAK,eAAe;gBAClB,GAAG,CAAC,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAChC,MAAM;YACR,KAAK,kBAAkB;gBACrB,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACnC,MAAM;YACR,KAAK,sBAAsB;gBACzB,GAAG,CAAC,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACtC,MAAM;YACR,KAAK,qBAAqB;gBACxB,GAAG,CAAC,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7C,MAAM;YACR,KAAK,IAAI,CAAC;YACV,KAAK,OAAO;gBACV,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC;gBACf,MAAM;YACR,KAAK,IAAI,CAAC;YACV,KAAK,QAAQ;gBACX,SAAS,EAAE,CAAC;gBACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAChB,MAAM;YACR;gBACE,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxB,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC;gBAC1C,CAAC;gBACD,0CAA0C;gBAC1C,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;oBACnB,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC;gBACtB,CAAC;gBACD,MAAM;QACV,CAAC;QACD,CAAC,IAAI,QAAQ,CAAC;IAChB,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCb,CAAC,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,SAAuB,EAAE,IAAc;IAC5D,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,IAAI,eAAe,CAAC;IAC7D,kEAAkE;IAClE,8DAA8D;IAC9D,kDAAkD;IAClD,mEAAmE;IACnE,wBAAwB;IACxB,MAAM,mBAAmB,GACvB,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,MAAM,SAAS,GACb,SAAS,CAAC,SAAS,IAAI,mBAAmB,IAAI,KAAK,WAAW,EAAE,CAAC;IACnE,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,IAAI,IAAI,CAAC;IACtD,MAAM,gBAAgB,GAAG,YAAY,CACnC,SAAS,CAAC,gBAAgB,IAAI,aAAa,CAC5C,CAAC;IACF,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,IAAI,MAAM,CAAC;IAChD,MAAM,YAAY,GAChB,SAAS,CAAC,YAAY,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,IAAI,cAAc,CAAC,CAAC;IAE/D,gEAAgE;IAChE,gFAAgF;IAChF,sFAAsF;IACtF,mEAAmE;IACnE,MAAM,UAAU,GACd,SAAS,CAAC,UAAU;QACpB,OAAO,CAAC,GAAG,CAAC,0BAA0B;QACtC,mBAAmB,CAAC;IACtB,MAAM,iBAAiB,GAAG,sBAAsB,EAAE,CAAC;IACnD,MAAM,aAAa,GACjB,SAAS,CAAC,aAAa;QACvB,OAAO,CAAC,GAAG,CAAC,6BAA6B;QACzC,iBAAiB,CAAC;IACpB,MAAM,sBAAsB,GAC1B,aAAa,KAAK,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC;IAEtE,6DAA6D;IAC7D,kEAAkE;IAClE,4BAA4B;IAC5B,MAAM,gBAAgB,GACpB,SAAS,CAAC,gBAAgB;QAC1B,OAAO,CAAC,GAAG,CAAC,iCAAiC;QAC7C,EAAE,CAAC;IACL,MAAM,eAAe,GACnB,SAAS,CAAC,eAAe;QACzB,CAAC,OAAO,CAAC,GAAG,CAAC,gCAAgC,KAAK,SAAS;YACzD,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC;YACtD,CAAC,CAAC,CAAC,CAAC,CAAC;IAET,2EAA2E;IAC3E,+DAA+D;IAC/D,oEAAoE;IACpE,IAAI,kBAAkB,GAAY,IAAI,CAAC;IACvC,IAAI,SAAS,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC/C,kBAAkB,GAAG,SAAS,CAAC,kBAAkB,CAAC;IACpD,CAAC;SAAM,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,CAAC;QACvD,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,WAAW,EAAE,CAAC;QACpE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;YAC7C,kBAAkB,GAAG,KAAK,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,gDAAgD;IAChD,IAAI,YAAY,GAAY,IAAI,CAAC;IACjC,IAAI,SAAS,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACzC,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC;IACxC,CAAC;SAAM,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;QAChD,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,WAAW,EAAE,CAAC;QAC7D,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;YAC7C,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,gEAAgE;IAChE,yDAAyD;IACzD,MAAM,UAAU,GAAG,WAAW,CAC5B,SAAS,CAAC,UAAU,EACpB,wBAAwB,CACzB,CAAC;IACF,IAAI,WAAW,GAAG,WAAW,CAC3B,SAAS,CAAC,WAAW,EACrB,yBAAyB,CAC1B,CAAC;IACF,IAAI,WAAW,GAAG,WAAW,CAC3B,SAAS,CAAC,WAAW,EACrB,yBAAyB,CAC1B,CAAC;IACF,MAAM,YAAY,GAAG,WAAW,CAC9B,SAAS,CAAC,YAAY,EACtB,0BAA0B,CAC3B,CAAC;IAEF,6DAA6D;IAC7D,8DAA8D;IAC9D,gEAAgE;IAChE,IAAI,CAAC,UAAU,IAAI,WAAW,EAAE,CAAC;QAC/B,WAAW,GAAG,KAAK,CAAC;IACtB,CAAC;IACD,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC;QACjC,WAAW,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,OAAO;QACL,WAAW;QACX,SAAS;QACT,aAAa;QACb,gBAAgB,EAAE,gBAAgB,CAAC,MAAM;YACvC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC;YAC3D,CAAC,CAAC,CAAC,aAAa,CAAC;QACnB,aAAa,EAAE,SAAS,CAAC,aAAa,IAAI,uBAAuB;QACjE,aAAa,EAAE;YACb,EAAE,EAAE,SAAS;YACb,KAAK,EAAE,YAAY;YACnB,MAAM;SACP;QACD,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE;QACpC,aAAa;QACb,gBAAgB;QAChB,eAAe;QACf,kBAAkB;QAClB,YAAY;QACZ,UAAU;QACV,WAAW;QACX,WAAW;QACX,YAAY;QACZ,+DAA+D;QAC/D,kEAAkE;QAClE,8DAA8D;QAC9D,GAAG,CAAC,sBAAsB;YACxB,CAAC,CAAC,EAAE,uBAAuB,EAAE,sBAAsB,EAAE;YACrD,CAAC,CAAC,EAAE,CAAC;KAC0C,CAAC;AACtD,CAAC;AAOD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAiB,OAAO,CAAC,IAAI;IAE7B,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE5B,oEAAoE;IACpE,kEAAkE;IAClE,oEAAoE;IACpE,oDAAoD;IACpD,kEAAkE;IAClE,6DAA6D;IAC7D,iEAAiE;IACjE,iEAAiE;IACjE,gEAAgE;IAChE,kEAAkE;IAClE,+DAA+D;IAC/D,0CAA0C;IAC1C,MAAM,mBAAmB,GACvB,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,MAAM,cAAc,GAClB,GAAG,CAAC,SAAS,IAAI,mBAAmB,IAAI,KAAK,GAAG,CAAC,WAAW,IAAI,aAAa,EAAE,CAAC;IAClF,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAC9C,GAAG,CAAC,aAAa,EACjB,cAAc,CACf,CAAC;IAEF,mEAAmE;IACnE,8DAA8D;IAC9D,oCAAoC;IACpC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QAC/B,OAAO,aAAa,CAAC,EAAE,GAAG,GAAG,EAAE,aAAa,EAAE,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,gEAAgE;IAChE,gEAAgE;IAChE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC,CAAC,GAAG,CAAC,IAAI,CACR,8FAA8F,CAC/F,CAAC;QACF,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,kEAAkE;IAClE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC"}