@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
@@ -0,0 +1,144 @@
1
+ // packages/create-notionx-app/src/notionx-source.test.ts
2
+ //
3
+ // Covers the `notionxSource` resolver:
4
+ // - explicit CLI overrides pass through unchanged
5
+ // - the monorepo dev path emits `workspace:*` when the target
6
+ // lives inside the `notionx` monorepo
7
+ // - the default path fetches the live version from the npm
8
+ // registry, with a hardcoded caret-range fallback when the
9
+ // registry is unreachable
10
+ import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "node:fs";
11
+ import { tmpdir } from "node:os";
12
+ import { join, resolve } from "node:path";
13
+ import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
14
+ import { isMonorepoDevMode, MONOREPO_PROTOCOL, resolveNotionxSource, } from "./notionx-source.js";
15
+ const ORIGINAL_FETCH = globalThis.fetch;
16
+ // A scratch monorepo laid out as
17
+ //
18
+ // <root>/packages/notionx/package.json (name: "@notionx/core")
19
+ // <root>/apps/scratch/digwis (the target)
20
+ //
21
+ // `isMonorepoDevMode` should return `true` for a target that is
22
+ // two levels deep from the monorepo root.
23
+ let scratchRoot = "";
24
+ let scratchAppDir = "";
25
+ beforeAll(() => {
26
+ scratchRoot = mkdtempSync(join(tmpdir(), "notionx-src-test-"));
27
+ const pkgDir = join(scratchRoot, "packages", "notionx");
28
+ mkdirSync(pkgDir, { recursive: true });
29
+ writeFileSync(join(pkgDir, "package.json"), JSON.stringify({ name: "@notionx/core", version: "1.0.0" }));
30
+ scratchAppDir = resolve(scratchRoot, "apps", "scratch", "digwis");
31
+ mkdirSync(scratchAppDir, { recursive: true });
32
+ });
33
+ afterEach(() => {
34
+ globalThis.fetch = ORIGINAL_FETCH;
35
+ vi.restoreAllMocks();
36
+ });
37
+ afterAll(() => {
38
+ if (scratchRoot) {
39
+ rmSync(scratchRoot, { recursive: true, force: true });
40
+ }
41
+ });
42
+ function mockFetch(body, init = {}) {
43
+ return vi.fn().mockResolvedValue({
44
+ ok: init.ok ?? true,
45
+ status: init.status ?? 200,
46
+ json: async () => body,
47
+ });
48
+ }
49
+ describe("isMonorepoDevMode", () => {
50
+ it("returns true when the target is inside the notionx monorepo", () => {
51
+ expect(isMonorepoDevMode(scratchAppDir)).toBe(true);
52
+ });
53
+ it("returns false for a path that has no monorepo neighbour", () => {
54
+ const orphan = mkdtempSync(join(tmpdir(), "notionx-orphan-"));
55
+ try {
56
+ expect(isMonorepoDevMode(orphan)).toBe(false);
57
+ }
58
+ finally {
59
+ rmSync(orphan, { recursive: true, force: true });
60
+ }
61
+ });
62
+ it("returns false when the neighbour package is not @notionx/core", () => {
63
+ const other = mkdtempSync(join(tmpdir(), "notionx-other-"));
64
+ try {
65
+ const pkgDir = join(other, "packages", "notionx");
66
+ mkdirSync(pkgDir, { recursive: true });
67
+ writeFileSync(join(pkgDir, "package.json"), JSON.stringify({ name: "something-else", version: "0.1.0" }));
68
+ const target = join(other, "apps", "scratch", "digwis");
69
+ mkdirSync(target, { recursive: true });
70
+ expect(isMonorepoDevMode(target)).toBe(false);
71
+ }
72
+ finally {
73
+ rmSync(other, { recursive: true, force: true });
74
+ }
75
+ });
76
+ });
77
+ describe("resolveNotionxSource", () => {
78
+ it("returns the override unchanged when supplied", async () => {
79
+ const fetchSpy = vi.fn();
80
+ globalThis.fetch = fetchSpy;
81
+ await expect(resolveNotionxSource("^1.2.3", scratchAppDir)).resolves.toBe("^1.2.3");
82
+ expect(fetchSpy).not.toHaveBeenCalled();
83
+ });
84
+ it("short-circuits to workspace:* when the target is inside the monorepo", async () => {
85
+ const fetchSpy = vi.fn();
86
+ globalThis.fetch = fetchSpy;
87
+ await expect(resolveNotionxSource(undefined, scratchAppDir)).resolves.toBe(MONOREPO_PROTOCOL);
88
+ expect(fetchSpy).not.toHaveBeenCalled();
89
+ });
90
+ it("treats an empty-string override the same as an absent one", async () => {
91
+ globalThis.fetch = mockFetch({ version: "1.0.0" });
92
+ const orphan = mkdtempSync(join(tmpdir(), "notionx-empty-"));
93
+ try {
94
+ await expect(resolveNotionxSource("", orphan)).resolves.toBe("^1.0.0");
95
+ }
96
+ finally {
97
+ rmSync(orphan, { recursive: true, force: true });
98
+ }
99
+ });
100
+ it("prefixes the live npm version with a caret when no override is set and target is outside the monorepo", async () => {
101
+ globalThis.fetch = mockFetch({ version: "1.0.0" });
102
+ const orphan = mkdtempSync(join(tmpdir(), "notionx-live-"));
103
+ try {
104
+ await expect(resolveNotionxSource(undefined, orphan)).resolves.toBe("^1.0.0");
105
+ expect(globalThis.fetch).toHaveBeenCalledWith("https://registry.npmjs.org/@notionx/core/latest", expect.objectContaining({ signal: expect.any(AbortSignal) }));
106
+ }
107
+ finally {
108
+ rmSync(orphan, { recursive: true, force: true });
109
+ }
110
+ });
111
+ it("falls back to a hardcoded caret range on HTTP errors", async () => {
112
+ globalThis.fetch = mockFetch("not found", { ok: false, status: 404 });
113
+ const orphan = mkdtempSync(join(tmpdir(), "notionx-404-"));
114
+ try {
115
+ await expect(resolveNotionxSource(undefined, orphan)).resolves.toMatch(/^\^/);
116
+ }
117
+ finally {
118
+ rmSync(orphan, { recursive: true, force: true });
119
+ }
120
+ });
121
+ it("falls back to a hardcoded caret range on network errors", async () => {
122
+ globalThis.fetch = vi
123
+ .fn()
124
+ .mockRejectedValue(new Error("ECONNREFUSED"));
125
+ const orphan = mkdtempSync(join(tmpdir(), "notionx-net-"));
126
+ try {
127
+ await expect(resolveNotionxSource(undefined, orphan)).resolves.toMatch(/^\^/);
128
+ }
129
+ finally {
130
+ rmSync(orphan, { recursive: true, force: true });
131
+ }
132
+ });
133
+ it("falls back when the registry response is missing a version field", async () => {
134
+ globalThis.fetch = mockFetch({});
135
+ const orphan = mkdtempSync(join(tmpdir(), "notionx-empty-body-"));
136
+ try {
137
+ await expect(resolveNotionxSource(undefined, orphan)).resolves.toMatch(/^\^/);
138
+ }
139
+ finally {
140
+ rmSync(orphan, { recursive: true, force: true });
141
+ }
142
+ });
143
+ });
144
+ //# sourceMappingURL=notionx-source.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notionx-source.test.js","sourceRoot":"","sources":["../src/notionx-source.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import * as crypto from "node:crypto";
2
+ /** Generate a 14-char password with letters + digits, easy to copy. */
3
+ export function generateRandomPassword() {
4
+ // Avoid 0/O/1/l/I for readability; pick from a friendly alphabet.
5
+ const letters = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
6
+ const digits = "23456789";
7
+ const all = letters + digits;
8
+ const bytes = crypto.randomBytes(14);
9
+ let out = "";
10
+ // Guarantee at least one letter and one digit.
11
+ out += letters[bytes[0] % letters.length];
12
+ out += digits[bytes[1] % digits.length];
13
+ for (let i = 2; i < 14; i++) {
14
+ out += all[bytes[i] % all.length];
15
+ }
16
+ return out;
17
+ }
18
+ //# sourceMappingURL=password.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password.js","sourceRoot":"","sources":["../src/password.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAEtC,uEAAuE;AACvE,MAAM,UAAU,sBAAsB;IACpC,kEAAkE;IAClE,MAAM,OAAO,GAAG,gDAAgD,CAAC;IACjE,MAAM,MAAM,GAAG,UAAU,CAAC;IAC1B,MAAM,GAAG,GAAG,OAAO,GAAG,MAAM,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,+CAA+C;IAC/C,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,83 @@
1
+ // packages/create-notionx-app/src/presets.ts
2
+ //
3
+ // The scaffolder ships a single UI component set (the "site" set):
4
+ // the shadcn/ui primitives the Notion block renderer leans on.
5
+ // Earlier 0.5.x versions offered `minimal`/`app` alternatives;
6
+ // those were collapsed because every shipped scaffold needs the
7
+ // page-builder components.
8
+ //
9
+ // The component filenames must match the source `*.tmpl` files in
10
+ // `templates/components/ui/` exactly. The renderer does not
11
+ // validate this — a typo here silently produces a project missing
12
+ // one component file. Tests under `presets.test.ts` pin the file
13
+ // set so the gap shows up in CI instead of in a user's project.
14
+ /**
15
+ * shadcn/ui components vendored into every generated project's
16
+ * `components/ui/` directory.
17
+ */
18
+ export const SITE_COMPONENTS = [
19
+ "accordion",
20
+ "alert",
21
+ "aspect-ratio",
22
+ "badge",
23
+ "button",
24
+ "card",
25
+ "dialog",
26
+ "dropdown-menu",
27
+ "input",
28
+ "label",
29
+ "separator",
30
+ "sheet",
31
+ "skeleton",
32
+ "table",
33
+ "tabs",
34
+ "tooltip",
35
+ ];
36
+ /**
37
+ * Extra `@radix-ui/*` packages required to compile the vendored
38
+ * components above. The base template already declares
39
+ * `@radix-ui/react-slot`, `class-variance-authority`, `clsx`,
40
+ * `lucide-react`, `next-themes`, `tailwind-merge`, and
41
+ * `tailwindcss-animate` — those are not duplicated here.
42
+ */
43
+ export const SITE_DEPENDENCIES = [
44
+ { name: "@radix-ui/react-accordion", version: "^1.2.2" },
45
+ { name: "@radix-ui/react-alert-dialog", version: "^1.1.4" },
46
+ { name: "@radix-ui/react-aspect-ratio", version: "^1.1.1" },
47
+ { name: "@radix-ui/react-dialog", version: "^1.1.4" },
48
+ { name: "@radix-ui/react-dropdown-menu", version: "^2.1.4" },
49
+ { name: "@radix-ui/react-label", version: "^2.1.0" },
50
+ { name: "@radix-ui/react-separator", version: "^1.1.0" },
51
+ { name: "@radix-ui/react-slot", version: "^1.2.0" },
52
+ { name: "@radix-ui/react-tabs", version: "^1.1.2" },
53
+ { name: "@radix-ui/react-tooltip", version: "^1.1.6" },
54
+ ];
55
+ /**
56
+ * Render the dependency list for the site component set as a sorted
57
+ * array. Excludes any package that already appears in the base
58
+ * template's dependency block so we don't end up with duplicate
59
+ * keys after a preset upgrade.
60
+ */
61
+ export function siteDependencyEntries(excludeNames = new Set()) {
62
+ const seen = new Set();
63
+ const out = [];
64
+ for (const dep of SITE_DEPENDENCIES) {
65
+ if (seen.has(dep.name))
66
+ continue;
67
+ if (excludeNames.has(dep.name))
68
+ continue;
69
+ seen.add(dep.name);
70
+ out.push(dep);
71
+ }
72
+ return out;
73
+ }
74
+ /**
75
+ * Stable, sorted list of component file basenames. The renderer
76
+ * uses this to decide which files in
77
+ * `templates/components/ui/` survive the copy step. Stable sort
78
+ * makes the generated project deterministic.
79
+ */
80
+ export function siteComponentNames() {
81
+ return [...SITE_COMPONENTS].sort();
82
+ }
83
+ //# sourceMappingURL=presets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,mEAAmE;AACnE,+DAA+D;AAC/D,+DAA+D;AAC/D,gEAAgE;AAChE,2BAA2B;AAC3B,EAAE;AACF,kEAAkE;AAClE,4DAA4D;AAC5D,kEAAkE;AAClE,iEAAiE;AACjE,gEAAgE;AAUhE;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,WAAW;IACX,OAAO;IACP,cAAc;IACd,OAAO;IACP,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,eAAe;IACf,OAAO;IACP,OAAO;IACP,WAAW;IACX,OAAO;IACP,UAAU;IACV,OAAO;IACP,MAAM;IACN,SAAS;CACV,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAgC;IAC5D,EAAE,IAAI,EAAE,2BAA2B,EAAE,OAAO,EAAE,QAAQ,EAAE;IACxD,EAAE,IAAI,EAAE,8BAA8B,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC3D,EAAE,IAAI,EAAE,8BAA8B,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC3D,EAAE,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACrD,EAAE,IAAI,EAAE,+BAA+B,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC5D,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACpD,EAAE,IAAI,EAAE,2BAA2B,EAAE,OAAO,EAAE,QAAQ,EAAE;IACxD,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACnD,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACnD,EAAE,IAAI,EAAE,yBAAyB,EAAE,OAAO,EAAE,QAAQ,EAAE;CACvD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,eAAoC,IAAI,GAAG,EAAE;IAE7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAuB,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACjC,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACzC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { SITE_COMPONENTS, siteComponentNames, siteDependencyEntries, } from "./presets.js";
3
+ describe("site components", () => {
4
+ it("includes the page-builder component set", () => {
5
+ const names = siteComponentNames();
6
+ for (const expected of [
7
+ "accordion",
8
+ "alert",
9
+ "aspect-ratio",
10
+ "badge",
11
+ "button",
12
+ "card",
13
+ "dialog",
14
+ "dropdown-menu",
15
+ "input",
16
+ "label",
17
+ "separator",
18
+ "sheet",
19
+ "skeleton",
20
+ "table",
21
+ "tabs",
22
+ "tooltip",
23
+ ]) {
24
+ expect(names).toContain(expected);
25
+ }
26
+ });
27
+ it("returns a stable, alphabetised list (no ordering flakiness)", () => {
28
+ expect(siteComponentNames()).toEqual([...siteComponentNames()].sort());
29
+ });
30
+ it("SITE_COMPONENTS matches siteComponentNames()", () => {
31
+ expect([...SITE_COMPONENTS].sort()).toEqual(siteComponentNames());
32
+ });
33
+ });
34
+ describe("site dependency entries", () => {
35
+ it("deduplicates Radix packages that appear via multiple components", () => {
36
+ const deps = siteDependencyEntries();
37
+ const seen = new Set();
38
+ for (const dep of deps) {
39
+ expect(seen.has(dep.name)).toBe(false);
40
+ seen.add(dep.name);
41
+ }
42
+ });
43
+ it("respects the exclusion list (caller already covered these)", () => {
44
+ const exclude = new Set(["@radix-ui/react-slot"]);
45
+ const deps = siteDependencyEntries(exclude);
46
+ expect(deps.find((d) => d.name === "@radix-ui/react-slot")).toBeUndefined();
47
+ expect(deps.find((d) => d.name === "@radix-ui/react-accordion")).toBeDefined();
48
+ });
49
+ });
50
+ //# sourceMappingURL=presets.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.test.js","sourceRoot":"","sources":["../src/presets.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAEtB,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;QACnC,KAAK,MAAM,QAAQ,IAAI;YACrB,WAAW;YACX,OAAO;YACP,cAAc;YACd,OAAO;YACP,QAAQ;YACR,MAAM;YACN,QAAQ;YACR,eAAe;YACf,OAAO;YACP,OAAO;YACP,WAAW;YACX,OAAO;YACP,UAAU;YACV,OAAO;YACP,MAAM;YACN,SAAS;SACV,EAAE,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,kBAAkB,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC5E,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,2BAA2B,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/prompt.js ADDED
@@ -0,0 +1,218 @@
1
+ // packages/create-notionx-app/src/prompt.ts
2
+ //
3
+ // Interactive prompt for `create-notionx-app`. The flow is intentionally
4
+ // minimal: we ask for the project name, language mode, and admin email.
5
+ // Everything else (content-source shape, etc.) uses sensible defaults
6
+ // that can be edited in the generated project after scaffolding.
7
+ import * as p from "@clack/prompts";
8
+ import { generateRandomPassword } from "./password.js";
9
+ import { FALLBACK_NOTIONX_SOURCE } from "./notionx-source.js";
10
+ const FIELD_KEY_RE = /^[a-z][a-zA-Z0-9]*$/;
11
+ const LANGUAGE_OPTIONS = {
12
+ en: {
13
+ defaultLocale: "en",
14
+ supportedLocales: ["en"],
15
+ label: "English",
16
+ },
17
+ zh: {
18
+ defaultLocale: "zh-CN",
19
+ supportedLocales: ["zh-CN"],
20
+ label: "中文",
21
+ },
22
+ bilingual: {
23
+ defaultLocale: "en",
24
+ supportedLocales: ["en", "zh-CN"],
25
+ label: "English + 中文",
26
+ },
27
+ };
28
+ function asString(value, fallback) {
29
+ if (typeof value === "string" && value.trim().length > 0)
30
+ return value.trim();
31
+ return fallback;
32
+ }
33
+ function toCamelCase(name) {
34
+ const cleaned = name.replace(/[^a-zA-Z0-9 ]/g, " ").trim();
35
+ if (!cleaned)
36
+ return "field";
37
+ const parts = cleaned.split(/\s+/);
38
+ const [first, ...rest] = parts;
39
+ return (first.toLowerCase() +
40
+ rest.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(""));
41
+ }
42
+ /** Defaults applied when the user accepts the canned scaffolding. */
43
+ export const DEFAULT_ANSWERS = {
44
+ defaultLocale: "en",
45
+ supportedLocales: ["en"],
46
+ notionxSource: FALLBACK_NOTIONX_SOURCE,
47
+ // Admin defaults are placeholders only — `gatherAnswers()` and the
48
+ // interactive prompt both overwrite them. The strings here are
49
+ // chosen so any logic that accidentally reads them sees clearly
50
+ // non-runnable values.
51
+ adminEmail: "admin@example.com",
52
+ adminPassword: "ChangeMe1234",
53
+ notionParentPage: "",
54
+ notionSeedCount: 6,
55
+ // Site-level config lives in a separate Notion data source by
56
+ // default. The generated project reads site name / tagline /
57
+ // description / default locale / social image from there, with
58
+ // `lib/site/config.ts` as a static fallback. Set to `false` to
59
+ // skip the extra data source entirely (e.g. for projects that
60
+ // don't need operators to edit site copy from Notion).
61
+ enableSiteSettings: true,
62
+ enableBlocks: true,
63
+ enableAuth: true,
64
+ enableAdmin: true,
65
+ enablePages: true,
66
+ enableSearch: true,
67
+ contentSource: {
68
+ id: "blog",
69
+ title: "Blog",
70
+ fields: [
71
+ { key: "title", notionName: "Name" },
72
+ { key: "slug", notionName: "Slug" },
73
+ { key: "description", notionName: "Description" },
74
+ { key: "published", notionName: "Published" },
75
+ { key: "date", notionName: "Date" },
76
+ { key: "tags", notionName: "Tags" },
77
+ { key: "cover", notionName: "Cover" },
78
+ ],
79
+ },
80
+ };
81
+ /**
82
+ * Run the interactive prompt sequence. Cancels (Ctrl-C) throw so the
83
+ * CLI wrapper can exit with a friendly message. The `argv` parameter
84
+ * lets the caller pre-fill answers from positional args; positional
85
+ * arg `argv[2]` (if any) is used as the target directory.
86
+ *
87
+ * The flow is intentionally minimal: project name → confirm-and-go.
88
+ * All other settings use the canned defaults in `DEFAULT_ANSWERS`.
89
+ */
90
+ export async function prompt(argv = process.argv, resolved = {}) {
91
+ p.intro("@notionx/create-notionx-app — scaffold a new vinext project");
92
+ const targetFromArg = argv[2];
93
+ const projectName = asString(await p.text({
94
+ message: "Project name?",
95
+ placeholder: "my-vinext-app",
96
+ validate: (v) => {
97
+ if (!v || v.trim().length === 0)
98
+ return "Project name is required";
99
+ if (!/^[a-z0-9][a-z0-9-_]*$/i.test(v.trim()))
100
+ return "Use letters, digits, dashes, or underscores";
101
+ return undefined;
102
+ },
103
+ }), "");
104
+ const targetDir = targetFromArg && targetFromArg.trim().length > 0
105
+ ? targetFromArg.trim()
106
+ : `./${projectName}`;
107
+ const languageMode = await p.select({
108
+ message: "Project language?",
109
+ initialValue: "en",
110
+ options: [
111
+ {
112
+ value: "en",
113
+ label: "English",
114
+ hint: "single-language starter",
115
+ },
116
+ {
117
+ value: "zh",
118
+ label: "中文",
119
+ hint: "单语言中文项目",
120
+ },
121
+ {
122
+ value: "bilingual",
123
+ label: "English + 中文",
124
+ hint: "ready for future multilingual content",
125
+ },
126
+ ],
127
+ });
128
+ if (p.isCancel(languageMode)) {
129
+ p.cancel("Cancelled by user");
130
+ throw new Error("cancelled");
131
+ }
132
+ const localeConfig = LANGUAGE_OPTIONS[String(languageMode)] ??
133
+ LANGUAGE_OPTIONS.en;
134
+ // Summarise the canned defaults so the user knows what they're agreeing to.
135
+ const fieldsList = DEFAULT_ANSWERS.contentSource.fields
136
+ .map((f) => f.notionName)
137
+ .join(", ");
138
+ p.log.info([
139
+ `Defaults:`,
140
+ ` target dir : ${targetDir}`,
141
+ ` language : ${localeConfig.label}`,
142
+ ` default locale : ${localeConfig.defaultLocale} (fallback/current)`,
143
+ ` supported locales: ${localeConfig.supportedLocales.join(", ")} (available)`,
144
+ ` content source : ${DEFAULT_ANSWERS.contentSource.id} (${DEFAULT_ANSWERS.contentSource.title})`,
145
+ ` fields : ${fieldsList}`,
146
+ ].join("\n"));
147
+ const confirmed = await p.confirm({
148
+ message: "Generate the project with these settings?",
149
+ initialValue: true,
150
+ });
151
+ if (!confirmed || p.isCancel(confirmed)) {
152
+ p.cancel("Cancelled by user");
153
+ throw new Error("cancelled");
154
+ }
155
+ // Admin account — collected last so users see what they're agreeing
156
+ // to before we ask for credentials. The password is generated here,
157
+ // hashed at render time, and printed once at the end by index.ts.
158
+ p.log.info("Admin account: the email below is granted the `admin` role on first login. " +
159
+ "The scaffolder will generate an initial password, hash it into D1, " +
160
+ "and print it once after setup so you can log in and change it.");
161
+ const adminEmail = asString(await p.text({
162
+ message: "Admin email?",
163
+ placeholder: "you@example.com",
164
+ validate: (v) => {
165
+ const t = (v ?? "").trim();
166
+ if (!t)
167
+ return "Admin email is required";
168
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t))
169
+ return "Must be a valid email address";
170
+ return undefined;
171
+ },
172
+ }), "");
173
+ const adminPassword = generateRandomPassword();
174
+ p.outro("Prompt complete — generating files…");
175
+ // Validate field keys (defensive — DEFAULT_ANSWERS is hand-written so
176
+ // it should always pass, but we re-run the same guard used by the
177
+ // legacy multi-step prompt).
178
+ const seen = new Set();
179
+ const fields = [];
180
+ for (const f of DEFAULT_ANSWERS.contentSource.fields) {
181
+ if (!FIELD_KEY_RE.test(f.key))
182
+ continue;
183
+ if (seen.has(f.key))
184
+ continue;
185
+ seen.add(f.key);
186
+ fields.push(f);
187
+ }
188
+ return {
189
+ projectName: projectName.trim(),
190
+ targetDir,
191
+ defaultLocale: localeConfig.defaultLocale,
192
+ supportedLocales: [...localeConfig.supportedLocales],
193
+ // Caller-supplied `notionxSource` (resolved from the npm
194
+ // registry / monorepo probe by `gatherAnswers()`) wins over
195
+ // the canned default. Without this, a successful registry
196
+ // resolution is silently discarded and the generated
197
+ // `package.json` ends up pinned to `DEFAULT_ANSWERS.notionxSource`
198
+ // even when npm already publishes a newer `@notionx/core`.
199
+ notionxSource: resolved.notionxSource ?? DEFAULT_ANSWERS.notionxSource,
200
+ contentSource: {
201
+ id: DEFAULT_ANSWERS.contentSource.id,
202
+ title: DEFAULT_ANSWERS.contentSource.title,
203
+ fields: fields.length ? fields : DEFAULT_ANSWERS.contentSource.fields,
204
+ },
205
+ adminEmail: adminEmail.toLowerCase(),
206
+ adminPassword,
207
+ notionParentPage: DEFAULT_ANSWERS.notionParentPage,
208
+ notionSeedCount: DEFAULT_ANSWERS.notionSeedCount,
209
+ enableSiteSettings: DEFAULT_ANSWERS.enableSiteSettings,
210
+ enableBlocks: DEFAULT_ANSWERS.enableBlocks,
211
+ enableAuth: DEFAULT_ANSWERS.enableAuth,
212
+ enableAdmin: DEFAULT_ANSWERS.enableAdmin,
213
+ enablePages: DEFAULT_ANSWERS.enablePages,
214
+ enableSearch: DEFAULT_ANSWERS.enableSearch,
215
+ _generatedAdminPassword: adminPassword,
216
+ };
217
+ }
218
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,yEAAyE;AACzE,wEAAwE;AACxE,sEAAsE;AACtE,iEAAiE;AAEjE,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAyF9D,MAAM,YAAY,GAAG,qBAAqB,CAAC;AAC3C,MAAM,gBAAgB,GAAG;IACvB,EAAE,EAAE;QACF,aAAa,EAAE,IAAI;QACnB,gBAAgB,EAAE,CAAC,IAAI,CAAC;QACxB,KAAK,EAAE,SAAS;KACjB;IACD,EAAE,EAAE;QACF,aAAa,EAAE,OAAO;QACtB,gBAAgB,EAAE,CAAC,OAAO,CAAC;QAC3B,KAAK,EAAE,IAAI;KACZ;IACD,SAAS,EAAE;QACT,aAAa,EAAE,IAAI;QACnB,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;QACjC,KAAK,EAAE,cAAc;KACtB;CACO,CAAC;AAEX,SAAS,QAAQ,CAAC,KAAc,EAAE,QAAgB;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;IAC9E,OAAO,QAAQ,CAAC;AAClB,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,qEAAqE;AACrE,MAAM,CAAC,MAAM,eAAe,GAGxB;IACF,aAAa,EAAE,IAAI;IACnB,gBAAgB,EAAE,CAAC,IAAI,CAAC;IACxB,aAAa,EAAE,uBAAuB;IACtC,mEAAmE;IACnE,+DAA+D;IAC/D,gEAAgE;IAChE,uBAAuB;IACvB,UAAU,EAAE,mBAAmB;IAC/B,aAAa,EAAE,cAAc;IAC7B,gBAAgB,EAAE,EAAE;IACpB,eAAe,EAAE,CAAC;IAClB,8DAA8D;IAC9D,6DAA6D;IAC7D,+DAA+D;IAC/D,+DAA+D;IAC/D,8DAA8D;IAC9D,uDAAuD;IACvD,kBAAkB,EAAE,IAAI;IACxB,YAAY,EAAE,IAAI;IAClB,UAAU,EAAE,IAAI;IAChB,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;IAClB,aAAa,EAAE;QACb,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,MAAM;QACb,MAAM,EAAE;YACN,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE;YACpC,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE;YACnC,EAAE,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE;YACjD,EAAE,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE;YAC7C,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE;YACnC,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE;YACnC,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE;SACtC;KACF;CACF,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,OAAiB,OAAO,CAAC,IAAI,EAC7B,WAAuC,EAAE;IAEzC,CAAC,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAEvE,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAE9B,MAAM,WAAW,GAAG,QAAQ,CAC1B,MAAM,CAAC,CAAC,IAAI,CAAC;QACX,OAAO,EAAE,eAAe;QACxB,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;YACd,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,0BAA0B,CAAC;YACnE,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC1C,OAAO,6CAA6C,CAAC;YACvD,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC,EACF,EAAE,CACH,CAAC;IAEF,MAAM,SAAS,GACb,aAAa,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QAC9C,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE;QACtB,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;IAEzB,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC;QAClC,OAAO,EAAE,mBAAmB;QAC5B,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE;YACP;gBACE,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,yBAAyB;aAChC;YACD;gBACE,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,IAAI;gBACX,IAAI,EAAE,SAAS;aAChB;YACD;gBACE,KAAK,EAAE,WAAW;gBAClB,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,uCAAuC;aAC9C;SACF;KACF,CAAC,CAAC;IACH,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,YAAY,GAChB,gBAAgB,CAAC,MAAM,CAAC,YAAY,CAAkC,CAAC;QACvE,gBAAgB,CAAC,EAAE,CAAC;IAEtB,4EAA4E;IAC5E,MAAM,UAAU,GAAG,eAAe,CAAC,aAAa,CAAC,MAAM;SACpD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;SACxB,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,CAAC,CAAC,GAAG,CAAC,IAAI,CACR;QACE,WAAW;QACX,uBAAuB,SAAS,EAAE;QAClC,uBAAuB,YAAY,CAAC,KAAK,EAAE;QAC3C,uBAAuB,YAAY,CAAC,aAAa,qBAAqB;QACtE,wBAAwB,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc;QAC9E,uBAAuB,eAAe,CAAC,aAAa,CAAC,EAAE,KAAK,eAAe,CAAC,aAAa,CAAC,KAAK,GAAG;QAClG,uBAAuB,UAAU,EAAE;KACpC,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC;QAChC,OAAO,EAAE,2CAA2C;QACpD,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACxC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAED,oEAAoE;IACpE,oEAAoE;IACpE,kEAAkE;IAClE,CAAC,CAAC,GAAG,CAAC,IAAI,CACR,6EAA6E;QAC3E,qEAAqE;QACrE,gEAAgE,CACnE,CAAC;IACF,MAAM,UAAU,GAAG,QAAQ,CACzB,MAAM,CAAC,CAAC,IAAI,CAAC;QACX,OAAO,EAAE,cAAc;QACvB,WAAW,EAAE,iBAAiB;QAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;YACd,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,CAAC;gBAAE,OAAO,yBAAyB,CAAC;YACzC,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC,CAAC;gBACvC,OAAO,+BAA+B,CAAC;YACzC,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC,EACF,EAAE,CACH,CAAC;IACF,MAAM,aAAa,GAAG,sBAAsB,EAAE,CAAC;IAE/C,CAAC,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAE/C,sEAAsE;IACtE,kEAAkE;IAClE,6BAA6B;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAA0B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,eAAe,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QACrD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;YAAE,SAAS;QACxC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAAE,SAAS;QAC9B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,OAAO;QACL,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE;QAC/B,SAAS;QACT,aAAa,EAAE,YAAY,CAAC,aAAa;QACzC,gBAAgB,EAAE,CAAC,GAAG,YAAY,CAAC,gBAAgB,CAAC;QACpD,yDAAyD;QACzD,4DAA4D;QAC5D,0DAA0D;QAC1D,qDAAqD;QACrD,mEAAmE;QACnE,2DAA2D;QAC3D,aAAa,EAAE,QAAQ,CAAC,aAAa,IAAI,eAAe,CAAC,aAAa;QACtE,aAAa,EAAE;YACb,EAAE,EAAE,eAAe,CAAC,aAAa,CAAC,EAAE;YACpC,KAAK,EAAE,eAAe,CAAC,aAAa,CAAC,KAAK;YAC1C,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,aAAa,CAAC,MAAM;SACtE;QACD,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE;QACpC,aAAa;QACb,gBAAgB,EAAE,eAAe,CAAC,gBAAgB;QAClD,eAAe,EAAE,eAAe,CAAC,eAAe;QAChD,kBAAkB,EAAE,eAAe,CAAC,kBAAkB;QACtD,YAAY,EAAE,eAAe,CAAC,YAAY;QAC1C,UAAU,EAAE,eAAe,CAAC,UAAU;QACtC,WAAW,EAAE,eAAe,CAAC,WAAW;QACxC,WAAW,EAAE,eAAe,CAAC,WAAW;QACxC,YAAY,EAAE,eAAe,CAAC,YAAY;QAC1C,uBAAuB,EAAE,aAAa;KACU,CAAC;AACrD,CAAC"}