@c15t/cli 2.0.0-rc.0 → 2.0.0-rc.10

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 (250) hide show
  1. package/README.md +47 -18
  2. package/dist/145.mjs +7401 -0
  3. package/dist/generate-files.mjs +1771 -0
  4. package/dist/index.mjs +1 -3399
  5. package/{dist → dist-types}/actions/show-help-menu.d.ts +0 -1
  6. package/dist-types/auth/base-url.d.ts +7 -0
  7. package/{dist → dist-types}/auth/config-store.d.ts +2 -3
  8. package/{dist → dist-types}/auth/device-flow.d.ts +0 -1
  9. package/{dist → dist-types}/auth/index.d.ts +1 -1
  10. package/{dist → dist-types}/auth/types.d.ts +1 -2
  11. package/{dist → dist-types}/commands/auth/index.d.ts +0 -1
  12. package/dist-types/commands/codemods/active-ui-api.d.ts +41 -0
  13. package/dist-types/commands/codemods/add-stylesheet-imports.d.ts +54 -0
  14. package/dist-types/commands/codemods/component-renames.d.ts +41 -0
  15. package/dist-types/commands/codemods/gdpr-types-to-consent-categories.d.ts +41 -0
  16. package/dist-types/commands/codemods/ignore-geo-location-to-overrides.d.ts +41 -0
  17. package/dist-types/commands/codemods/index.d.ts +28 -0
  18. package/dist-types/commands/codemods/mode-c15t-to-hosted.d.ts +43 -0
  19. package/dist-types/commands/codemods/offline-add-policy-packs.d.ts +21 -0
  20. package/dist-types/commands/codemods/react-options-to-top-level.d.ts +41 -0
  21. package/dist-types/commands/codemods/tracking-blocker-to-network-blocker.d.ts +41 -0
  22. package/dist-types/commands/codemods/translations-to-i18n.d.ts +51 -0
  23. package/dist-types/commands/codemods/versioning.d.ts +49 -0
  24. package/{dist → dist-types}/commands/generate/index.d.ts +0 -1
  25. package/{dist → dist-types}/commands/generate/options/shared/backend-options.d.ts +0 -1
  26. package/{dist → dist-types}/commands/generate/options/shared/dev-tools.d.ts +0 -1
  27. package/{dist → dist-types}/commands/generate/options/shared/frontend-ui-options.d.ts +0 -1
  28. package/{dist → dist-types}/commands/generate/options/shared/scripts.d.ts +0 -1
  29. package/{dist → dist-types}/commands/generate/options/shared/ssr.d.ts +0 -1
  30. package/{dist → dist-types}/commands/generate/options/types.d.ts +0 -1
  31. package/{dist → dist-types}/commands/generate/options/utils/dependencies.d.ts +0 -1
  32. package/{dist → dist-types}/commands/generate/options/utils/generate-files.d.ts +2 -2
  33. package/{dist → dist-types}/commands/generate/preflight.d.ts +0 -1
  34. package/{dist → dist-types}/commands/generate/prompts/expanded-theme.d.ts +0 -1
  35. package/{dist → dist-types}/commands/generate/prompts/index.d.ts +0 -2
  36. package/{dist → dist-types}/commands/generate/prompts/mode-select.d.ts +1 -7
  37. package/{dist → dist-types}/commands/generate/prompts/scripts.d.ts +0 -1
  38. package/{dist → dist-types}/commands/generate/prompts/theme.d.ts +1 -2
  39. package/{dist → dist-types}/commands/generate/prompts/ui-style.d.ts +0 -1
  40. package/{dist → dist-types}/commands/generate/summary.d.ts +0 -1
  41. package/{dist → dist-types}/commands/generate/templates/config.d.ts +0 -1
  42. package/dist-types/commands/generate/templates/css.d.ts +10 -0
  43. package/{dist → dist-types}/commands/generate/templates/env.d.ts +0 -1
  44. package/{dist → dist-types}/commands/generate/templates/index.d.ts +0 -1
  45. package/{dist → dist-types}/commands/generate/templates/layout.d.ts +0 -1
  46. package/{dist → dist-types}/commands/generate/templates/next/app/layout.d.ts +2 -2
  47. package/{dist → dist-types}/commands/generate/templates/next/index.d.ts +0 -1
  48. package/{dist → dist-types}/commands/generate/templates/next/pages/layout.d.ts +2 -2
  49. package/{dist → dist-types}/commands/generate/templates/next-config.d.ts +1 -4
  50. package/{dist → dist-types}/commands/generate/templates/shared/components.d.ts +3 -4
  51. package/{dist → dist-types}/commands/generate/templates/shared/directory.d.ts +0 -1
  52. package/{dist → dist-types}/commands/generate/templates/shared/expanded-components.d.ts +0 -1
  53. package/{dist → dist-types}/commands/generate/templates/shared/framework-config.d.ts +0 -1
  54. package/{dist → dist-types}/commands/generate/templates/shared/layout-pipeline.d.ts +1 -1
  55. package/{dist → dist-types}/commands/generate/templates/shared/module-specifier.d.ts +0 -1
  56. package/{dist → dist-types}/commands/generate/templates/shared/options.d.ts +5 -6
  57. package/{dist → dist-types}/commands/generate/templates/shared/scripts.d.ts +0 -1
  58. package/{dist → dist-types}/commands/generate/templates/shared/server-components.d.ts +0 -1
  59. package/{dist → dist-types}/commands/index.d.ts +3 -2
  60. package/dist-types/commands/instances/index.d.ts +26 -0
  61. package/{dist → dist-types}/commands/self-host/index.d.ts +0 -1
  62. package/{dist → dist-types}/commands/self-host/migrate/ensure-backend-config.d.ts +0 -1
  63. package/{dist → dist-types}/commands/self-host/migrate/index.d.ts +0 -1
  64. package/{dist → dist-types}/commands/self-host/migrate/migrator-result.d.ts +0 -1
  65. package/{dist → dist-types}/commands/self-host/migrate/orm-result.d.ts +0 -1
  66. package/{dist → dist-types}/commands/self-host/migrate/read-config.d.ts +0 -1
  67. package/dist-types/commands/shared/stylesheets.d.ts +19 -0
  68. package/dist-types/commands/skills.d.ts +10 -0
  69. package/{dist → dist-types}/components/intro.d.ts +0 -1
  70. package/{dist → dist-types}/constants.d.ts +31 -9
  71. package/{dist → dist-types}/context/creator.d.ts +0 -1
  72. package/{dist → dist-types}/context/error-handlers.d.ts +0 -1
  73. package/{dist → dist-types}/context/file-system.d.ts +0 -1
  74. package/{dist → dist-types}/context/framework-detection.d.ts +0 -1
  75. package/{dist → dist-types}/context/package-manager-detection.d.ts +0 -1
  76. package/{dist → dist-types}/context/parser.d.ts +0 -1
  77. package/{dist → dist-types}/context/types.d.ts +3 -2
  78. package/{dist → dist-types}/context/user-interaction.d.ts +0 -1
  79. package/dist-types/control-plane/client.d.ts +56 -0
  80. package/dist-types/control-plane/index.d.ts +5 -0
  81. package/dist-types/control-plane/types.d.ts +73 -0
  82. package/{dist → dist-types}/core/context.d.ts +0 -1
  83. package/{dist → dist-types}/core/errors.d.ts +10 -16
  84. package/{dist → dist-types}/core/index.d.ts +0 -1
  85. package/{dist → dist-types}/core/logger.d.ts +0 -1
  86. package/{dist → dist-types}/core/parser.d.ts +0 -1
  87. package/dist-types/core/telemetry.d.ts +2 -0
  88. package/{dist → dist-types}/detection/framework.d.ts +0 -1
  89. package/{dist → dist-types}/detection/index.d.ts +0 -1
  90. package/{dist → dist-types}/detection/layout.d.ts +0 -1
  91. package/{dist → dist-types}/detection/package-manager.d.ts +0 -1
  92. package/{dist → dist-types}/index.d.ts +0 -1
  93. package/{dist → dist-types}/machines/generate/actions.d.ts +0 -1
  94. package/{dist → dist-types}/machines/generate/actors/dependencies.d.ts +0 -1
  95. package/{dist → dist-types}/machines/generate/actors/file-generation.d.ts +1 -2
  96. package/{dist → dist-types}/machines/generate/actors/preflight.d.ts +0 -1
  97. package/{dist → dist-types}/machines/generate/actors/prompts.d.ts +15 -13
  98. package/{dist → dist-types}/machines/generate/guards.d.ts +4 -5
  99. package/{dist → dist-types}/machines/generate/machine.d.ts +20 -28
  100. package/{dist → dist-types}/machines/generate/runner.d.ts +0 -1
  101. package/{dist → dist-types}/machines/generate/types.d.ts +6 -3
  102. package/{dist → dist-types}/machines/index.d.ts +1 -2
  103. package/{dist → dist-types}/machines/persistence.d.ts +0 -1
  104. package/{dist → dist-types}/machines/telemetry-plugin.d.ts +0 -1
  105. package/{dist → dist-types}/machines/types.d.ts +0 -1
  106. package/{dist → dist-types}/types.d.ts +13 -20
  107. package/{dist → dist-types}/utils/capitalize-first-letter.d.ts +0 -1
  108. package/{dist → dist-types}/utils/formatter.d.ts +0 -1
  109. package/{dist → dist-types}/utils/fs.d.ts +0 -1
  110. package/{dist → dist-types}/utils/index.d.ts +0 -1
  111. package/{dist → dist-types}/utils/logger.d.ts +6 -6
  112. package/{dist → dist-types}/utils/spinner.d.ts +0 -1
  113. package/{dist/core → dist-types/utils}/telemetry.d.ts +75 -32
  114. package/{dist → dist-types}/utils/validation.d.ts +2 -3
  115. package/package.json +21 -19
  116. package/readme.json +22 -8
  117. package/dist/760.mjs +0 -1720
  118. package/dist/__tests__/auth/config-store.test.d.ts +0 -2
  119. package/dist/__tests__/auth/config-store.test.d.ts.map +0 -1
  120. package/dist/__tests__/constants.test.d.ts +0 -2
  121. package/dist/__tests__/constants.test.d.ts.map +0 -1
  122. package/dist/__tests__/detection/layout.test.d.ts +0 -2
  123. package/dist/__tests__/detection/layout.test.d.ts.map +0 -1
  124. package/dist/__tests__/mocks/prompts.d.ts +0 -25
  125. package/dist/__tests__/mocks/prompts.d.ts.map +0 -1
  126. package/dist/__tests__/utils/validation.test.d.ts +0 -2
  127. package/dist/__tests__/utils/validation.test.d.ts.map +0 -1
  128. package/dist/actions/show-help-menu.d.ts.map +0 -1
  129. package/dist/auth/config-store.d.ts.map +0 -1
  130. package/dist/auth/device-flow.d.ts.map +0 -1
  131. package/dist/auth/index.d.ts.map +0 -1
  132. package/dist/auth/types.d.ts.map +0 -1
  133. package/dist/commands/auth/index.d.ts.map +0 -1
  134. package/dist/commands/generate/index.d.ts.map +0 -1
  135. package/dist/commands/generate/options/c15t-mode.d.ts +0 -27
  136. package/dist/commands/generate/options/c15t-mode.d.ts.map +0 -1
  137. package/dist/commands/generate/options/custom-mode.d.ts +0 -26
  138. package/dist/commands/generate/options/custom-mode.d.ts.map +0 -1
  139. package/dist/commands/generate/options/offline-mode.d.ts +0 -26
  140. package/dist/commands/generate/options/offline-mode.d.ts.map +0 -1
  141. package/dist/commands/generate/options/self-hosted-mode.d.ts +0 -19
  142. package/dist/commands/generate/options/self-hosted-mode.d.ts.map +0 -1
  143. package/dist/commands/generate/options/shared/backend-options.d.ts.map +0 -1
  144. package/dist/commands/generate/options/shared/dev-tools.d.ts.map +0 -1
  145. package/dist/commands/generate/options/shared/frontend-ui-options.d.ts.map +0 -1
  146. package/dist/commands/generate/options/shared/index.d.ts +0 -9
  147. package/dist/commands/generate/options/shared/index.d.ts.map +0 -1
  148. package/dist/commands/generate/options/shared/scripts.d.ts.map +0 -1
  149. package/dist/commands/generate/options/shared/ssr.d.ts.map +0 -1
  150. package/dist/commands/generate/options/types.d.ts.map +0 -1
  151. package/dist/commands/generate/options/utils/dependencies.d.ts.map +0 -1
  152. package/dist/commands/generate/options/utils/generate-files.d.ts.map +0 -1
  153. package/dist/commands/generate/preflight.d.ts.map +0 -1
  154. package/dist/commands/generate/prompts/expanded-theme.d.ts.map +0 -1
  155. package/dist/commands/generate/prompts/index.d.ts.map +0 -1
  156. package/dist/commands/generate/prompts/instance.d.ts +0 -33
  157. package/dist/commands/generate/prompts/instance.d.ts.map +0 -1
  158. package/dist/commands/generate/prompts/mode-select.d.ts.map +0 -1
  159. package/dist/commands/generate/prompts/scripts.d.ts.map +0 -1
  160. package/dist/commands/generate/prompts/theme.d.ts.map +0 -1
  161. package/dist/commands/generate/prompts/ui-style.d.ts.map +0 -1
  162. package/dist/commands/generate/summary.d.ts.map +0 -1
  163. package/dist/commands/generate/templates/config.d.ts.map +0 -1
  164. package/dist/commands/generate/templates/css.d.ts +0 -12
  165. package/dist/commands/generate/templates/css.d.ts.map +0 -1
  166. package/dist/commands/generate/templates/env.d.ts.map +0 -1
  167. package/dist/commands/generate/templates/index.d.ts.map +0 -1
  168. package/dist/commands/generate/templates/layout.d.ts.map +0 -1
  169. package/dist/commands/generate/templates/next/app/layout.d.ts.map +0 -1
  170. package/dist/commands/generate/templates/next/index.d.ts.map +0 -1
  171. package/dist/commands/generate/templates/next/pages/layout.d.ts.map +0 -1
  172. package/dist/commands/generate/templates/next-config.d.ts.map +0 -1
  173. package/dist/commands/generate/templates/shared/components.d.ts.map +0 -1
  174. package/dist/commands/generate/templates/shared/directory.d.ts.map +0 -1
  175. package/dist/commands/generate/templates/shared/expanded-components.d.ts.map +0 -1
  176. package/dist/commands/generate/templates/shared/framework-config.d.ts.map +0 -1
  177. package/dist/commands/generate/templates/shared/layout-pipeline.d.ts.map +0 -1
  178. package/dist/commands/generate/templates/shared/module-specifier.d.ts.map +0 -1
  179. package/dist/commands/generate/templates/shared/options.d.ts.map +0 -1
  180. package/dist/commands/generate/templates/shared/scripts.d.ts.map +0 -1
  181. package/dist/commands/generate/templates/shared/server-components.d.ts.map +0 -1
  182. package/dist/commands/index.d.ts.map +0 -1
  183. package/dist/commands/instances/index.d.ts +0 -22
  184. package/dist/commands/instances/index.d.ts.map +0 -1
  185. package/dist/commands/self-host/index.d.ts.map +0 -1
  186. package/dist/commands/self-host/migrate/ensure-backend-config.d.ts.map +0 -1
  187. package/dist/commands/self-host/migrate/ensure-backend-config.test.d.ts +0 -2
  188. package/dist/commands/self-host/migrate/ensure-backend-config.test.d.ts.map +0 -1
  189. package/dist/commands/self-host/migrate/index.d.ts.map +0 -1
  190. package/dist/commands/self-host/migrate/index.test.d.ts +0 -2
  191. package/dist/commands/self-host/migrate/index.test.d.ts.map +0 -1
  192. package/dist/commands/self-host/migrate/migrator-result.d.ts.map +0 -1
  193. package/dist/commands/self-host/migrate/migrator-result.test.d.ts +0 -2
  194. package/dist/commands/self-host/migrate/migrator-result.test.d.ts.map +0 -1
  195. package/dist/commands/self-host/migrate/orm-result.d.ts.map +0 -1
  196. package/dist/commands/self-host/migrate/orm-result.test.d.ts +0 -2
  197. package/dist/commands/self-host/migrate/orm-result.test.d.ts.map +0 -1
  198. package/dist/commands/self-host/migrate/read-config.d.ts.map +0 -1
  199. package/dist/commands/self-host/migrate/read-config.test.d.ts +0 -2
  200. package/dist/commands/self-host/migrate/read-config.test.d.ts.map +0 -1
  201. package/dist/components/intro.d.ts.map +0 -1
  202. package/dist/constants.d.ts.map +0 -1
  203. package/dist/context/creator.d.ts.map +0 -1
  204. package/dist/context/error-handlers.d.ts.map +0 -1
  205. package/dist/context/file-system.d.ts.map +0 -1
  206. package/dist/context/framework-detection.d.ts.map +0 -1
  207. package/dist/context/package-manager-detection.d.ts.map +0 -1
  208. package/dist/context/parser.d.ts.map +0 -1
  209. package/dist/context/types.d.ts.map +0 -1
  210. package/dist/context/user-interaction.d.ts.map +0 -1
  211. package/dist/core/context.d.ts.map +0 -1
  212. package/dist/core/errors.d.ts.map +0 -1
  213. package/dist/core/index.d.ts.map +0 -1
  214. package/dist/core/logger.d.ts.map +0 -1
  215. package/dist/core/parser.d.ts.map +0 -1
  216. package/dist/core/telemetry.d.ts.map +0 -1
  217. package/dist/detection/framework.d.ts.map +0 -1
  218. package/dist/detection/index.d.ts.map +0 -1
  219. package/dist/detection/layout.d.ts.map +0 -1
  220. package/dist/detection/package-manager.d.ts.map +0 -1
  221. package/dist/index.d.ts.map +0 -1
  222. package/dist/machines/generate/actions.d.ts.map +0 -1
  223. package/dist/machines/generate/actors/dependencies.d.ts.map +0 -1
  224. package/dist/machines/generate/actors/file-generation.d.ts.map +0 -1
  225. package/dist/machines/generate/actors/preflight.d.ts.map +0 -1
  226. package/dist/machines/generate/actors/prompts.d.ts.map +0 -1
  227. package/dist/machines/generate/guards.d.ts.map +0 -1
  228. package/dist/machines/generate/machine.d.ts.map +0 -1
  229. package/dist/machines/generate/runner.d.ts.map +0 -1
  230. package/dist/machines/generate/types.d.ts.map +0 -1
  231. package/dist/machines/index.d.ts.map +0 -1
  232. package/dist/machines/persistence.d.ts.map +0 -1
  233. package/dist/machines/telemetry-plugin.d.ts.map +0 -1
  234. package/dist/machines/types.d.ts.map +0 -1
  235. package/dist/mcp/client.d.ts +0 -61
  236. package/dist/mcp/client.d.ts.map +0 -1
  237. package/dist/mcp/index.d.ts +0 -6
  238. package/dist/mcp/index.d.ts.map +0 -1
  239. package/dist/mcp/types.d.ts +0 -84
  240. package/dist/mcp/types.d.ts.map +0 -1
  241. package/dist/types.d.ts.map +0 -1
  242. package/dist/utils/capitalize-first-letter.d.ts.map +0 -1
  243. package/dist/utils/formatter.d.ts.map +0 -1
  244. package/dist/utils/fs.d.ts.map +0 -1
  245. package/dist/utils/index.d.ts.map +0 -1
  246. package/dist/utils/logger.d.ts.map +0 -1
  247. package/dist/utils/spinner.d.ts.map +0 -1
  248. package/dist/utils/telemetry.d.ts +0 -178
  249. package/dist/utils/telemetry.d.ts.map +0 -1
  250. package/dist/utils/validation.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,3400 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import * as __rspack_external__clack_prompts_3cae1695 from "@clack/prompts";
3
- import * as __rspack_external_node_fs_promises_153e37e0 from "node:fs/promises";
4
- import * as __rspack_external_node_path_c5b9b54f from "node:path";
5
- import * as __rspack_external_picocolors from "picocolors";
6
- import "dotenv/config";
7
- import * as __rspack_external_open from "open";
8
- import * as __rspack_external_xstate from "xstate";
9
- import * as __rspack_external_node_crypto_9ba42079 from "node:crypto";
10
- import * as __rspack_external_node_os_74b4b876 from "node:os";
11
- import * as __rspack_external_posthog_node_1b07bdf4 from "posthog-node";
12
- import * as __rspack_external_node_child_process_27f17141 from "node:child_process";
13
- import * as __rspack_external_node_events_0a6aefe7 from "node:events";
14
- import * as __rspack_external__c15t_logger_04a510d4 from "@c15t/logger";
15
- import * as __rspack_external__c15t_backend_db_migrator_ebe6d5c7 from "@c15t/backend/db/migrator";
16
- import * as __rspack_external__c15t_backend_db_schema_e7c5e6a0 from "@c15t/backend/db/schema";
17
- import * as __rspack_external_c12 from "c12";
18
- import * as __rspack_external_figlet from "figlet";
19
- import * as __rspack_external_fs_extra_ce68a66b from "fs-extra";
20
- import * as __rspack_external_package_manager_detector_detect_94d6a9ae from "package-manager-detector/detect";
21
- var __webpack_modules__ = {
22
- "./src/constants.ts" (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
23
- __webpack_require__.d(__webpack_exports__, {
24
- $V: ()=>STORAGE_MODES,
25
- tl: ()=>URLS
26
- });
27
- const URLS = {
28
- CONSENT_IO: 'https://consent.io',
29
- DOCS: 'https://c15t.dev/docs',
30
- GITHUB: 'https://github.com/c15t/c15t',
31
- DISCORD: 'https://c15t.dev/discord',
32
- API_DOCS: 'https://c15t.dev/docs/api',
33
- CLI_DOCS: 'https://c15t.dev/docs/cli'
34
- };
35
- const STORAGE_MODES = {
36
- C15T: 'c15t',
37
- OFFLINE: 'offline',
38
- SELF_HOSTED: 'self-hosted',
39
- CUSTOM: 'custom'
40
- };
41
- },
42
- "./src/utils/logger.ts" (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
43
- __webpack_require__.d(__webpack_exports__, {
44
- U0: ()=>validLogLevels,
45
- $e: ()=>formatLogMessage,
46
- xw: ()=>createCliLogger
47
- });
48
- var prompts_ = __webpack_require__("@clack/prompts");
49
- var external_picocolors_ = __webpack_require__("picocolors");
50
- const validLogLevels = [
51
- 'error',
52
- 'warn',
53
- 'info',
54
- 'debug'
55
- ];
56
- const formatArgs = (args)=>{
57
- if (0 === args.length) return '';
58
- return `\n${args.map((arg)=>` - ${JSON.stringify(arg, null, 2)}`).join('\n')}`;
59
- };
60
- const formatLogMessage = (logLevel, message, args = [])=>{
61
- const messageStr = 'string' == typeof message ? message : String(message);
62
- const formattedArgs = formatArgs(args);
63
- switch(logLevel){
64
- case 'error':
65
- return `${external_picocolors_["default"].bgRed(external_picocolors_["default"].black(' error '))} ${messageStr}${formattedArgs}`;
66
- case 'warn':
67
- return `${external_picocolors_["default"].bgYellow(external_picocolors_["default"].black(' warning '))} ${messageStr}${formattedArgs}`;
68
- case 'info':
69
- return `${external_picocolors_["default"].bgGreen(external_picocolors_["default"].black(' info '))} ${messageStr}${formattedArgs}`;
70
- case 'debug':
71
- return `${external_picocolors_["default"].bgBlack(external_picocolors_["default"].white(' debug '))} ${messageStr}${formattedArgs}`;
72
- case 'success':
73
- return `${external_picocolors_["default"].bgGreen(external_picocolors_["default"].white(' success '))} ${messageStr}${formattedArgs}`;
74
- case 'failed':
75
- return `${external_picocolors_["default"].bgRed(external_picocolors_["default"].white(' failed '))} ${messageStr}${formattedArgs}`;
76
- default:
77
- {
78
- const levelStr = logLevel;
79
- return `[${levelStr.toUpperCase()}] ${messageStr}${formattedArgs}`;
80
- }
81
- }
82
- };
83
- const logMessage = (logLevel, message, ...args)=>{
84
- const formattedMessage = formatLogMessage(logLevel, message, args);
85
- switch(logLevel){
86
- case 'error':
87
- prompts_.log.error(formattedMessage);
88
- break;
89
- case 'warn':
90
- prompts_.log.warn(formattedMessage);
91
- break;
92
- case 'info':
93
- case 'debug':
94
- prompts_.log.info(formattedMessage);
95
- break;
96
- case 'success':
97
- case 'failed':
98
- prompts_.outro(formattedMessage);
99
- break;
100
- default:
101
- prompts_.log.message(formattedMessage);
102
- }
103
- };
104
- const createCliLogger = (level)=>{
105
- const baseLogger = (0, __rspack_external__c15t_logger_04a510d4.createLogger)({
106
- level,
107
- appName: 'c15t',
108
- log: (logLevel, message, ...args)=>{
109
- logMessage(logLevel, message, ...args);
110
- }
111
- });
112
- const extendedLogger = baseLogger;
113
- extendedLogger.message = (message)=>{
114
- prompts_.log.message(message);
115
- };
116
- extendedLogger.note = (message, ...args)=>{
117
- const messageStr = 'string' == typeof message ? message : String(message);
118
- const title = args.length > 0 && 'string' == typeof args[0] ? args[0] : void 0;
119
- prompts_.note(messageStr, title, {
120
- format: (line)=>line
121
- });
122
- };
123
- extendedLogger.success = (message, ...args)=>{
124
- logMessage('success', message, ...args);
125
- };
126
- extendedLogger.failed = (message, ...args)=>{
127
- logMessage('failed', message, ...args);
128
- process.exit(0);
129
- };
130
- extendedLogger.outro = (message)=>{
131
- prompts_.outro(message);
132
- };
133
- return extendedLogger;
134
- };
135
- },
136
- "@clack/prompts" (module) {
137
- module.exports = __rspack_external__clack_prompts_3cae1695;
138
- },
139
- "node:fs/promises" (module) {
140
- module.exports = __rspack_external_node_fs_promises_153e37e0;
141
- },
142
- "node:path" (module) {
143
- module.exports = __rspack_external_node_path_c5b9b54f;
144
- },
145
- picocolors (module) {
146
- module.exports = __rspack_external_picocolors;
147
- }
148
- };
149
- var __webpack_module_cache__ = {};
150
- function __webpack_require__(moduleId) {
151
- var cachedModule = __webpack_module_cache__[moduleId];
152
- if (void 0 !== cachedModule) return cachedModule.exports;
153
- var module = __webpack_module_cache__[moduleId] = {
154
- exports: {}
155
- };
156
- __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
157
- return module.exports;
158
- }
159
- __webpack_require__.m = __webpack_modules__;
160
- (()=>{
161
- __webpack_require__.d = (exports, definition)=>{
162
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
163
- enumerable: true,
164
- get: definition[key]
165
- });
166
- };
167
- })();
168
- (()=>{
169
- __webpack_require__.f = {};
170
- __webpack_require__.e = (chunkId)=>Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key)=>{
171
- __webpack_require__.f[key](chunkId, promises);
172
- return promises;
173
- }, []));
174
- })();
175
- (()=>{
176
- __webpack_require__.u = (chunkId)=>"" + chunkId + ".mjs";
177
- })();
178
- (()=>{
179
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
180
- })();
181
- (()=>{
182
- var installedChunks = {
183
- 410: 0
184
- };
185
- var installChunk = (data)=>{
186
- var __rspack_esm_ids = data.__rspack_esm_ids;
187
- var __webpack_modules__ = data.__webpack_modules__;
188
- var __rspack_esm_runtime = data.__rspack_esm_runtime;
189
- var moduleId, chunkId, i = 0;
190
- for(moduleId in __webpack_modules__)if (__webpack_require__.o(__webpack_modules__, moduleId)) __webpack_require__.m[moduleId] = __webpack_modules__[moduleId];
191
- if (__rspack_esm_runtime) __rspack_esm_runtime(__webpack_require__);
192
- for(; i < __rspack_esm_ids.length; i++){
193
- chunkId = __rspack_esm_ids[i];
194
- if (__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) installedChunks[chunkId][0]();
195
- installedChunks[__rspack_esm_ids[i]] = 0;
196
- }
197
- };
198
- __webpack_require__.f.j = function(chunkId, promises) {
199
- var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : void 0;
200
- if (0 !== installedChunkData) if (installedChunkData) promises.push(installedChunkData[1]);
201
- else {
202
- var promise = import("./" + __webpack_require__.u(chunkId)).then(installChunk, (e)=>{
203
- if (0 !== installedChunks[chunkId]) installedChunks[chunkId] = void 0;
204
- throw e;
205
- });
206
- var promise = Promise.race([
207
- promise,
208
- new Promise((resolve)=>{
209
- installedChunkData = installedChunks[chunkId] = [
210
- resolve
211
- ];
212
- })
213
- ]);
214
- promises.push(installedChunkData[1] = promise);
215
- }
216
- };
217
- })();
218
- var prompts_ = __webpack_require__("@clack/prompts");
219
- var external_picocolors_ = __webpack_require__("picocolors");
220
- function showHelpMenu(context, version, commands, flags) {
221
- const { logger } = context;
222
- logger.debug('Displaying help menu using command and flag structures.');
223
- const commandLines = commands.map((cmd)=>` ${cmd.name.padEnd(10)} ${cmd.description}`).join('\n');
224
- const optionLines = flags.map((flag)=>{
225
- const names = flag.names.join(', ');
226
- const valuePlaceholder = flag.expectsValue ? ' <value>' : '';
227
- return ` ${(names + valuePlaceholder).padEnd(20)} ${flag.description}`;
228
- }).join('\n');
229
- const helpContent = `c15t CLI version ${version}
230
-
231
- Available Commands:
232
- ${commandLines}
233
-
234
- Options:
235
- ${optionLines}
236
-
237
- Run a command directly (e.g., ${external_picocolors_["default"].cyan('c15t generate')}) or select one interactively when no command is provided.
238
-
239
- For more help, visit: https://c15t.dev`;
240
- logger.debug('Help menu content generated.');
241
- logger.note(helpContent, 'Usage');
242
- }
243
- const TELEMETRY_DISABLED_ENV = 'C15T_TELEMETRY_DISABLED';
244
- const TelemetryEventName = {
245
- CLI_INVOKED: 'cli.invoked',
246
- CLI_COMPLETED: 'cli.completed',
247
- CLI_EXITED: 'cli.exited',
248
- CLI_ENVIRONMENT_DETECTED: 'cli.environment_detected',
249
- COMMAND_EXECUTED: 'command.executed',
250
- COMMAND_SUCCEEDED: 'command.succeeded',
251
- COMMAND_FAILED: 'command.failed',
252
- COMMAND_UNKNOWN: 'command.unknown',
253
- INTERACTIVE_MENU_OPENED: 'ui.menu.opened',
254
- INTERACTIVE_MENU_EXITED: 'ui.menu.exited',
255
- CONFIG_LOADED: 'config.loaded',
256
- CONFIG_ERROR: 'config.error',
257
- CONFIG_UPDATED: 'config.updated',
258
- HELP_DISPLAYED: 'help.displayed',
259
- VERSION_DISPLAYED: 'version.displayed',
260
- ONBOARDING_STARTED: 'onboarding.started',
261
- ONBOARDING_COMPLETED: 'onboarding.completed',
262
- ONBOARDING_EXITED: 'onboarding.exited',
263
- ONBOARDING_STORAGE_MODE_SELECTED: 'onboarding.storage_mode_selected',
264
- ONBOARDING_C15T_MODE_CONFIGURED: 'onboarding.c15t_mode_configured',
265
- ONBOARDING_OFFLINE_MODE_CONFIGURED: 'onboarding.offline_mode_configured',
266
- ONBOARDING_SELF_HOSTED_CONFIGURED: 'onboarding.self_hosted_configured',
267
- ONBOARDING_CUSTOM_MODE_CONFIGURED: 'onboarding.custom_mode_configured',
268
- ONBOARDING_DEPENDENCIES_CHOICE: 'onboarding.dependencies_choice',
269
- ONBOARDING_DEPENDENCIES_INSTALLED: 'onboarding.dependencies_installed',
270
- ONBOARDING_GITHUB_STAR: 'onboarding.github_star',
271
- ERROR_OCCURRED: 'error.occurred',
272
- MIGRATION_STARTED: 'migration.started',
273
- MIGRATION_PLANNED: 'migration.planned',
274
- MIGRATION_EXECUTED: 'migration.executed',
275
- MIGRATION_COMPLETED: 'migration.completed',
276
- MIGRATION_FAILED: 'migration.failed',
277
- GENERATE_STARTED: 'generate.started',
278
- GENERATE_COMPLETED: 'generate.completed',
279
- GENERATE_FAILED: 'generate.failed',
280
- SELF_HOST_STARTED: 'self-host.started',
281
- SELF_HOST_COMPLETED: 'self-host.completed',
282
- SELF_HOST_FAILED: 'self-host.failed',
283
- CLI_STATE_TRANSITION: 'cli.state.transition',
284
- CLI_STATE_ERROR: 'cli.state.error',
285
- CLI_STATE_CANCELLED: 'cli.state.cancelled',
286
- CLI_STATE_COMPLETE: 'cli.state.complete'
287
- };
288
- class Telemetry {
289
- client = null;
290
- disabled;
291
- defaultProperties;
292
- distinctId;
293
- apiKey = 'phc_ViY5LtTmh4kqoumXZB2olPFoTz4AbbDfrogNgFi1MH3';
294
- debug;
295
- logger;
296
- constructor(options){
297
- const envDisabled = '1' === process.env[TELEMETRY_DISABLED_ENV] || process.env[TELEMETRY_DISABLED_ENV]?.toLowerCase() === 'true';
298
- const hasValidApiKey = !!(this.apiKey && '' !== this.apiKey.trim());
299
- this.disabled = options?.disabled ?? envDisabled ?? !hasValidApiKey;
300
- this.defaultProperties = options?.defaultProperties ?? {};
301
- this.logger = options?.logger;
302
- this.debug = options?.debug ?? false;
303
- this.distinctId = this.generateAnonymousId();
304
- if (this.disabled) {
305
- if (!hasValidApiKey) this.logDebug('Telemetry disabled: No API key provided');
306
- } else try {
307
- this.initClient(options?.client);
308
- } catch (error) {
309
- this.disabled = true;
310
- this.logDebug('Telemetry disabled due to initialization error:', error);
311
- }
312
- }
313
- trackEvent(eventName, properties = {}) {
314
- if (this.disabled || !this.client) {
315
- if (this.debug) this.logDebug(`Telemetry event skipped (${eventName}): Telemetry disabled or client not initialized`);
316
- return;
317
- }
318
- try {
319
- const safeProperties = {};
320
- for (const [key, value] of Object.entries(properties))if ('config' !== key && void 0 !== value) safeProperties[key] = value;
321
- if (this.debug) this.logDebug(`Sending telemetry event: ${eventName}`);
322
- this.client.capture({
323
- distinctId: this.distinctId,
324
- event: eventName,
325
- properties: {
326
- ...this.defaultProperties,
327
- ...safeProperties,
328
- timestamp: new Date().toISOString()
329
- }
330
- });
331
- this.client.flush();
332
- } catch (error) {
333
- if (this.debug) this.logDebug(`Error sending telemetry event ${eventName}:`, error);
334
- }
335
- }
336
- trackEventSync(eventName, properties = {}) {
337
- if (this.disabled || !this.client) {
338
- if (this.debug) this.logDebug('Telemetry disabled or client not initialized');
339
- return;
340
- }
341
- const safeProperties = {};
342
- for (const [key, value] of Object.entries(properties))if ('config' !== key && void 0 !== value) safeProperties[key] = value;
343
- if (this.debug) this.logDebug(`Sending telemetry event: ${eventName}`);
344
- try {
345
- this.client.capture({
346
- distinctId: this.distinctId,
347
- event: eventName,
348
- properties: {
349
- ...this.defaultProperties,
350
- ...safeProperties,
351
- timestamp: new Date().toISOString()
352
- }
353
- });
354
- this.client.flush();
355
- if (this.debug) this.logDebug(`Flushed telemetry event: ${eventName}`);
356
- } catch (error) {
357
- if (this.debug) this.logDebug(`Error sending telemetry: ${error}`);
358
- }
359
- }
360
- trackCommand(command, args = [], flags = {}) {
361
- if (this.disabled || !this.client) return;
362
- const safeFlags = {};
363
- for (const [key, value] of Object.entries(flags))if ('config' !== key && void 0 !== value) safeFlags[key] = value;
364
- this.trackEvent(TelemetryEventName.COMMAND_EXECUTED, {
365
- command,
366
- args: args.join(' '),
367
- flagsData: JSON.stringify(safeFlags)
368
- });
369
- }
370
- trackError(error, command) {
371
- if (this.disabled || !this.client) return;
372
- this.trackEvent(TelemetryEventName.ERROR_OCCURRED, {
373
- command,
374
- error: error.message,
375
- errorName: error.name,
376
- stack: 'development' === process.env.NODE_ENV ? error.stack : void 0
377
- });
378
- }
379
- disable() {
380
- this.disabled = true;
381
- }
382
- enable() {
383
- this.disabled = false;
384
- if (!this.client) this.initClient();
385
- }
386
- isDisabled() {
387
- return this.disabled;
388
- }
389
- async shutdown() {
390
- if (this.client) {
391
- await this.client.shutdown();
392
- this.client = null;
393
- }
394
- }
395
- setLogger(logger) {
396
- this.logger = logger;
397
- }
398
- logDebug(message, ...args) {
399
- if (this.logger) this.logger.debug(message, ...args);
400
- else console.debug(message, ...args);
401
- }
402
- initClient(customClient) {
403
- if (customClient) {
404
- this.client = customClient;
405
- if (this.debug) this.logDebug('Using custom PostHog client');
406
- } else {
407
- if (!this.apiKey || '' === this.apiKey.trim()) {
408
- this.disabled = true;
409
- this.logDebug('Telemetry disabled: No API key provided');
410
- return;
411
- }
412
- const startTime = Date.now();
413
- try {
414
- const clientConfig = {
415
- host: 'https://eu.i.posthog.com',
416
- flushInterval: 0,
417
- flushAt: 1,
418
- requestTimeout: 3000
419
- };
420
- if (this.debug) this.logDebug('Initializing PostHog client with config:', JSON.stringify(clientConfig));
421
- this.client = new __rspack_external_posthog_node_1b07bdf4.PostHog(this.apiKey, clientConfig);
422
- const initTime = Date.now() - startTime;
423
- if (this.debug) this.logDebug('PostHog client initialized in', initTime, 'ms');
424
- } catch (error) {
425
- this.disabled = true;
426
- const errorDetails = error instanceof Error ? {
427
- message: error.message,
428
- name: error.name,
429
- stack: error.stack
430
- } : {
431
- rawError: String(error)
432
- };
433
- if (this.debug) this.logDebug('Telemetry disabled due to initialization error:', JSON.stringify(errorDetails, null, 2));
434
- try {
435
- if (this.debug) this.logDebug('Attempting fallback PostHog initialization');
436
- this.client = new __rspack_external_posthog_node_1b07bdf4.PostHog(this.apiKey);
437
- this.disabled = false;
438
- if (this.debug) this.logDebug('PostHog client initialized using fallback method');
439
- } catch (fallbackError) {
440
- this.logDebug('Fallback initialization also failed:', fallbackError instanceof Error ? fallbackError.message : String(fallbackError));
441
- }
442
- }
443
- }
444
- }
445
- generateAnonymousId() {
446
- const machineId = __rspack_external_node_crypto_9ba42079["default"].createHash('sha256').update(__rspack_external_node_os_74b4b876["default"].hostname() + __rspack_external_node_os_74b4b876["default"].platform() + __rspack_external_node_os_74b4b876["default"].arch() + __rspack_external_node_os_74b4b876["default"].totalmem()).digest('hex');
447
- return machineId;
448
- }
449
- flushSync() {
450
- if (this.disabled || !this.client) return;
451
- try {
452
- this.client.flush();
453
- if (this.debug) this.logDebug('Manually flushed telemetry events');
454
- } catch (error) {
455
- if (this.debug) this.logDebug(`Error flushing telemetry: ${error}`);
456
- }
457
- }
458
- }
459
- function createTelemetry(options) {
460
- return new Telemetry(options);
461
- }
462
- var external_node_path_ = __webpack_require__("node:path");
463
- const DEFAULT_PERSIST_FILENAME = '.c15t-state.json';
464
- function getPersistPath(projectRoot) {
465
- return external_node_path_["default"].join(projectRoot, DEFAULT_PERSIST_FILENAME);
466
- }
467
- const NON_SERIALIZABLE_FIELDS = new Set([
468
- 'cliContext',
469
- 'spinner',
470
- '_parent',
471
- '_actorScope',
472
- '_processingStatus',
473
- '_systemId',
474
- 'logic',
475
- 'src',
476
- 'system',
477
- 'self',
478
- '_snapshot'
479
- ]);
480
- function makeSerializable(obj, seen = new WeakSet()) {
481
- if (null == obj) return obj;
482
- if ('object' != typeof obj) return obj;
483
- if (seen.has(obj)) return '[Circular]';
484
- seen.add(obj);
485
- if (Array.isArray(obj)) return obj.map((item)=>makeSerializable(item, seen));
486
- if (obj instanceof Date) return obj.toISOString();
487
- if (obj instanceof Map) return Object.fromEntries(Array.from(obj.entries()).map(([k, v])=>[
488
- k,
489
- makeSerializable(v, seen)
490
- ]));
491
- if (obj instanceof Set) return Array.from(obj).map((v)=>makeSerializable(v, seen));
492
- const result = {};
493
- for (const [key, value] of Object.entries(obj))if (!NON_SERIALIZABLE_FIELDS.has(key)) {
494
- if ('function' != typeof value && 'symbol' != typeof value) result[key] = makeSerializable(value, seen);
495
- }
496
- return result;
497
- }
498
- async function saveSnapshot(snapshot, machineId, persistPath) {
499
- const fs = await import("node:fs/promises");
500
- const serializableSnapshot = makeSerializable(snapshot);
501
- const persisted = {
502
- machineId,
503
- version: 1,
504
- savedAt: Date.now(),
505
- snapshot: serializableSnapshot
506
- };
507
- await fs.writeFile(persistPath, JSON.stringify(persisted, null, 2), 'utf-8');
508
- }
509
- async function loadSnapshot(persistPath, machineId) {
510
- const fs = await import("node:fs/promises");
511
- try {
512
- const content = await fs.readFile(persistPath, 'utf-8');
513
- const persisted = JSON.parse(content);
514
- if (persisted.machineId !== machineId) return null;
515
- const maxAge = 86400000;
516
- if (Date.now() - persisted.savedAt > maxAge) {
517
- await clearSnapshot(persistPath);
518
- return null;
519
- }
520
- return persisted.snapshot;
521
- } catch {
522
- return null;
523
- }
524
- }
525
- async function clearSnapshot(persistPath) {
526
- const fs = await import("node:fs/promises");
527
- try {
528
- await fs.unlink(persistPath);
529
- } catch {}
530
- }
531
- async function hasPersistedState(persistPath) {
532
- const fs = await import("node:fs/promises");
533
- try {
534
- await fs.access(persistPath);
535
- return true;
536
- } catch {
537
- return false;
538
- }
539
- }
540
- function createPersistenceSubscriber(machineId, persistPath, options = {}) {
541
- const { persistStates, skipStates = [
542
- 'exited',
543
- 'complete',
544
- 'error'
545
- ] } = options;
546
- return (snapshot)=>{
547
- const stateValue = String(snapshot.value);
548
- if (skipStates.includes(stateValue)) return void clearSnapshot(persistPath).catch(()=>{});
549
- if (persistStates && !persistStates.includes(stateValue)) return;
550
- saveSnapshot(snapshot, machineId, persistPath).catch((error)=>{
551
- console.error('Failed to persist state:', error);
552
- });
553
- };
554
- }
555
- function createTelemetrySubscriber(config) {
556
- const { telemetry, machineId, skipStates = [] } = config;
557
- let lastState = null;
558
- let lastStateTime = Date.now();
559
- const stateHistory = [];
560
- return (snapshot)=>{
561
- const currentState = String(snapshot.value);
562
- const now = Date.now();
563
- if (currentState === lastState) return;
564
- if (skipStates.includes(currentState)) return;
565
- if (null !== lastState) {
566
- const duration = now - lastStateTime;
567
- telemetry.trackEvent(TelemetryEventName.CLI_STATE_TRANSITION, {
568
- machineId,
569
- fromState: lastState,
570
- toState: currentState,
571
- duration
572
- });
573
- }
574
- stateHistory.push({
575
- state: currentState,
576
- timestamp: now
577
- });
578
- if ('error' === currentState || 'preflightError' === currentState) {
579
- const ctx = snapshot.context;
580
- const errors = ctx?.errors;
581
- const lastError = errors?.[errors.length - 1];
582
- telemetry.trackEvent(TelemetryEventName.CLI_STATE_ERROR, {
583
- machineId,
584
- state: currentState,
585
- error: lastError?.error?.message ?? 'Unknown error',
586
- stateHistory: stateHistory.map((e)=>e.state).join(',')
587
- });
588
- }
589
- if ('exited' === currentState || 'cancelled' === currentState) telemetry.trackEvent(TelemetryEventName.CLI_STATE_CANCELLED, {
590
- machineId,
591
- lastState: lastState ?? 'unknown',
592
- stateHistory: stateHistory.map((e)=>e.state).join(',')
593
- });
594
- if ('complete' === currentState || 'success' === currentState) {
595
- const totalDuration = now - (stateHistory[0]?.timestamp ?? now);
596
- telemetry.trackEvent(TelemetryEventName.CLI_STATE_COMPLETE, {
597
- machineId,
598
- totalDuration,
599
- statesVisited: stateHistory.length,
600
- stateHistory: stateHistory.map((e)=>e.state).join(',')
601
- });
602
- }
603
- lastState = currentState;
604
- lastStateTime = now;
605
- };
606
- }
607
- function combineSubscribers(...subscribers) {
608
- return (snapshot)=>{
609
- for (const subscriber of subscribers)try {
610
- subscriber(snapshot);
611
- } catch (error) {
612
- console.error('Subscriber error:', error);
613
- }
614
- };
615
- }
616
- function createDebugSubscriber(machineId, logger) {
617
- let lastState = null;
618
- return (snapshot)=>{
619
- const currentState = String(snapshot.value);
620
- if (currentState !== lastState) {
621
- const log = logger?.debug ?? console.debug;
622
- log(`[${machineId}] State: ${lastState ?? 'initial'} -> ${currentState}`);
623
- lastState = currentState;
624
- }
625
- };
626
- }
627
- async function runPackageManagerInstall(projectRoot, dependencies, packageManager) {
628
- if (0 === dependencies.length) return;
629
- let command;
630
- let args;
631
- switch(packageManager){
632
- case 'npm':
633
- command = 'npm';
634
- args = [
635
- 'install',
636
- ...dependencies
637
- ];
638
- break;
639
- case 'yarn':
640
- command = 'yarn';
641
- args = [
642
- 'add',
643
- ...dependencies
644
- ];
645
- break;
646
- case 'pnpm':
647
- command = 'pnpm';
648
- args = [
649
- 'add',
650
- ...dependencies
651
- ];
652
- break;
653
- case 'bun':
654
- command = 'bun';
655
- args = [
656
- 'add',
657
- ...dependencies
658
- ];
659
- break;
660
- default:
661
- throw new Error(`Unsupported package manager: ${packageManager}`);
662
- }
663
- const child = (0, __rspack_external_node_child_process_27f17141.spawn)(command, args, {
664
- cwd: projectRoot,
665
- stdio: 'inherit'
666
- });
667
- const [exitCode] = await (0, __rspack_external_node_events_0a6aefe7.once)(child, 'exit');
668
- if (0 !== exitCode) throw new Error(`Package manager exited with code ${exitCode}`);
669
- }
670
- const dependencyInstallActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
671
- const { cliContext, dependencies } = input;
672
- const { projectRoot, packageManager, logger } = cliContext;
673
- if (0 === dependencies.length) return {
674
- success: true,
675
- installedDependencies: []
676
- };
677
- logger.debug(`Installing dependencies: ${dependencies.join(', ')}`);
678
- logger.debug(`Using package manager: ${packageManager.name}`);
679
- try {
680
- await runPackageManagerInstall(projectRoot, dependencies, packageManager.name);
681
- return {
682
- success: true,
683
- installedDependencies: dependencies
684
- };
685
- } catch (error) {
686
- const errorMessage = error instanceof Error ? error.message : String(error);
687
- logger.error(`Dependency installation failed: ${errorMessage}`);
688
- return {
689
- success: false,
690
- installedDependencies: [],
691
- error: errorMessage
692
- };
693
- }
694
- });
695
- function getManualInstallCommand(dependencies, packageManager) {
696
- switch(packageManager){
697
- case 'npm':
698
- return `npm install ${dependencies.join(' ')}`;
699
- case 'yarn':
700
- return `yarn add ${dependencies.join(' ')}`;
701
- case 'pnpm':
702
- return `pnpm add ${dependencies.join(' ')}`;
703
- case 'bun':
704
- return `bun add ${dependencies.join(' ')}`;
705
- default:
706
- return `npm install ${dependencies.join(' ')}`;
707
- }
708
- }
709
- const checkDependenciesActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
710
- const { projectRoot, dependencies } = input;
711
- const fs = await import("node:fs/promises");
712
- const path = await import("node:path");
713
- const installed = [];
714
- const missing = [];
715
- try {
716
- const packageJsonPath = path.join(projectRoot, 'package.json');
717
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
718
- const allDeps = {
719
- ...packageJson.dependencies,
720
- ...packageJson.devDependencies
721
- };
722
- for (const dep of dependencies){
723
- const depName = dep.startsWith('@') ? dep : dep.split('@')[0];
724
- if (depName && depName in allDeps) installed.push(dep);
725
- else missing.push(dep);
726
- }
727
- } catch {
728
- missing.push(...dependencies);
729
- }
730
- return {
731
- installed,
732
- missing
733
- };
734
- });
735
- async function readFileForBackup(filePath) {
736
- const fs = await import("node:fs/promises");
737
- try {
738
- return await fs.readFile(filePath, 'utf-8');
739
- } catch {
740
- return null;
741
- }
742
- }
743
- async function fileExists(filePath) {
744
- const fs = await import("node:fs/promises");
745
- try {
746
- await fs.access(filePath);
747
- return true;
748
- } catch {
749
- return false;
750
- }
751
- }
752
- async function formatGeneratedFiles(projectRoot, files, logger) {
753
- const fs = await import("node:fs/promises");
754
- const { execFile } = await import("node:child_process");
755
- const { promisify } = await import("node:util");
756
- const execFileAsync = promisify(execFile);
757
- const codeFiles = files.filter((f)=>f.endsWith('.ts') || f.endsWith('.tsx') || f.endsWith('.js') || f.endsWith('.jsx'));
758
- if (0 === codeFiles.length) return;
759
- const formatters = [
760
- {
761
- bin: external_node_path_["default"].join(projectRoot, 'node_modules', '.bin', 'prettier'),
762
- args: [
763
- '--write'
764
- ]
765
- },
766
- {
767
- bin: external_node_path_["default"].join(projectRoot, 'node_modules', '.bin', 'biome'),
768
- args: [
769
- 'format',
770
- '--write'
771
- ]
772
- }
773
- ];
774
- for (const { bin, args } of formatters)try {
775
- await fs.access(bin);
776
- await execFileAsync(bin, [
777
- ...args,
778
- ...codeFiles
779
- ], {
780
- cwd: projectRoot
781
- });
782
- logger.debug(`Formatted ${codeFiles.length} files with ${external_node_path_["default"].basename(bin)}`);
783
- return;
784
- } catch {}
785
- logger.debug('No formatter found, skipping formatting');
786
- }
787
- const fileGenerationActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
788
- const { cliContext, mode, backendURL, useEnvFile, proxyNextjs, enableSSR, enableDevTools, uiStyle, expandedTheme, selectedScripts } = input;
789
- const filesCreated = [];
790
- const filesModified = [];
791
- const result = {
792
- filesCreated: [],
793
- filesModified: [],
794
- configPath: null,
795
- layoutPath: null,
796
- nextConfigPath: null,
797
- envPath: null
798
- };
799
- const { projectRoot, framework, cwd, logger } = cliContext;
800
- framework.pkg;
801
- const { generateFiles } = await __webpack_require__.e("760").then(__webpack_require__.bind(__webpack_require__, "./src/commands/generate/options/utils/generate-files.ts"));
802
- const spinnerMock = {
803
- start: (msg)=>logger.debug(`[spinner] ${msg}`),
804
- stop: (msg)=>logger.debug(`[spinner] ${msg}`),
805
- message: (msg)=>logger.debug(`[spinner] ${msg}`)
806
- };
807
- try {
808
- const potentialFiles = [
809
- external_node_path_["default"].join(projectRoot, 'c15t.config.ts'),
810
- external_node_path_["default"].join(projectRoot, '.env.local'),
811
- external_node_path_["default"].join(projectRoot, '.env.example'),
812
- external_node_path_["default"].join(projectRoot, 'next.config.ts'),
813
- external_node_path_["default"].join(projectRoot, 'next.config.js'),
814
- external_node_path_["default"].join(projectRoot, 'next.config.mjs')
815
- ];
816
- for (const filePath of potentialFiles){
817
- const exists = await fileExists(filePath);
818
- if (exists) {
819
- const backup = await readFileForBackup(filePath);
820
- if (null !== backup) filesModified.push({
821
- path: filePath,
822
- backup,
823
- type: 'modified'
824
- });
825
- }
826
- }
827
- const generateResult = await generateFiles({
828
- context: cliContext,
829
- mode: mode,
830
- spinner: spinnerMock,
831
- backendURL: backendURL ?? void 0,
832
- useEnvFile,
833
- proxyNextjs,
834
- enableSSR,
835
- enableDevTools,
836
- uiStyle,
837
- expandedTheme: expandedTheme ?? void 0,
838
- selectedScripts
839
- });
840
- if (generateResult.configPath) {
841
- result.configPath = generateResult.configPath;
842
- if (!filesModified.some((f)=>f.path === generateResult.configPath)) filesCreated.push(generateResult.configPath);
843
- }
844
- if (generateResult.layoutPath) result.layoutPath = generateResult.layoutPath;
845
- if (generateResult.nextConfigPath) {
846
- result.nextConfigPath = generateResult.nextConfigPath;
847
- if (generateResult.nextConfigCreated) filesCreated.push(generateResult.nextConfigPath);
848
- }
849
- if (useEnvFile && backendURL) {
850
- const envPath = external_node_path_["default"].join(projectRoot, '.env.local');
851
- const envExamplePath = external_node_path_["default"].join(projectRoot, '.env.example');
852
- if (!filesModified.some((f)=>f.path === envPath) && await fileExists(envPath)) filesCreated.push(envPath);
853
- result.envPath = envPath;
854
- if (!filesModified.some((f)=>f.path === envExamplePath) && await fileExists(envExamplePath)) filesCreated.push(envExamplePath);
855
- }
856
- result.filesCreated = filesCreated;
857
- result.filesModified = filesModified;
858
- const allFiles = [
859
- ...filesCreated,
860
- ...filesModified.map((f)=>f.path),
861
- generateResult.layoutPath
862
- ].filter((f)=>!!f);
863
- await formatGeneratedFiles(projectRoot, allFiles, logger);
864
- return result;
865
- } catch (error) {
866
- result.filesCreated = filesCreated;
867
- result.filesModified = filesModified;
868
- throw error;
869
- }
870
- });
871
- const rollbackActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
872
- const { filesCreated, filesModified } = input;
873
- const fs = await import("node:fs/promises");
874
- const errors = [];
875
- for (const filePath of filesCreated)try {
876
- await fs.unlink(filePath);
877
- } catch (error) {
878
- errors.push(`Failed to delete ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
879
- }
880
- for (const mod of filesModified)try {
881
- await fs.writeFile(mod.path, mod.backup, 'utf-8');
882
- } catch (error) {
883
- errors.push(`Failed to restore ${mod.path}: ${error instanceof Error ? error.message : String(error)}`);
884
- }
885
- return {
886
- success: 0 === errors.length,
887
- errors
888
- };
889
- });
890
- async function preflight_fileExists(filePath) {
891
- try {
892
- const fs = await import("node:fs/promises");
893
- await fs.access(filePath);
894
- return true;
895
- } catch {
896
- return false;
897
- }
898
- }
899
- async function checkGitStatus(projectRoot) {
900
- try {
901
- const gitDir = external_node_path_["default"].join(projectRoot, '.git');
902
- const isGitRepo = await preflight_fileExists(gitDir);
903
- if (!isGitRepo) return {
904
- name: 'Git',
905
- status: 'warn',
906
- message: 'Not a git repository',
907
- hint: 'Consider initializing git to track changes'
908
- };
909
- return {
910
- name: 'Git',
911
- status: 'pass',
912
- message: 'Git repository detected'
913
- };
914
- } catch {
915
- return {
916
- name: 'Git',
917
- status: 'warn',
918
- message: 'Could not check git status'
919
- };
920
- }
921
- }
922
- async function runPreflightChecks(context) {
923
- const { projectRoot, framework, packageManager, logger } = context;
924
- const checks = [];
925
- logger.debug('Running preflight checks...');
926
- const packageJsonPath = external_node_path_["default"].join(projectRoot, 'package.json');
927
- const hasPackageJson = await preflight_fileExists(packageJsonPath);
928
- checks.push({
929
- name: 'package.json',
930
- status: hasPackageJson ? 'pass' : 'fail',
931
- message: hasPackageJson ? 'Found package.json' : 'No package.json found',
932
- hint: hasPackageJson ? void 0 : 'Make sure you are in a JavaScript/TypeScript project'
933
- });
934
- checks.push({
935
- name: 'Framework',
936
- status: framework.framework ? 'pass' : 'warn',
937
- message: framework.framework ? `Detected ${framework.framework}` : 'No framework detected',
938
- hint: framework.framework ? void 0 : 'Will use vanilla JavaScript setup'
939
- });
940
- if ('c15t' !== framework.pkg) checks.push({
941
- name: 'React',
942
- status: framework.hasReact ? 'pass' : 'warn',
943
- message: framework.hasReact ? `Found React ${framework.reactVersion || ''}` : 'React not detected',
944
- hint: framework.hasReact ? void 0 : 'c15t works best with React'
945
- });
946
- checks.push({
947
- name: 'Package Manager',
948
- status: packageManager.name ? 'pass' : 'warn',
949
- message: packageManager.name ? `Using ${packageManager.name}` : 'No package manager detected',
950
- hint: packageManager.name ? void 0 : 'Will default to npm'
951
- });
952
- const gitCheck = await checkGitStatus(projectRoot);
953
- checks.push(gitCheck);
954
- const configPath = external_node_path_["default"].join(projectRoot, 'c15t.config.ts');
955
- const hasExistingConfig = await preflight_fileExists(configPath);
956
- checks.push({
957
- name: 'Existing config',
958
- status: hasExistingConfig ? 'warn' : 'pass',
959
- message: hasExistingConfig ? 'c15t.config.ts already exists' : 'No existing configuration',
960
- hint: hasExistingConfig ? 'Existing config will be overwritten' : void 0
961
- });
962
- const hasFailures = checks.some((c)=>'fail' === c.status);
963
- return {
964
- passed: !hasFailures,
965
- checks,
966
- projectRoot,
967
- framework: {
968
- name: framework.framework,
969
- version: framework.frameworkVersion,
970
- pkg: framework.pkg,
971
- hasReact: framework.hasReact,
972
- reactVersion: framework.reactVersion,
973
- tailwindVersion: framework.tailwindVersion
974
- },
975
- packageManager
976
- };
977
- }
978
- const preflightActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
979
- const { cliContext } = input;
980
- if (!cliContext) throw new Error('CLI context is required for preflight checks');
981
- return runPreflightChecks(cliContext);
982
- });
983
- function getStatusIcon(status) {
984
- switch(status){
985
- case 'pass':
986
- return external_picocolors_["default"].green('✓');
987
- case 'warn':
988
- return external_picocolors_["default"].yellow('⚠');
989
- case 'fail':
990
- return external_picocolors_["default"].red('✗');
991
- default:
992
- return ' ';
993
- }
994
- }
995
- function displayPreflightResults(context, checks) {
996
- const { logger } = context;
997
- const lines = [];
998
- lines.push('');
999
- lines.push(external_picocolors_["default"].bold('Pre-flight checks:'));
1000
- for (const check of checks){
1001
- const icon = getStatusIcon(check.status);
1002
- lines.push(` ${icon} ${check.message}`);
1003
- if (check.hint && 'pass' !== check.status) lines.push(` ${external_picocolors_["default"].dim(check.hint)}`);
1004
- }
1005
- lines.push('');
1006
- logger.message(lines.join('\n'));
1007
- }
1008
- function displayPreflightFailure(context, checks) {
1009
- const { logger } = context;
1010
- const lines = [];
1011
- lines.push(external_picocolors_["default"].red('Pre-flight checks failed'));
1012
- lines.push('');
1013
- const failures = checks.filter((c)=>'fail' === c.status);
1014
- for (const check of failures){
1015
- lines.push(` ${external_picocolors_["default"].red('•')} ${check.message}`);
1016
- if (check.hint) lines.push(` ${check.hint}`);
1017
- }
1018
- lines.push('');
1019
- lines.push('Please fix the issues above and try again.');
1020
- logger.message(lines.join('\n'));
1021
- }
1022
- async function getDevToolsOption({ context, handleCancel, onCancel }) {
1023
- const isReactProject = '@c15t/react' === context.framework.pkg || '@c15t/nextjs' === context.framework.pkg;
1024
- context.logger.info("c15t DevTools helps you inspect consent state, scripts, and location overrides during development.");
1025
- context.logger.info('Learn more: https://c15t.com/docs/dev-tools/overview');
1026
- const enableDevTools = await prompts_.select({
1027
- message: 'Install and enable c15t DevTools?',
1028
- options: [
1029
- {
1030
- value: true,
1031
- label: 'Yes (Recommended)',
1032
- hint: isReactProject ? 'Adds <C15TDevTools /> to generated consent components' : 'Adds createDevTools() setup to c15t.config.ts'
1033
- },
1034
- {
1035
- value: false,
1036
- label: 'No',
1037
- hint: 'Skip DevTools installation and setup'
1038
- }
1039
- ],
1040
- initialValue: true
1041
- });
1042
- const cancelled = handleCancel?.(enableDevTools) ?? prompts_.isCancel(enableDevTools);
1043
- if (cancelled) {
1044
- if (onCancel) onCancel();
1045
- context.error.handleCancel('Setup cancelled.', {
1046
- command: 'onboarding',
1047
- stage: 'dev_tools_option'
1048
- });
1049
- }
1050
- return enableDevTools;
1051
- }
1052
- async function getSSROption({ context, handleCancel, onCancel }) {
1053
- context.logger.info('SSR consent prefetch starts data loading on the server for faster banner visibility.');
1054
- context.logger.info('Tradeoff: this uses Next.js headers() and makes the route dynamic (not fully static).');
1055
- context.logger.info('On slow backends or cross-region setups, SSR can increase TTFB. Measure both TTFB and banner visibility.');
1056
- context.logger.info('Learn more: https://c15t.com/docs/frameworks/nextjs/ssr');
1057
- const enableSSR = await prompts_.select({
1058
- message: 'Enable SSR consent prefetch? (faster first banner visibility, dynamic route)',
1059
- options: [
1060
- {
1061
- value: true,
1062
- label: 'Yes (Recommended)',
1063
- hint: 'Fetch consent data on server and stream to client'
1064
- },
1065
- {
1066
- value: false,
1067
- label: 'No',
1068
- hint: 'Client-only fetch after hydration (better for fully static pages)'
1069
- }
1070
- ],
1071
- initialValue: true
1072
- });
1073
- const cancelled = handleCancel?.(enableSSR) ?? prompts_.isCancel(enableSSR);
1074
- if (cancelled) {
1075
- if (onCancel) onCancel();
1076
- context.error.handleCancel('Setup cancelled.', {
1077
- command: 'onboarding',
1078
- stage: 'ssr_option'
1079
- });
1080
- }
1081
- return enableSSR;
1082
- }
1083
- function isCancel(value) {
1084
- return prompts_.isCancel(value);
1085
- }
1086
- class PromptCancelledError extends Error {
1087
- constructor(stage){
1088
- super(`Prompt cancelled at stage: ${stage}`);
1089
- this.name = 'PromptCancelledError';
1090
- }
1091
- }
1092
- const modeSelectionActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
1093
- const result = await prompts_.select({
1094
- message: 'How would you like to store consent decisions?',
1095
- initialValue: input.initialMode ?? 'c15t',
1096
- options: [
1097
- {
1098
- value: 'c15t',
1099
- label: 'Hosted c15t (consent.io)',
1100
- hint: 'Recommended: Fully managed service'
1101
- },
1102
- {
1103
- value: 'offline',
1104
- label: 'Offline Mode',
1105
- hint: 'Store in browser, no backend needed'
1106
- },
1107
- {
1108
- value: 'self-hosted',
1109
- label: 'Self-Hosted',
1110
- hint: 'Run your own c15t backend'
1111
- },
1112
- {
1113
- value: 'custom',
1114
- label: 'Custom Implementation',
1115
- hint: 'Full control over storage logic'
1116
- }
1117
- ]
1118
- });
1119
- if (isCancel(result)) throw new PromptCancelledError('mode_selection');
1120
- return {
1121
- mode: result
1122
- };
1123
- });
1124
- const accountCreationActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
1125
- const { cliContext } = input;
1126
- const needsAccount = await prompts_.confirm({
1127
- message: 'Do you need to create a consent.io account?',
1128
- initialValue: true
1129
- });
1130
- if (isCancel(needsAccount)) throw new PromptCancelledError('account_creation');
1131
- if (!needsAccount) return {
1132
- needsAccount: false,
1133
- browserOpened: false
1134
- };
1135
- prompts_.note(`We'll open your browser to create a consent.io account and set up your instance.\nFollow these steps:\n1. Sign up for a consent.io account\n2. Create a new instance in the dashboard\n3. Configure your trusted origins (domains that can connect)\n4. Copy the provided backendURL (e.g., https://your-instance.c15t.dev)`, 'consent.io Setup');
1136
- const shouldOpen = await prompts_.confirm({
1137
- message: 'Open browser to sign up for consent.io?',
1138
- initialValue: true
1139
- });
1140
- if (isCancel(shouldOpen)) throw new PromptCancelledError('browser_open');
1141
- let browserOpened = false;
1142
- if (shouldOpen) try {
1143
- const open = (await import("open")).default;
1144
- await open('https://consent.io/dashboard/register?ref=cli');
1145
- browserOpened = true;
1146
- const enterPressed = await prompts_.text({
1147
- message: 'Press Enter once you have created your instance and have the backendURL'
1148
- });
1149
- if (isCancel(enterPressed)) throw new PromptCancelledError('url_input_wait');
1150
- } catch (error) {
1151
- if (error instanceof PromptCancelledError) throw error;
1152
- cliContext.logger.warn('Failed to open browser automatically. Please visit https://consent.io/dashboard/register manually.');
1153
- }
1154
- return {
1155
- needsAccount: true,
1156
- browserOpened
1157
- };
1158
- });
1159
- const backendURLActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
1160
- const { initialURL, isC15tMode } = input;
1161
- const placeholder = isC15tMode ? 'https://your-instance.c15t.dev' : 'https://your-backend.example.com/api/c15t';
1162
- const result = await prompts_.text({
1163
- message: isC15tMode ? 'Enter your consent.io instance URL:' : 'Enter your self-hosted backend URL:',
1164
- placeholder,
1165
- initialValue: initialURL,
1166
- validate: (value)=>{
1167
- if (!value || '' === value) return 'URL is required';
1168
- try {
1169
- const url = new URL(value);
1170
- if (isC15tMode && !url.hostname.endsWith('.c15t.dev')) return 'Please enter a valid *.c15t.dev URL';
1171
- } catch {
1172
- return 'Please enter a valid URL';
1173
- }
1174
- }
1175
- });
1176
- if (isCancel(result)) throw new PromptCancelledError('backend_url');
1177
- return {
1178
- url: result
1179
- };
1180
- });
1181
- const backendOptionsActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
1182
- const { cliContext } = input;
1183
- const useEnvFile = await prompts_.confirm({
1184
- message: 'Store the backendURL in a .env file? (Recommended, URL is public)',
1185
- initialValue: true
1186
- });
1187
- if (isCancel(useEnvFile)) throw new PromptCancelledError('env_file');
1188
- let proxyNextjs = false;
1189
- if ('@c15t/nextjs' === cliContext.framework.pkg) {
1190
- cliContext.logger.info('Learn more about Next.js Rewrites: https://nextjs.org/docs/app/api-reference/config/next-config-js/rewrites');
1191
- const proxyResult = await prompts_.confirm({
1192
- message: 'Proxy requests to your instance with Next.js Rewrites? (Recommended)',
1193
- initialValue: true
1194
- });
1195
- if (isCancel(proxyResult)) throw new PromptCancelledError('proxy_nextjs');
1196
- proxyNextjs = proxyResult;
1197
- }
1198
- return {
1199
- useEnvFile: useEnvFile,
1200
- proxyNextjs
1201
- };
1202
- });
1203
- const frontendOptionsActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
1204
- const { cliContext, hasBackend } = input;
1205
- const pkg = cliContext.framework.pkg;
1206
- let enableSSR;
1207
- let enableDevTools = false;
1208
- let uiStyle = 'prebuilt';
1209
- let expandedTheme;
1210
- if ('@c15t/nextjs' === pkg) {
1211
- if (hasBackend) {
1212
- const { existsSync } = await import("node:fs");
1213
- const { join } = await import("node:path");
1214
- const projectRoot = cliContext.projectRoot;
1215
- const isAppRouter = [
1216
- 'app/layout.tsx',
1217
- 'src/app/layout.tsx',
1218
- 'app/layout.ts',
1219
- 'src/app/layout.ts'
1220
- ].some((p)=>existsSync(join(projectRoot, p)));
1221
- if (isAppRouter) enableSSR = await getSSROption({
1222
- context: cliContext,
1223
- onCancel: ()=>{
1224
- throw new PromptCancelledError('ssr_option');
1225
- }
1226
- });
1227
- }
1228
- cliContext.logger.info('Choose how you want your consent UI components generated.');
1229
- cliContext.logger.info('Learn more: https://c15t.com/docs/frameworks/nextjs/customization');
1230
- const styleResult = await prompts_.select({
1231
- message: 'UI component style:',
1232
- options: [
1233
- {
1234
- value: 'prebuilt',
1235
- label: 'Prebuilt (Recommended)',
1236
- hint: 'Ready-to-use components'
1237
- },
1238
- {
1239
- value: 'expanded',
1240
- label: 'Compound components',
1241
- hint: 'Full customization control'
1242
- }
1243
- ],
1244
- initialValue: 'prebuilt'
1245
- });
1246
- if (isCancel(styleResult)) throw new PromptCancelledError('ui_style');
1247
- uiStyle = styleResult;
1248
- const themeResult = await prompts_.select({
1249
- message: 'Theme preset:',
1250
- options: [
1251
- {
1252
- value: 'none',
1253
- label: 'None',
1254
- hint: 'No preset styling'
1255
- },
1256
- {
1257
- value: 'minimal',
1258
- label: 'Minimal',
1259
- hint: 'Clean light theme'
1260
- },
1261
- {
1262
- value: 'dark',
1263
- label: 'Dark',
1264
- hint: 'High contrast dark mode'
1265
- },
1266
- {
1267
- value: 'tailwind',
1268
- label: 'Tailwind',
1269
- hint: 'Uses Tailwind utility classes'
1270
- }
1271
- ],
1272
- initialValue: 'none'
1273
- });
1274
- if (isCancel(themeResult)) throw new PromptCancelledError('expanded_theme');
1275
- expandedTheme = themeResult;
1276
- }
1277
- if ('@c15t/react' === pkg) {
1278
- cliContext.logger.info('Choose how you want your consent UI components generated.');
1279
- const styleResult = await prompts_.select({
1280
- message: 'UI component style:',
1281
- options: [
1282
- {
1283
- value: 'prebuilt',
1284
- label: 'Prebuilt (Recommended)',
1285
- hint: 'Ready-to-use components'
1286
- },
1287
- {
1288
- value: 'expanded',
1289
- label: 'Compound components',
1290
- hint: 'Full customization control'
1291
- }
1292
- ],
1293
- initialValue: 'prebuilt'
1294
- });
1295
- if (isCancel(styleResult)) throw new PromptCancelledError('ui_style');
1296
- uiStyle = styleResult;
1297
- const reactThemeResult = await prompts_.select({
1298
- message: 'Theme preset:',
1299
- options: [
1300
- {
1301
- value: 'none',
1302
- label: 'None',
1303
- hint: 'No preset styling'
1304
- },
1305
- {
1306
- value: 'minimal',
1307
- label: 'Minimal',
1308
- hint: 'Clean light theme'
1309
- },
1310
- {
1311
- value: 'dark',
1312
- label: 'Dark',
1313
- hint: 'High contrast dark mode'
1314
- },
1315
- {
1316
- value: 'tailwind',
1317
- label: 'Tailwind',
1318
- hint: 'Uses Tailwind utility classes'
1319
- }
1320
- ],
1321
- initialValue: 'none'
1322
- });
1323
- if (isCancel(reactThemeResult)) throw new PromptCancelledError('expanded_theme');
1324
- expandedTheme = reactThemeResult;
1325
- }
1326
- if ('c15t' === pkg || '@c15t/react' === pkg || '@c15t/nextjs' === pkg) enableDevTools = await getDevToolsOption({
1327
- context: cliContext,
1328
- onCancel: ()=>{
1329
- throw new PromptCancelledError('dev_tools_option');
1330
- }
1331
- });
1332
- return {
1333
- enableSSR,
1334
- enableDevTools,
1335
- uiStyle,
1336
- expandedTheme
1337
- };
1338
- });
1339
- const AVAILABLE_SCRIPTS = [
1340
- {
1341
- value: 'google-tag-manager',
1342
- label: 'Google Tag Manager',
1343
- hint: "GTM container script"
1344
- },
1345
- {
1346
- value: 'google-tag',
1347
- label: 'Google Tag (gtag.js)',
1348
- hint: 'Google Analytics 4'
1349
- },
1350
- {
1351
- value: 'meta-pixel',
1352
- label: 'Meta Pixel',
1353
- hint: 'Facebook/Instagram tracking'
1354
- },
1355
- {
1356
- value: 'posthog',
1357
- label: 'PostHog',
1358
- hint: 'Product analytics'
1359
- },
1360
- {
1361
- value: 'linkedin-insights',
1362
- label: 'LinkedIn Insight Tag',
1363
- hint: 'LinkedIn conversion tracking'
1364
- },
1365
- {
1366
- value: 'tiktok-pixel',
1367
- label: 'TikTok Pixel',
1368
- hint: 'TikTok ads tracking'
1369
- },
1370
- {
1371
- value: 'x-pixel',
1372
- label: 'X (Twitter) Pixel',
1373
- hint: 'X/Twitter conversion tracking'
1374
- },
1375
- {
1376
- value: 'microsoft-uet',
1377
- label: 'Microsoft UET',
1378
- hint: 'Bing Ads tracking'
1379
- },
1380
- {
1381
- value: 'databuddy',
1382
- label: 'Databuddy',
1383
- hint: 'Data collection'
1384
- }
1385
- ];
1386
- const scriptsOptionActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
1387
- const { cliContext } = input;
1388
- cliContext.logger.info("The @c15t/scripts package provides pre-configured third-party scripts with consent management.");
1389
- const addScripts = await prompts_.confirm({
1390
- message: "Add @c15t/scripts for third-party script management?",
1391
- initialValue: true
1392
- });
1393
- if (isCancel(addScripts)) throw new PromptCancelledError("scripts_option");
1394
- if (!addScripts) return {
1395
- addScripts: false,
1396
- selectedScripts: []
1397
- };
1398
- const selected = await prompts_.multiselect({
1399
- message: "Which scripts do you want to add?",
1400
- options: AVAILABLE_SCRIPTS.map((s)=>({
1401
- value: s.value,
1402
- label: s.label,
1403
- hint: s.hint
1404
- })),
1405
- required: false
1406
- });
1407
- if (isCancel(selected)) throw new PromptCancelledError("scripts_selection");
1408
- return {
1409
- addScripts: true,
1410
- selectedScripts: selected
1411
- };
1412
- });
1413
- const installConfirmActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
1414
- const { dependencies, packageManager } = input;
1415
- const depList = dependencies.join(', ');
1416
- const result = await prompts_.confirm({
1417
- message: `Install dependencies (${depList}) with ${packageManager}?`,
1418
- initialValue: true
1419
- });
1420
- if (isCancel(result)) throw new PromptCancelledError('install_confirm');
1421
- return {
1422
- confirmed: result
1423
- };
1424
- });
1425
- const githubStarActor = (0, __rspack_external_xstate.fromPromise)(async ({ input })=>{
1426
- const { cliContext } = input;
1427
- const result = await prompts_.confirm({
1428
- message: 'Would you like to star c15t on GitHub now?',
1429
- initialValue: true
1430
- });
1431
- if (isCancel(result)) return {
1432
- opened: false
1433
- };
1434
- if (result) try {
1435
- const open = (await import("open")).default;
1436
- await open('https://github.com/c15t/c15t');
1437
- cliContext.logger.success('GitHub repository opened. Thank you for your support!');
1438
- return {
1439
- opened: true
1440
- };
1441
- } catch {
1442
- cliContext.logger.info('You can star us later by visiting: https://github.com/c15t/c15t');
1443
- }
1444
- return {
1445
- opened: false
1446
- };
1447
- });
1448
- function preflightPassed({ context }) {
1449
- return context.preflightPassed;
1450
- }
1451
- function preflightFailed({ context }) {
1452
- return !context.preflightPassed;
1453
- }
1454
- function hasModeArg({ context }) {
1455
- return null !== context.modeArg;
1456
- }
1457
- function guards_isC15tMode({ context }) {
1458
- return 'c15t' === context.selectedMode;
1459
- }
1460
- function isOfflineMode({ context }) {
1461
- return 'offline' === context.selectedMode;
1462
- }
1463
- function isSelfHostedMode({ context }) {
1464
- return 'self-hosted' === context.selectedMode;
1465
- }
1466
- function isCustomMode({ context }) {
1467
- return 'custom' === context.selectedMode;
1468
- }
1469
- function modeRequiresBackend({ context }) {
1470
- return 'c15t' === context.selectedMode || 'self-hosted' === context.selectedMode;
1471
- }
1472
- function modeNoBackend({ context }) {
1473
- return 'offline' === context.selectedMode || 'custom' === context.selectedMode;
1474
- }
1475
- function isNextjs({ context }) {
1476
- return context.framework?.pkg === '@c15t/nextjs';
1477
- }
1478
- function isReact({ context }) {
1479
- return context.framework?.pkg === '@c15t/react';
1480
- }
1481
- function isCore({ context }) {
1482
- return context.framework?.pkg === 'c15t';
1483
- }
1484
- function guards_hasReact({ context }) {
1485
- return context.framework?.hasReact ?? false;
1486
- }
1487
- function hasTailwind({ context }) {
1488
- return context.framework?.tailwindVersion !== null;
1489
- }
1490
- function hasBackendURL({ context }) {
1491
- return null !== context.backendURL && '' !== context.backendURL;
1492
- }
1493
- function isExpandedUIStyle({ context }) {
1494
- return 'expanded' === context.uiStyle;
1495
- }
1496
- function installConfirmed({ context }) {
1497
- return context.installConfirmed;
1498
- }
1499
- function installSucceeded({ context }) {
1500
- return context.installSucceeded;
1501
- }
1502
- function hasFilesToRollback({ context }) {
1503
- return context.filesCreated.length > 0 || context.filesModified.length > 0;
1504
- }
1505
- function hasDependencies({ context }) {
1506
- return context.dependenciesToAdd.length > 0;
1507
- }
1508
- function hasErrors({ context }) {
1509
- return context.errors.length > 0;
1510
- }
1511
- function needsCleanup({ context }) {
1512
- return !context.cleanupDone && (context.filesCreated.length > 0 || context.filesModified.length > 0);
1513
- }
1514
- function shouldPromptSSR({ context }) {
1515
- return context.framework?.pkg === '@c15t/nextjs' && ('c15t' === context.selectedMode || 'self-hosted' === context.selectedMode);
1516
- }
1517
- function shouldPromptUIStyle({ context }) {
1518
- return context.framework?.pkg === '@c15t/nextjs' || context.framework?.pkg === '@c15t/react';
1519
- }
1520
- const guards = {
1521
- preflightPassed,
1522
- preflightFailed,
1523
- hasModeArg,
1524
- isC15tMode: guards_isC15tMode,
1525
- isOfflineMode,
1526
- isSelfHostedMode,
1527
- isCustomMode,
1528
- modeRequiresBackend,
1529
- modeNoBackend,
1530
- isNextjs,
1531
- isReact,
1532
- isCore,
1533
- hasReact: guards_hasReact,
1534
- hasTailwind,
1535
- hasBackendURL,
1536
- isExpandedUIStyle,
1537
- installConfirmed,
1538
- installSucceeded,
1539
- hasFilesToRollback,
1540
- hasDependencies,
1541
- hasErrors,
1542
- needsCleanup,
1543
- shouldPromptSSR,
1544
- shouldPromptUIStyle
1545
- };
1546
- function createInitialContext(cliContext, modeArg) {
1547
- return {
1548
- cliContext: cliContext ?? null,
1549
- projectRoot: cliContext?.projectRoot ?? '',
1550
- framework: null,
1551
- packageManager: null,
1552
- preflightPassed: false,
1553
- preflightChecks: [],
1554
- selectedMode: null,
1555
- modeArg: modeArg ?? null,
1556
- backendURL: null,
1557
- useEnvFile: true,
1558
- proxyNextjs: true,
1559
- enableSSR: false,
1560
- enableDevTools: false,
1561
- uiStyle: 'prebuilt',
1562
- expandedTheme: null,
1563
- addScripts: false,
1564
- selectedScripts: [],
1565
- filesCreated: [],
1566
- filesModified: [],
1567
- dependenciesToAdd: [],
1568
- installConfirmed: false,
1569
- installAttempted: false,
1570
- installSucceeded: false,
1571
- runMigrations: false,
1572
- cancelReason: null,
1573
- cleanupDone: false,
1574
- errors: [],
1575
- stateHistory: []
1576
- };
1577
- }
1578
- const generateMachine = (0, __rspack_external_xstate.setup)({
1579
- types: {
1580
- context: {},
1581
- events: {},
1582
- input: {}
1583
- },
1584
- guards: guards,
1585
- actors: {
1586
- preflight: preflightActor,
1587
- modeSelection: modeSelectionActor,
1588
- accountCreation: accountCreationActor,
1589
- backendURL: backendURLActor,
1590
- backendOptions: backendOptionsActor,
1591
- frontendOptions: frontendOptionsActor,
1592
- scriptsOption: scriptsOptionActor,
1593
- fileGeneration: fileGenerationActor,
1594
- checkDependencies: checkDependenciesActor,
1595
- installConfirm: installConfirmActor,
1596
- dependencyInstall: dependencyInstallActor,
1597
- rollback: rollbackActor,
1598
- githubStar: githubStarActor
1599
- }
1600
- }).createMachine({
1601
- id: 'generate',
1602
- initial: 'idle',
1603
- context: ({ input })=>createInitialContext(input.cliContext, input.modeArg),
1604
- on: {
1605
- CANCEL: {
1606
- target: '.cancelling',
1607
- actions: (0, __rspack_external_xstate.assign)({
1608
- cancelReason: ({ event })=>event.reason ?? 'User cancelled'
1609
- })
1610
- }
1611
- },
1612
- states: {
1613
- idle: {
1614
- on: {
1615
- START: 'preflight'
1616
- }
1617
- },
1618
- preflight: {
1619
- invoke: {
1620
- src: 'preflight',
1621
- input: ({ context })=>({
1622
- cliContext: context.cliContext
1623
- }),
1624
- onDone: [
1625
- {
1626
- guard: ({ event })=>event.output.passed,
1627
- target: 'modeSelection',
1628
- actions: [
1629
- (0, __rspack_external_xstate.assign)({
1630
- preflightPassed: ({ event })=>event.output.passed,
1631
- preflightChecks: ({ event })=>event.output.checks,
1632
- projectRoot: ({ event })=>event.output.projectRoot,
1633
- framework: ({ event })=>event.output.framework,
1634
- packageManager: ({ event })=>event.output.packageManager
1635
- }),
1636
- ({ context, event })=>{
1637
- if (context.cliContext) displayPreflightResults(context.cliContext, event.output.checks);
1638
- }
1639
- ]
1640
- },
1641
- {
1642
- target: 'preflightError',
1643
- actions: (0, __rspack_external_xstate.assign)({
1644
- preflightPassed: false,
1645
- preflightChecks: ({ event })=>event.output.checks
1646
- })
1647
- }
1648
- ],
1649
- onError: {
1650
- target: 'error',
1651
- actions: (0, __rspack_external_xstate.assign)({
1652
- errors: ({ context, event })=>[
1653
- ...context.errors,
1654
- {
1655
- state: 'preflight',
1656
- error: event.error,
1657
- timestamp: Date.now()
1658
- }
1659
- ]
1660
- })
1661
- }
1662
- }
1663
- },
1664
- preflightError: {
1665
- entry: ({ context })=>{
1666
- if (context.cliContext) displayPreflightFailure(context.cliContext, context.preflightChecks);
1667
- },
1668
- on: {
1669
- RETRY: {
1670
- target: 'preflight',
1671
- actions: (0, __rspack_external_xstate.assign)({
1672
- preflightPassed: false,
1673
- preflightChecks: [],
1674
- errors: []
1675
- })
1676
- }
1677
- },
1678
- after: {
1679
- 100: 'exited'
1680
- }
1681
- },
1682
- modeSelection: {
1683
- always: [
1684
- {
1685
- guard: 'hasModeArg',
1686
- target: 'routeToMode',
1687
- actions: (0, __rspack_external_xstate.assign)({
1688
- selectedMode: ({ context })=>context.modeArg
1689
- })
1690
- }
1691
- ],
1692
- invoke: {
1693
- src: 'modeSelection',
1694
- input: ()=>({}),
1695
- onDone: {
1696
- target: 'routeToMode',
1697
- actions: (0, __rspack_external_xstate.assign)({
1698
- selectedMode: ({ event })=>event.output.mode
1699
- })
1700
- },
1701
- onError: {
1702
- target: 'cancelling',
1703
- actions: (0, __rspack_external_xstate.assign)({
1704
- cancelReason: 'Mode selection cancelled'
1705
- })
1706
- }
1707
- }
1708
- },
1709
- routeToMode: {
1710
- always: [
1711
- {
1712
- guard: 'isC15tMode',
1713
- target: 'c15tMode'
1714
- },
1715
- {
1716
- guard: 'isOfflineMode',
1717
- target: 'offlineMode'
1718
- },
1719
- {
1720
- guard: 'isSelfHostedMode',
1721
- target: 'selfHostedMode'
1722
- },
1723
- {
1724
- guard: 'isCustomMode',
1725
- target: 'customMode'
1726
- },
1727
- {
1728
- target: 'customMode'
1729
- }
1730
- ]
1731
- },
1732
- c15tMode: {
1733
- initial: 'accountCreation',
1734
- states: {
1735
- accountCreation: {
1736
- invoke: {
1737
- src: 'accountCreation',
1738
- input: ({ context })=>({
1739
- cliContext: context.cliContext
1740
- }),
1741
- onDone: 'backendURL',
1742
- onError: {
1743
- target: '#generate.cancelling',
1744
- actions: (0, __rspack_external_xstate.assign)({
1745
- cancelReason: 'Account creation cancelled'
1746
- })
1747
- }
1748
- }
1749
- },
1750
- backendURL: {
1751
- invoke: {
1752
- src: 'backendURL',
1753
- input: ()=>({
1754
- isC15tMode: true
1755
- }),
1756
- onDone: {
1757
- target: '#generate.backendOptions',
1758
- actions: (0, __rspack_external_xstate.assign)({
1759
- backendURL: ({ event })=>event.output.url
1760
- })
1761
- },
1762
- onError: {
1763
- target: '#generate.cancelling',
1764
- actions: (0, __rspack_external_xstate.assign)({
1765
- cancelReason: 'Backend URL entry cancelled'
1766
- })
1767
- }
1768
- }
1769
- }
1770
- }
1771
- },
1772
- offlineMode: {
1773
- always: 'frontendOptions'
1774
- },
1775
- selfHostedMode: {
1776
- invoke: {
1777
- src: 'backendURL',
1778
- input: ()=>({
1779
- isC15tMode: false
1780
- }),
1781
- onDone: {
1782
- target: 'backendOptions',
1783
- actions: (0, __rspack_external_xstate.assign)({
1784
- backendURL: ({ event })=>event.output.url
1785
- })
1786
- },
1787
- onError: {
1788
- target: 'cancelling',
1789
- actions: (0, __rspack_external_xstate.assign)({
1790
- cancelReason: 'Backend URL entry cancelled'
1791
- })
1792
- }
1793
- }
1794
- },
1795
- customMode: {
1796
- always: 'frontendOptions'
1797
- },
1798
- backendOptions: {
1799
- invoke: {
1800
- src: 'backendOptions',
1801
- input: ({ context })=>({
1802
- cliContext: context.cliContext,
1803
- backendURL: context.backendURL
1804
- }),
1805
- onDone: {
1806
- target: 'frontendOptions',
1807
- actions: (0, __rspack_external_xstate.assign)({
1808
- useEnvFile: ({ event })=>event.output.useEnvFile,
1809
- proxyNextjs: ({ event })=>event.output.proxyNextjs
1810
- })
1811
- },
1812
- onError: {
1813
- target: 'cancelling',
1814
- actions: (0, __rspack_external_xstate.assign)({
1815
- cancelReason: 'Backend options cancelled'
1816
- })
1817
- }
1818
- }
1819
- },
1820
- frontendOptions: {
1821
- invoke: {
1822
- src: 'frontendOptions',
1823
- input: ({ context })=>({
1824
- cliContext: context.cliContext,
1825
- hasBackend: 'c15t' === context.selectedMode || 'self-hosted' === context.selectedMode
1826
- }),
1827
- onDone: {
1828
- target: "scriptsOptions",
1829
- actions: (0, __rspack_external_xstate.assign)({
1830
- enableSSR: ({ event, context })=>event.output.enableSSR ?? context.enableSSR,
1831
- enableDevTools: ({ event, context })=>event.output.enableDevTools ?? context.enableDevTools,
1832
- uiStyle: ({ event })=>event.output.uiStyle,
1833
- expandedTheme: ({ event })=>event.output.expandedTheme ?? null
1834
- })
1835
- },
1836
- onError: {
1837
- target: 'cancelling',
1838
- actions: (0, __rspack_external_xstate.assign)({
1839
- cancelReason: 'Frontend options cancelled'
1840
- })
1841
- }
1842
- }
1843
- },
1844
- scriptsOptions: {
1845
- invoke: {
1846
- src: "scriptsOption",
1847
- input: ({ context })=>({
1848
- cliContext: context.cliContext
1849
- }),
1850
- onDone: {
1851
- target: 'fileGeneration',
1852
- actions: (0, __rspack_external_xstate.assign)({
1853
- addScripts: ({ event })=>event.output.addScripts,
1854
- selectedScripts: ({ event })=>event.output.selectedScripts ?? [],
1855
- dependenciesToAdd: ({ context, event })=>{
1856
- const deps = [
1857
- context.framework?.pkg ?? 'c15t'
1858
- ];
1859
- if (event.output.addScripts) deps.push("@c15t/scripts");
1860
- if (context.enableDevTools) deps.push('@c15t/dev-tools');
1861
- return deps;
1862
- }
1863
- })
1864
- },
1865
- onError: {
1866
- target: 'cancelling',
1867
- actions: (0, __rspack_external_xstate.assign)({
1868
- cancelReason: 'Scripts option cancelled'
1869
- })
1870
- }
1871
- }
1872
- },
1873
- fileGeneration: {
1874
- invoke: {
1875
- src: 'fileGeneration',
1876
- input: ({ context })=>({
1877
- cliContext: context.cliContext,
1878
- mode: context.selectedMode,
1879
- backendURL: context.backendURL,
1880
- useEnvFile: context.useEnvFile,
1881
- proxyNextjs: context.proxyNextjs,
1882
- enableSSR: context.enableSSR,
1883
- enableDevTools: context.enableDevTools,
1884
- uiStyle: context.uiStyle,
1885
- expandedTheme: context.expandedTheme,
1886
- selectedScripts: context.selectedScripts
1887
- }),
1888
- onDone: {
1889
- target: 'dependencyCheck',
1890
- actions: (0, __rspack_external_xstate.assign)({
1891
- filesCreated: ({ event })=>event.output.filesCreated,
1892
- filesModified: ({ event })=>event.output.filesModified
1893
- })
1894
- },
1895
- onError: {
1896
- target: 'error',
1897
- actions: (0, __rspack_external_xstate.assign)({
1898
- errors: ({ context, event })=>[
1899
- ...context.errors,
1900
- {
1901
- state: 'fileGeneration',
1902
- error: event.error,
1903
- timestamp: Date.now()
1904
- }
1905
- ]
1906
- })
1907
- }
1908
- }
1909
- },
1910
- dependencyCheck: {
1911
- invoke: {
1912
- src: 'checkDependencies',
1913
- input: ({ context })=>({
1914
- projectRoot: context.cliContext.projectRoot,
1915
- dependencies: context.dependenciesToAdd
1916
- }),
1917
- onDone: {
1918
- target: 'dependencyConfirm',
1919
- actions: (0, __rspack_external_xstate.assign)({
1920
- dependenciesToAdd: ({ event })=>event.output.missing
1921
- })
1922
- },
1923
- onError: {
1924
- target: 'dependencyConfirm'
1925
- }
1926
- }
1927
- },
1928
- dependencyConfirm: {
1929
- always: [
1930
- {
1931
- guard: ({ context })=>0 === context.dependenciesToAdd.length,
1932
- target: 'summary'
1933
- }
1934
- ],
1935
- invoke: {
1936
- src: 'installConfirm',
1937
- input: ({ context })=>({
1938
- dependencies: context.dependenciesToAdd,
1939
- packageManager: context.packageManager?.name ?? 'npm'
1940
- }),
1941
- onDone: [
1942
- {
1943
- guard: ({ event })=>event.output.confirmed,
1944
- target: 'dependencyInstall',
1945
- actions: (0, __rspack_external_xstate.assign)({
1946
- installConfirmed: true
1947
- })
1948
- },
1949
- {
1950
- target: 'summary',
1951
- actions: (0, __rspack_external_xstate.assign)({
1952
- installConfirmed: false
1953
- })
1954
- }
1955
- ],
1956
- onError: {
1957
- target: 'summary',
1958
- actions: (0, __rspack_external_xstate.assign)({
1959
- installConfirmed: false
1960
- })
1961
- }
1962
- }
1963
- },
1964
- dependencyInstall: {
1965
- invoke: {
1966
- src: 'dependencyInstall',
1967
- input: ({ context })=>({
1968
- cliContext: context.cliContext,
1969
- dependencies: context.dependenciesToAdd
1970
- }),
1971
- onDone: {
1972
- target: 'summary',
1973
- actions: (0, __rspack_external_xstate.assign)({
1974
- installAttempted: true,
1975
- installSucceeded: ({ event })=>event.output.success
1976
- })
1977
- },
1978
- onError: {
1979
- target: 'summary',
1980
- actions: (0, __rspack_external_xstate.assign)({
1981
- installAttempted: true,
1982
- installSucceeded: false
1983
- })
1984
- }
1985
- }
1986
- },
1987
- summary: {
1988
- entry: ({ context })=>{
1989
- if (!context.cliContext) return;
1990
- const { logger, packageManager } = context.cliContext;
1991
- if ('self-hosted' === context.selectedMode) {
1992
- logger.info('Setup your backend with the c15t docs:');
1993
- logger.info('https://c15t.com/docs/self-host/v2');
1994
- } else if ('custom' === context.selectedMode) logger.info('Configuration Complete! Implement your custom endpoint handlers.');
1995
- if (context.installConfirmed && !context.installSucceeded) logger.warn('Dependency installation failed. Please check errors and install manually.');
1996
- else if (!context.installConfirmed && context.dependenciesToAdd.length > 0) {
1997
- const pmCommand = getManualInstallCommand(context.dependenciesToAdd, packageManager.name);
1998
- logger.warn(`Run ${pmCommand} to install required dependencies.`);
1999
- }
2000
- },
2001
- after: {
2002
- 100: 'githubStar'
2003
- }
2004
- },
2005
- githubStar: {
2006
- invoke: {
2007
- src: 'githubStar',
2008
- input: ({ context })=>({
2009
- cliContext: context.cliContext
2010
- }),
2011
- onDone: 'complete',
2012
- onError: 'complete'
2013
- }
2014
- },
2015
- complete: {
2016
- entry: ({ context })=>{
2017
- context.cliContext?.logger.success('Setup completed successfully!');
2018
- },
2019
- type: 'final'
2020
- },
2021
- error: {
2022
- entry: ({ context })=>{
2023
- const lastError = context.errors[context.errors.length - 1];
2024
- context.cliContext?.logger.error(`Error: ${lastError?.error?.message ?? 'Unknown error'}`);
2025
- },
2026
- always: [
2027
- {
2028
- guard: 'hasFilesToRollback',
2029
- target: 'rollback'
2030
- },
2031
- {
2032
- target: 'exited'
2033
- }
2034
- ]
2035
- },
2036
- cancelling: {
2037
- entry: ({ context })=>{
2038
- context.cliContext?.logger.info(context.cancelReason ?? 'Configuration cancelled.');
2039
- },
2040
- always: [
2041
- {
2042
- guard: 'hasFilesToRollback',
2043
- target: 'rollback'
2044
- },
2045
- {
2046
- target: 'exited'
2047
- }
2048
- ]
2049
- },
2050
- rollback: {
2051
- invoke: {
2052
- src: 'rollback',
2053
- input: ({ context })=>({
2054
- filesCreated: context.filesCreated,
2055
- filesModified: context.filesModified
2056
- }),
2057
- onDone: {
2058
- target: 'exited',
2059
- actions: (0, __rspack_external_xstate.assign)({
2060
- filesCreated: [],
2061
- filesModified: [],
2062
- cleanupDone: true
2063
- })
2064
- },
2065
- onError: {
2066
- target: 'exited',
2067
- actions: (0, __rspack_external_xstate.assign)({
2068
- cleanupDone: true
2069
- })
2070
- }
2071
- }
2072
- },
2073
- exited: {
2074
- type: 'final'
2075
- }
2076
- }
2077
- });
2078
- async function runGenerateMachine(options) {
2079
- const { context: cliContext, modeArg, resume = false, debug = false, persist = true } = options;
2080
- const { logger, telemetry } = cliContext;
2081
- const startTime = Date.now();
2082
- const persistPath = getPersistPath(cliContext.projectRoot);
2083
- const machineId = 'generate';
2084
- let snapshot;
2085
- if (resume) {
2086
- const hasPersisted = await hasPersistedState(persistPath);
2087
- if (hasPersisted) {
2088
- snapshot = await loadSnapshot(persistPath, machineId);
2089
- if (snapshot) logger.info('Resuming from previous state...');
2090
- }
2091
- }
2092
- const actor = (0, __rspack_external_xstate.createActor)(generateMachine, {
2093
- input: {
2094
- cliContext,
2095
- modeArg
2096
- },
2097
- ...snapshot ? {
2098
- snapshot: snapshot
2099
- } : {}
2100
- });
2101
- const subscribers = [];
2102
- subscribers.push(createTelemetrySubscriber({
2103
- telemetry,
2104
- machineId,
2105
- skipStates: [
2106
- 'routeToMode'
2107
- ]
2108
- }));
2109
- if (debug) subscribers.push(createDebugSubscriber(machineId, logger));
2110
- if (persist) subscribers.push(createPersistenceSubscriber(machineId, persistPath));
2111
- const combinedSubscriber = combineSubscribers(...subscribers);
2112
- actor.subscribe((snapshot)=>combinedSubscriber(snapshot));
2113
- telemetry.trackEvent(TelemetryEventName.ONBOARDING_STARTED, {
2114
- resumed: resume && void 0 !== snapshot
2115
- });
2116
- telemetry.flushSync();
2117
- actor.start();
2118
- if (!snapshot) actor.send({
2119
- type: 'START'
2120
- });
2121
- return new Promise((resolve)=>{
2122
- actor.subscribe({
2123
- complete: ()=>{
2124
- const finalSnapshot = actor.getSnapshot();
2125
- const finalContext = finalSnapshot.context;
2126
- const finalState = String(finalSnapshot.value);
2127
- const duration = Date.now() - startTime;
2128
- clearSnapshot(persistPath).catch(()=>{});
2129
- const success = 'complete' === finalState || 'done' === finalSnapshot.status;
2130
- telemetry.trackEvent(TelemetryEventName.ONBOARDING_COMPLETED, {
2131
- success,
2132
- selectedMode: finalContext.selectedMode ?? void 0,
2133
- installDependencies: finalContext.installSucceeded,
2134
- duration,
2135
- finalState
2136
- });
2137
- resolve({
2138
- success,
2139
- context: finalContext,
2140
- finalState,
2141
- duration,
2142
- errors: finalContext.errors
2143
- });
2144
- }
2145
- });
2146
- });
2147
- }
2148
- async function generateAction(context) {
2149
- const { logger, commandArgs, flags } = context;
2150
- const modeArg = commandArgs[0];
2151
- const resume = true === flags.resume;
2152
- const debug = true === flags.debug || 'debug' === flags.logger;
2153
- logger.debug('Starting generate command with state machine...');
2154
- logger.debug(`Mode arg: ${modeArg}`);
2155
- logger.debug(`Resume: ${resume}`);
2156
- try {
2157
- const result = await runGenerateMachine({
2158
- context,
2159
- modeArg,
2160
- resume,
2161
- debug,
2162
- persist: true
2163
- });
2164
- if (!result.success) {
2165
- if (result.errors.length > 0) process.exitCode = 1;
2166
- }
2167
- } catch (error) {
2168
- logger.error(`Generate command failed: ${error instanceof Error ? error.message : String(error)}`);
2169
- process.exitCode = 1;
2170
- }
2171
- }
2172
- async function generate(context, mode) {
2173
- if (mode) context.commandArgs = [
2174
- mode
2175
- ];
2176
- return generateAction(context);
2177
- }
2178
- var utils_logger = __webpack_require__("./src/utils/logger.ts");
2179
- async function addAndInstallDependenciesViaPM(projectRoot, dependencies, packageManager) {
2180
- if (0 === dependencies.length) return;
2181
- let command = '';
2182
- let args = [];
2183
- switch(packageManager){
2184
- case 'npm':
2185
- command = 'npm';
2186
- args = [
2187
- 'install',
2188
- ...dependencies
2189
- ];
2190
- break;
2191
- case 'yarn':
2192
- command = 'yarn';
2193
- args = [
2194
- 'add',
2195
- ...dependencies
2196
- ];
2197
- break;
2198
- case 'pnpm':
2199
- command = 'pnpm';
2200
- args = [
2201
- 'add',
2202
- ...dependencies
2203
- ];
2204
- break;
2205
- case 'bun':
2206
- command = 'bun';
2207
- args = [
2208
- 'add',
2209
- ...dependencies
2210
- ];
2211
- break;
2212
- default:
2213
- throw new Error(`Unsupported package manager for dependency addition: ${packageManager}`);
2214
- }
2215
- const child = (0, __rspack_external_node_child_process_27f17141.spawn)(command, args, {
2216
- cwd: projectRoot,
2217
- stdio: 'inherit'
2218
- });
2219
- await (0, __rspack_external_node_events_0a6aefe7.once)(child, 'exit');
2220
- }
2221
- function dependencies_getManualInstallCommand(dependencies, packageManager) {
2222
- switch(packageManager){
2223
- case 'npm':
2224
- return `npm install ${dependencies.join(' ')}`;
2225
- case 'yarn':
2226
- return `yarn add ${dependencies.join(' ')}`;
2227
- case 'pnpm':
2228
- return `pnpm add ${dependencies.join(' ')}`;
2229
- case 'bun':
2230
- return `bun add ${dependencies.join(' ')}`;
2231
- default:
2232
- return `npm install ${dependencies.join(' ')}`;
2233
- }
2234
- }
2235
- async function installDependencies({ context, dependenciesToAdd, handleCancel, autoInstall = false }) {
2236
- const { telemetry, logger } = context;
2237
- const s = prompts_.spinner();
2238
- if (0 === dependenciesToAdd.length) return {
2239
- installDepsConfirmed: false,
2240
- ranInstall: false
2241
- };
2242
- const depsString = dependenciesToAdd.map((d)=>external_picocolors_["default"].cyan(d)).join(', ');
2243
- if (!autoInstall) {
2244
- const addDepsSelection = await prompts_.confirm({
2245
- message: `Add required dependencies using ${external_picocolors_["default"].cyan(context.packageManager.name)}? (${depsString})`,
2246
- initialValue: true
2247
- });
2248
- if (handleCancel?.(addDepsSelection)) return {
2249
- installDepsConfirmed: false,
2250
- ranInstall: false
2251
- };
2252
- if (!addDepsSelection) return {
2253
- installDepsConfirmed: false,
2254
- ranInstall: false
2255
- };
2256
- }
2257
- s.start(`Running ${external_picocolors_["default"].cyan(context.packageManager.name)} to add and install dependencies... (this might take a moment)`);
2258
- try {
2259
- await addAndInstallDependenciesViaPM(context.projectRoot, dependenciesToAdd, context.packageManager.name);
2260
- s.stop(`✅ Dependencies installed: ${dependenciesToAdd.map((d)=>external_picocolors_["default"].cyan(d)).join(', ')}`);
2261
- telemetry.trackEvent(TelemetryEventName.ONBOARDING_DEPENDENCIES_INSTALLED, {
2262
- success: true,
2263
- dependencies: dependenciesToAdd.join(','),
2264
- packageManager: context.packageManager.name
2265
- });
2266
- return {
2267
- installDepsConfirmed: true,
2268
- ranInstall: true
2269
- };
2270
- } catch (installError) {
2271
- s.stop(external_picocolors_["default"].yellow('⚠️ Dependency installation failed.'));
2272
- logger.error('Installation Error:', installError);
2273
- telemetry.trackEvent(TelemetryEventName.ONBOARDING_DEPENDENCIES_INSTALLED, {
2274
- success: false,
2275
- error: installError instanceof Error ? installError.message : String(installError),
2276
- dependencies: dependenciesToAdd.join(','),
2277
- packageManager: context.packageManager.name
2278
- });
2279
- const pmCommand = dependencies_getManualInstallCommand(dependenciesToAdd, context.packageManager.name);
2280
- logger.info(`Please try running '${pmCommand}' manually in ${external_picocolors_["default"].cyan(external_node_path_["default"].relative(context.cwd, context.projectRoot))}.`);
2281
- return {
2282
- installDepsConfirmed: true,
2283
- ranInstall: false
2284
- };
2285
- }
2286
- }
2287
- var promises_ = __webpack_require__("node:fs/promises");
2288
- const ADAPTER_LABELS = {
2289
- kyselyAdapter: 'kysely',
2290
- drizzleAdapter: 'drizzle',
2291
- prismaAdapter: 'prisma',
2292
- typeormAdapter: 'typeorm',
2293
- mongoAdapter: 'mongo'
2294
- };
2295
- const PROVIDERS_BY_ADAPTER = {
2296
- kyselyAdapter: [
2297
- {
2298
- label: 'PostgreSQL',
2299
- value: 'postgresql'
2300
- },
2301
- {
2302
- label: 'MySQL',
2303
- value: 'mysql'
2304
- },
2305
- {
2306
- label: 'SQLite',
2307
- value: 'sqlite'
2308
- },
2309
- {
2310
- label: 'CockroachDB',
2311
- value: 'cockroachdb'
2312
- },
2313
- {
2314
- label: 'Microsoft SQL Server',
2315
- value: 'mssql'
2316
- }
2317
- ],
2318
- drizzleAdapter: [
2319
- {
2320
- label: 'PostgreSQL',
2321
- value: 'postgresql'
2322
- },
2323
- {
2324
- label: 'MySQL',
2325
- value: 'mysql'
2326
- },
2327
- {
2328
- label: 'SQLite',
2329
- value: 'sqlite'
2330
- }
2331
- ],
2332
- prismaAdapter: [
2333
- {
2334
- label: 'PostgreSQL',
2335
- value: 'postgresql'
2336
- },
2337
- {
2338
- label: 'MySQL',
2339
- value: 'mysql'
2340
- },
2341
- {
2342
- label: 'SQLite',
2343
- value: 'sqlite'
2344
- },
2345
- {
2346
- label: 'MongoDB',
2347
- value: 'mongodb'
2348
- }
2349
- ],
2350
- typeormAdapter: [
2351
- {
2352
- label: 'PostgreSQL',
2353
- value: 'postgresql'
2354
- },
2355
- {
2356
- label: 'MySQL',
2357
- value: 'mysql'
2358
- },
2359
- {
2360
- label: 'SQLite',
2361
- value: 'sqlite'
2362
- },
2363
- {
2364
- label: 'SQL Server',
2365
- value: 'mssql'
2366
- }
2367
- ],
2368
- mongoAdapter: [
2369
- {
2370
- label: 'MongoDB',
2371
- value: 'mongodb'
2372
- }
2373
- ]
2374
- };
2375
- class Cancelled extends Error {
2376
- stage;
2377
- constructor(stage){
2378
- super('Operation cancelled.');
2379
- this.stage = stage;
2380
- }
2381
- }
2382
- const CONFIG_BUILDERS = {
2383
- kyselyAdapter: (provider)=>`kyselyAdapter({ provider: '${provider}', db })`,
2384
- drizzleAdapter: (provider)=>`drizzleAdapter({ provider: '${provider}', db })`,
2385
- prismaAdapter: (provider)=>`prismaAdapter({ provider: '${provider}', prisma })`,
2386
- typeormAdapter: (provider)=>`typeormAdapter({ provider: '${provider}', source })`,
2387
- mongoAdapter: ()=>'mongoAdapter({ client })'
2388
- };
2389
- async function pathExists(filePath) {
2390
- try {
2391
- await promises_["default"].access(filePath);
2392
- return true;
2393
- } catch {
2394
- return false;
2395
- }
2396
- }
2397
- function buildDatabaseConfig(adapter, provider, connection) {
2398
- const builder = CONFIG_BUILDERS[adapter];
2399
- return builder(provider, connection);
2400
- }
2401
- function buildKyselyPrelude(provider, connection) {
2402
- const connExpr = connection.useEnv ? `process.env.${connection.envVar || 'DATABASE_URL'}!` : `"${connection.value || ''}"`;
2403
- if ('postgresql' === provider || 'cockroachdb' === provider) return {
2404
- imports: "import { Kysely, PostgresDialect } from 'kysely';\nimport { Pool } from 'pg';",
2405
- prelude: `const db = new Kysely({\n\tdialect: new PostgresDialect({\n\t\tpool: new Pool({ connectionString: ${connExpr} }),\n\t}),\n});`
2406
- };
2407
- if ('mysql' === provider) return {
2408
- imports: "import { Kysely, MysqlDialect } from 'kysely';\nimport mysql from 'mysql2/promise';",
2409
- prelude: `const db = new Kysely({\n\tdialect: new MysqlDialect({\n\t\tpool: mysql.createPool(${connExpr}),\n\t}),\n});`
2410
- };
2411
- if ('mssql' === provider) return {
2412
- imports: "import { Kysely, MssqlDialect } from 'kysely';\nimport mssql from 'mssql';",
2413
- prelude: `const db = new Kysely({\n\tdialect: new MssqlDialect({\n\t\tpool: new mssql.ConnectionPool(${connExpr}),\n\t}),\n});`
2414
- };
2415
- return {
2416
- imports: '',
2417
- prelude: ''
2418
- };
2419
- }
2420
- function buildSqliteKyselyPrelude(file) {
2421
- return {
2422
- imports: "import { Kysely, SqliteDialect } from 'kysely';\nimport Database from 'better-sqlite3';",
2423
- prelude: `const db = new Kysely({\n\tdialect: new SqliteDialect({\n\t\tdatabase: new Database("${file}"),\n\t}),\n});`
2424
- };
2425
- }
2426
- function buildDrizzlePrelude(provider, connection) {
2427
- const connExpr = connection.useEnv ? `process.env.${connection.envVar || 'DATABASE_URL'}!` : `"${connection.value || ''}"`;
2428
- if ('postgresql' === provider) return {
2429
- imports: "import { drizzle } from 'drizzle-orm/node-postgres';\nimport { Pool } from 'pg';",
2430
- prelude: `const db = drizzle(new Pool({ connectionString: ${connExpr} }));`
2431
- };
2432
- if ('mysql' === provider) return {
2433
- imports: "import { drizzle } from 'drizzle-orm/mysql2';\nimport mysql from 'mysql2/promise';",
2434
- prelude: `const db = drizzle(await mysql.createConnection(${connExpr}));`
2435
- };
2436
- if ('sqlite' === provider) {
2437
- const file = connection.sqliteFile || './db.sqlite';
2438
- return {
2439
- imports: "import { drizzle } from 'drizzle-orm/better-sqlite3';\nimport Database from 'better-sqlite3';",
2440
- prelude: `const db = drizzle(new Database("${file}"));`
2441
- };
2442
- }
2443
- return {
2444
- imports: '',
2445
- prelude: ''
2446
- };
2447
- }
2448
- function buildPrismaPrelude(_provider, _connection) {
2449
- return {
2450
- imports: "import { PrismaClient } from '@prisma/client';",
2451
- prelude: 'const prisma = new PrismaClient();'
2452
- };
2453
- }
2454
- function buildTypeormPrelude(provider, connection) {
2455
- const connExpr = connection.useEnv ? `process.env.${connection.envVar || 'DATABASE_URL'}!` : `"${connection.value || ''}"`;
2456
- if ('sqlite' === provider) {
2457
- const file = connection.sqliteFile || './db.sqlite';
2458
- return {
2459
- imports: "import { DataSource } from 'typeorm';",
2460
- prelude: `const source = new DataSource({ type: 'sqlite', database: "${file}" });`
2461
- };
2462
- }
2463
- const typeMap = {
2464
- postgresql: 'postgres',
2465
- mysql: 'mysql',
2466
- mssql: 'mssql'
2467
- };
2468
- return {
2469
- imports: "import { DataSource } from 'typeorm';",
2470
- prelude: `const source = new DataSource({ type: '${typeMap[String(provider)]}', url: ${connExpr} });`
2471
- };
2472
- }
2473
- function buildMongoPrelude(connection) {
2474
- const urlExpr = connection.useEnv ? `process.env.${connection.envVar || 'MONGODB_URI'}!` : `"${connection.value || ''}"`;
2475
- return {
2476
- imports: "import { MongoClient } from 'mongodb';",
2477
- prelude: `const client = new MongoClient(${urlExpr});`
2478
- };
2479
- }
2480
- function buildFileContent(adapter, provider, dbConfig, connection) {
2481
- const adapterPath = 'mongoAdapter' === adapter ? 'mongo' : adapter.replace('Adapter', '');
2482
- const importAdapter = `import { ${adapter} } from '@c15t/backend/db/adapters/${adapterPath}';`;
2483
- let extras = {
2484
- imports: '',
2485
- prelude: ''
2486
- };
2487
- if ('kyselyAdapter' === adapter) if ('sqlite' === provider) {
2488
- const file = connection.sqliteFile || './db.sqlite';
2489
- extras = buildSqliteKyselyPrelude(file);
2490
- } else extras = buildKyselyPrelude(provider, connection);
2491
- else if ('drizzleAdapter' === adapter) extras = buildDrizzlePrelude(provider, connection);
2492
- else if ('prismaAdapter' === adapter) extras = buildPrismaPrelude(provider, connection);
2493
- else if ('typeormAdapter' === adapter) extras = buildTypeormPrelude(provider, connection);
2494
- else if ('mongoAdapter' === adapter) extras = buildMongoPrelude(connection);
2495
- return `import { defineConfig } from '@c15t/backend';
2496
- ${importAdapter}
2497
- ${extras.imports ? `${extras.imports}\n` : ''}
2498
- ${extras.prelude ? `${extras.prelude}\n` : ''}
2499
- export default defineConfig({
2500
- adapter: ${dbConfig},
2501
- });
2502
- `;
2503
- }
2504
- async function promptSelectAdapter() {
2505
- const selection = await prompts_.select({
2506
- message: 'Select database adapter:',
2507
- options: Object.keys(ADAPTER_LABELS).map((key)=>({
2508
- value: key,
2509
- label: ADAPTER_LABELS[key]
2510
- }))
2511
- });
2512
- if (prompts_.isCancel(selection)) throw new Cancelled('adapter_select');
2513
- return selection;
2514
- }
2515
- async function promptSelectProvider(adapter) {
2516
- const providers = PROVIDERS_BY_ADAPTER[adapter];
2517
- if (0 === providers.length) throw new Error('No providers available for selected adapter');
2518
- if (1 === providers.length) {
2519
- const [first] = providers;
2520
- return first.value;
2521
- }
2522
- const selection = await prompts_.select({
2523
- message: 'Select database provider:',
2524
- options: providers.map((opt)=>({
2525
- value: opt.value,
2526
- label: opt.label
2527
- }))
2528
- });
2529
- if (prompts_.isCancel(selection)) throw new Cancelled('provider_select');
2530
- return selection;
2531
- }
2532
- async function promptConnection(adapter, provider) {
2533
- const connection = {
2534
- useEnv: true
2535
- };
2536
- if ('sqlite' === provider) {
2537
- const sqliteFile = await prompts_.text({
2538
- message: 'SQLite file path:',
2539
- initialValue: './db.sqlite'
2540
- });
2541
- if (prompts_.isCancel(sqliteFile)) throw new Cancelled('sqlite_path');
2542
- connection.sqliteFile = String(sqliteFile);
2543
- return connection;
2544
- }
2545
- const useEnv = await prompts_.confirm({
2546
- message: 'Store connection string in an environment variable?',
2547
- initialValue: true
2548
- });
2549
- if (prompts_.isCancel(useEnv)) throw new Cancelled('use_env_confirm');
2550
- connection.useEnv = Boolean(useEnv);
2551
- if (connection.useEnv) {
2552
- const defaultVar = 'mongoAdapter' === adapter ? 'MONGODB_URI' : 'DATABASE_URL';
2553
- const envVarName = await prompts_.text({
2554
- message: 'Env var name for connection string:',
2555
- initialValue: defaultVar
2556
- });
2557
- if (prompts_.isCancel(envVarName)) throw new Cancelled('env_var_name');
2558
- connection.envVar = String(envVarName);
2559
- return connection;
2560
- }
2561
- const placeholder = 'mongoAdapter' === adapter ? 'mongodb+srv://user:pass@host/db' : 'postgresql://user:pass@host:5432/db';
2562
- const connectionString = await prompts_.text({
2563
- message: 'Connection string:',
2564
- placeholder
2565
- });
2566
- if (prompts_.isCancel(connectionString)) throw new Cancelled('connection_string');
2567
- connection.value = String(connectionString);
2568
- return connection;
2569
- }
2570
- async function ensureBackendConfig(context) {
2571
- const { cwd, logger } = context;
2572
- const targetPath = external_node_path_["default"].join(cwd, 'c15t-backend.config.ts');
2573
- if (await pathExists(targetPath)) {
2574
- logger.debug(`Backend config already exists at ${targetPath}`);
2575
- return {
2576
- path: targetPath,
2577
- dependencies: []
2578
- };
2579
- }
2580
- try {
2581
- const adapter = await promptSelectAdapter();
2582
- const provider = await promptSelectProvider(adapter);
2583
- const connection = await promptConnection(adapter, provider);
2584
- const dependencies = [];
2585
- if ('kyselyAdapter' === adapter) {
2586
- dependencies.push('kysely');
2587
- if ('postgresql' === provider || 'cockroachdb' === provider) dependencies.push('pg');
2588
- else if ('mysql' === provider) dependencies.push('mysql2');
2589
- else if ('mssql' === provider) dependencies.push('mssql');
2590
- else if ('sqlite' === provider) dependencies.push('better-sqlite3');
2591
- } else if ('drizzleAdapter' === adapter) {
2592
- dependencies.push('drizzle-orm');
2593
- if ('postgresql' === provider) dependencies.push('pg');
2594
- else if ('mysql' === provider) dependencies.push('mysql2');
2595
- else if ('sqlite' === provider) dependencies.push('better-sqlite3');
2596
- } else if ('prismaAdapter' === adapter) dependencies.push('@prisma/client');
2597
- else if ('typeormAdapter' === adapter) dependencies.push('typeorm');
2598
- else if ('mongoAdapter' === adapter) dependencies.push('mongodb');
2599
- const dbConfig = buildDatabaseConfig(adapter, provider, connection);
2600
- const fileContent = buildFileContent(adapter, String(provider), dbConfig, connection);
2601
- await promises_["default"].writeFile(targetPath, fileContent, 'utf8');
2602
- context.logger.success(`Created ${external_node_path_["default"].relative(cwd, targetPath)}`);
2603
- if ('sqlite' !== provider && connection.useEnv && connection.envVar) context.logger.note(`Remember to set ${connection.envVar} in your environment or .env file.`, 'Environment');
2604
- return {
2605
- path: targetPath,
2606
- dependencies
2607
- };
2608
- } catch (err) {
2609
- if (err instanceof Cancelled) return context.error.handleCancel('Operation cancelled.', {
2610
- command: 'ensure-backend-config',
2611
- stage: err.stage
2612
- });
2613
- throw err;
2614
- }
2615
- }
2616
- async function handleMigrationResult(context, result) {
2617
- const { logger, telemetry } = context;
2618
- telemetry.trackEvent(TelemetryEventName.MIGRATION_PLANNED, {
2619
- success: true
2620
- });
2621
- const saveSQL = await prompts_.confirm({
2622
- message: 'Save SQL to file?',
2623
- initialValue: true
2624
- });
2625
- if (prompts_.isCancel(saveSQL)) return void telemetry.trackEvent(TelemetryEventName.MIGRATION_FAILED, {
2626
- saveSql: false
2627
- });
2628
- if (saveSQL) {
2629
- const sql = result.getSQL?.() ?? '';
2630
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
2631
- const filename = `migration-${timestamp}.sql`;
2632
- const filepath = (0, external_node_path_.join)(process.cwd(), filename);
2633
- await (0, promises_.writeFile)(filepath, sql, 'utf-8');
2634
- logger.success(`SQL saved to: ${filename}`);
2635
- }
2636
- const execute = await prompts_.confirm({
2637
- message: 'Execute this migration?',
2638
- initialValue: false
2639
- });
2640
- if (prompts_.isCancel(execute)) return void telemetry.trackEvent(TelemetryEventName.MIGRATION_FAILED, {
2641
- execute: false
2642
- });
2643
- await result.execute();
2644
- logger.success('Migration completed.');
2645
- telemetry.trackEvent(TelemetryEventName.MIGRATION_COMPLETED, {
2646
- success: true
2647
- });
2648
- }
2649
- async function handleORMResult(context, result) {
2650
- const { logger, telemetry, cwd } = context;
2651
- const filePath = external_node_path_["default"].join(cwd, result.path);
2652
- await promises_["default"].mkdir(external_node_path_["default"].dirname(filePath), {
2653
- recursive: true
2654
- });
2655
- await promises_["default"].writeFile(filePath, result.code);
2656
- logger.info(`Migration file created at ${filePath}`);
2657
- telemetry.trackEvent(TelemetryEventName.MIGRATION_COMPLETED, {
2658
- success: true,
2659
- migrationFileCreated: true
2660
- });
2661
- }
2662
- async function readConfigAndGetDb(context, absoluteConfigPath) {
2663
- const { logger } = context;
2664
- logger.info(`Loading backend config from ${absoluteConfigPath}`);
2665
- const resolvedPath = external_node_path_["default"].resolve(absoluteConfigPath);
2666
- try {
2667
- await promises_["default"].access(resolvedPath);
2668
- } catch {
2669
- throw new Error(`Backend config not found at: ${resolvedPath}`);
2670
- }
2671
- try {
2672
- const { config } = await (0, __rspack_external_c12.loadConfig)({
2673
- configFile: absoluteConfigPath,
2674
- jitiOptions: {
2675
- extensions: [
2676
- '.ts',
2677
- '.tsx',
2678
- '.js',
2679
- '.jsx',
2680
- '.mjs',
2681
- '.cjs',
2682
- '.mts',
2683
- '.cts',
2684
- '.cjs'
2685
- ]
2686
- }
2687
- });
2688
- logger.debug('Imported Config');
2689
- if (!config || 'object' != typeof config || !('adapter' in config)) throw new Error('Invalid backend config: missing required "adapter" property');
2690
- return {
2691
- db: __rspack_external__c15t_backend_db_schema_e7c5e6a0.DB.client(config.adapter)
2692
- };
2693
- } catch (error) {
2694
- logger.error('Failed to load backend config', error);
2695
- if (error instanceof Error) throw error;
2696
- throw new Error(`Unknown error loading backend config: ${String(error)}`);
2697
- }
2698
- }
2699
- async function migrate(context) {
2700
- const { logger } = context;
2701
- logger.info('Starting migration process...');
2702
- const configResult = await ensureBackendConfig(context);
2703
- if (!configResult || !configResult.path) return void logger.error('No backend config found.');
2704
- const { path, dependencies } = configResult;
2705
- if (dependencies.length > 0) await installDependencies({
2706
- context,
2707
- dependenciesToAdd: dependencies,
2708
- autoInstall: true
2709
- });
2710
- const { db } = await readConfigAndGetDb(context, path);
2711
- logger.info('Loaded c15t-backend.config.ts');
2712
- const result = await (0, __rspack_external__c15t_backend_db_migrator_ebe6d5c7.migrator)({
2713
- db,
2714
- schema: 'latest'
2715
- });
2716
- if ('path' in result) await handleORMResult(context, result);
2717
- else await handleMigrationResult(context, result);
2718
- }
2719
- const subcommands = [
2720
- {
2721
- name: 'generate',
2722
- label: 'Generate',
2723
- hint: 'Generate code for your c15t project',
2724
- action: generate
2725
- },
2726
- {
2727
- name: 'migrate',
2728
- label: 'Migrate',
2729
- hint: 'Run database migrations',
2730
- action: migrate
2731
- }
2732
- ];
2733
- async function selfHost(context) {
2734
- const { logger, telemetry, commandArgs, error } = context;
2735
- logger.debug('Starting self-host command...');
2736
- telemetry.trackEvent(TelemetryEventName.SELF_HOST_STARTED, {});
2737
- const [subcommand] = commandArgs;
2738
- if (subcommand) {
2739
- switch(subcommand){
2740
- case 'generate':
2741
- await generate(context, 'self-hosted');
2742
- break;
2743
- case 'migrate':
2744
- await migrate(context);
2745
- break;
2746
- default:
2747
- logger.error(`Unknown self-host subcommand: ${subcommand}`);
2748
- logger.info('Available subcommands: generate, migrate');
2749
- telemetry.trackEvent(TelemetryEventName.SELF_HOST_COMPLETED, {
2750
- success: false,
2751
- reason: 'unknown_subcommand'
2752
- });
2753
- break;
2754
- }
2755
- return;
2756
- }
2757
- logger.debug('No subcommand specified, entering interactive selection.');
2758
- telemetry.trackEvent(TelemetryEventName.INTERACTIVE_MENU_OPENED, {
2759
- context: 'self-host'
2760
- });
2761
- const promptOptions = subcommands.map((cmd)=>({
2762
- value: cmd.name,
2763
- label: cmd.label,
2764
- hint: cmd.hint
2765
- }));
2766
- promptOptions.push({
2767
- value: 'exit',
2768
- label: 'Exit',
2769
- hint: 'Return to main menu'
2770
- });
2771
- const selectedSubcommandName = await prompts_.select({
2772
- message: (0, utils_logger.$e)('info', 'Which self-host command would you like to run?'),
2773
- options: promptOptions
2774
- });
2775
- if (prompts_.isCancel(selectedSubcommandName) || 'exit' === selectedSubcommandName) {
2776
- logger.debug('Interactive selection cancelled or exit chosen.');
2777
- telemetry.trackEvent(TelemetryEventName.INTERACTIVE_MENU_EXITED, {
2778
- action: prompts_.isCancel(selectedSubcommandName) ? 'cancelled' : 'exit',
2779
- context: 'self-host'
2780
- });
2781
- error.handleCancel('Operation cancelled.', {
2782
- command: 'self-host',
2783
- stage: 'menu_selection'
2784
- });
2785
- return;
2786
- }
2787
- const selectedSubcommand = subcommands.find((cmd)=>cmd.name === selectedSubcommandName);
2788
- if (selectedSubcommand) {
2789
- logger.debug(`User selected subcommand: ${selectedSubcommand.name}`);
2790
- if ('generate' === selectedSubcommand.name) await generate(context, 'self-hosted');
2791
- else await selectedSubcommand.action(context);
2792
- } else {
2793
- logger.error(`Unknown subcommand: ${selectedSubcommandName}`);
2794
- telemetry.trackEvent(TelemetryEventName.SELF_HOST_COMPLETED, {
2795
- success: false,
2796
- reason: 'invalid_selection'
2797
- });
2798
- return;
2799
- }
2800
- telemetry.trackEvent(TelemetryEventName.SELF_HOST_COMPLETED, {
2801
- success: true
2802
- });
2803
- }
2804
- async function displayIntro(context, version) {
2805
- const { logger } = context;
2806
- logger.info(`${external_picocolors_["default"].bold('Welcome!')} Let's get you set up.`);
2807
- logger.message('');
2808
- let figletText = 'c15t';
2809
- try {
2810
- figletText = await new Promise((resolve)=>{
2811
- __rspack_external_figlet["default"].text('c15t', {
2812
- font: 'Nancyj-Improved',
2813
- horizontalLayout: 'default',
2814
- verticalLayout: 'default',
2815
- width: 80,
2816
- whitespaceBreak: true
2817
- }, (err, data)=>{
2818
- if (err) {
2819
- logger.debug('Failed to generate figlet text');
2820
- resolve('c15t');
2821
- } else resolve(data || 'c15t');
2822
- });
2823
- });
2824
- } catch (error) {
2825
- logger.debug('Error generating figlet text', error);
2826
- }
2827
- const customColor = {
2828
- teal10: (text)=>`\x1b[38;2;10;80;70m${text}\x1b[0m`,
2829
- teal20: (text)=>`\x1b[38;2;15;100;90m${text}\x1b[0m`,
2830
- teal30: (text)=>`\x1b[38;2;20;120;105m${text}\x1b[0m`,
2831
- teal40: (text)=>`\x1b[38;2;25;150;130m${text}\x1b[0m`,
2832
- teal50: (text)=>`\x1b[38;2;30;170;150m${text}\x1b[0m`,
2833
- teal75: (text)=>`\x1b[38;2;34;211;187m${text}\x1b[0m`,
2834
- teal90: (text)=>`\x1b[38;2;45;225;205m${text}\x1b[0m`,
2835
- teal100: (text)=>`\x1b[38;2;65;235;220m${text}\x1b[0m`
2836
- };
2837
- const lines = figletText.split('\n');
2838
- const coloredLines = lines.map((line, index)=>{
2839
- const position = index / (lines.length - 1);
2840
- if (position < 0.1) return customColor.teal10(line);
2841
- if (position < 0.2) return customColor.teal20(line);
2842
- if (position < 0.3) return customColor.teal30(line);
2843
- if (position < 0.4) return customColor.teal40(line);
2844
- if (position < 0.5) return customColor.teal50(line);
2845
- if (position < 0.65) return customColor.teal75(line);
2846
- if (position < 0.8) return customColor.teal90(line);
2847
- return customColor.teal100(line);
2848
- });
2849
- logger.message(coloredLines.join('\n'));
2850
- }
2851
- var constants = __webpack_require__("./src/constants.ts");
2852
- function createErrorHandlers(context) {
2853
- const { logger, telemetry } = context;
2854
- return {
2855
- handleError: (error, message)=>{
2856
- logger.error(message, error);
2857
- if (error instanceof Error) logger.error(error.message);
2858
- else logger.error(String(error));
2859
- logger.failed(`${external_picocolors_["default"].red('Operation failed unexpectedly.')}`);
2860
- process.exit(1);
2861
- },
2862
- handleCancel: (message = 'Operation cancelled.', context)=>{
2863
- logger.debug(`Handling cancellation: ${message}`, context);
2864
- telemetry.trackEvent(TelemetryEventName.ONBOARDING_EXITED, {
2865
- reason: 'user_cancelled',
2866
- command: context?.command || 'unknown',
2867
- stage: context?.stage || 'unknown'
2868
- });
2869
- logger.failed(message);
2870
- process.exit(0);
2871
- }
2872
- };
2873
- }
2874
- function createFileSystem(context) {
2875
- const { logger, cwd } = context;
2876
- return {
2877
- getPackageInfo: ()=>{
2878
- logger.debug('Reading package.json');
2879
- const packageJsonPath = external_node_path_["default"].join(cwd, 'package.json');
2880
- logger.debug(`package.json path: ${packageJsonPath}`);
2881
- try {
2882
- const packageInfo = __rspack_external_fs_extra_ce68a66b["default"].readJSONSync(packageJsonPath);
2883
- logger.debug('Successfully read package.json');
2884
- return {
2885
- name: packageInfo?.name || 'unknown',
2886
- version: packageInfo?.version || 'unknown',
2887
- ...packageInfo
2888
- };
2889
- } catch (error) {
2890
- logger.error(`Error reading package.json at ${packageJsonPath}:`, error);
2891
- return {
2892
- name: 'unknown',
2893
- version: 'unknown'
2894
- };
2895
- }
2896
- }
2897
- };
2898
- }
2899
- async function detectFramework(projectRoot, logger) {
2900
- try {
2901
- logger?.debug(`Detecting framework in ${projectRoot}`);
2902
- const packageJsonPath = external_node_path_["default"].join(projectRoot, 'package.json');
2903
- const packageJson = JSON.parse(await promises_["default"].readFile(packageJsonPath, 'utf-8'));
2904
- const deps = {
2905
- ...packageJson.dependencies,
2906
- ...packageJson.devDependencies
2907
- };
2908
- const hasReact = 'react' in deps;
2909
- const reactVersion = hasReact ? deps.react : null;
2910
- logger?.debug(`React detected: ${hasReact}${reactVersion ? ` (version: ${reactVersion})` : ''}`);
2911
- const tailwindVersion = deps.tailwindcss || null;
2912
- logger?.debug(`Tailwind detected: ${!!tailwindVersion}${tailwindVersion ? ` (version: ${tailwindVersion})` : ''}`);
2913
- let framework = null;
2914
- let frameworkVersion = null;
2915
- let pkg = hasReact ? '@c15t/react' : 'c15t';
2916
- if ('next' in deps) {
2917
- framework = 'Next.js';
2918
- frameworkVersion = deps.next;
2919
- pkg = '@c15t/nextjs';
2920
- } else if ('@remix-run/react' in deps) {
2921
- framework = 'Remix';
2922
- frameworkVersion = deps['@remix-run/react'];
2923
- } else if ('@vitejs/plugin-react' in deps || '@vitejs/plugin-react-swc' in deps) {
2924
- framework = 'Vite + React';
2925
- frameworkVersion = deps['@vitejs/plugin-react'] || deps['@vitejs/plugin-react-swc'];
2926
- } else if ('gatsby' in deps) {
2927
- framework = 'Gatsby';
2928
- frameworkVersion = deps.gatsby;
2929
- } else if (hasReact) {
2930
- framework = 'React';
2931
- frameworkVersion = reactVersion;
2932
- }
2933
- logger?.debug(`Detected framework: ${framework}${frameworkVersion ? ` (version: ${frameworkVersion})` : ''}, package: ${pkg}`);
2934
- return {
2935
- framework,
2936
- frameworkVersion,
2937
- pkg,
2938
- hasReact,
2939
- reactVersion,
2940
- tailwindVersion
2941
- };
2942
- } catch (error) {
2943
- logger?.debug(`Framework detection failed: ${error instanceof Error ? error.message : String(error)}`);
2944
- return {
2945
- framework: null,
2946
- frameworkVersion: null,
2947
- pkg: 'c15t',
2948
- hasReact: false,
2949
- reactVersion: null,
2950
- tailwindVersion: null
2951
- };
2952
- }
2953
- }
2954
- async function detectProjectRoot(cwd, logger) {
2955
- let projectRoot = cwd;
2956
- logger?.debug(`Starting project root detection from: ${cwd}`);
2957
- try {
2958
- let prevDir = '';
2959
- let depth = 0;
2960
- const maxDepth = 10;
2961
- while(projectRoot !== prevDir && depth < maxDepth){
2962
- logger?.debug(`Checking directory (depth ${depth}): ${projectRoot}`);
2963
- try {
2964
- const packageJsonPath = external_node_path_["default"].join(projectRoot, 'package.json');
2965
- logger?.debug(`Looking for package.json at: ${packageJsonPath}`);
2966
- await promises_["default"].access(packageJsonPath);
2967
- logger?.debug(`Found package.json at: ${projectRoot}`);
2968
- break;
2969
- } catch (error) {
2970
- logger?.debug(`No package.json found in ${projectRoot}: ${error instanceof Error ? error.message : String(error)}`);
2971
- prevDir = projectRoot;
2972
- projectRoot = external_node_path_["default"].dirname(projectRoot);
2973
- depth++;
2974
- }
2975
- }
2976
- if (projectRoot === prevDir) {
2977
- logger?.debug('Reached root directory without finding package.json');
2978
- logger?.failed('Could not find project root (no package.json found)');
2979
- }
2980
- if (depth >= maxDepth) {
2981
- logger?.debug('Reached maximum directory depth without finding package.json');
2982
- logger?.failed('Could not find project root (reached maximum directory depth)');
2983
- }
2984
- logger?.debug(`Project root detection complete. Found at: ${projectRoot}`);
2985
- return projectRoot;
2986
- } catch (error) {
2987
- logger?.debug(`Project root detection failed: ${error instanceof Error ? error.message : String(error)}`);
2988
- logger?.debug(`Falling back to current directory: ${cwd}`);
2989
- return cwd;
2990
- }
2991
- }
2992
- const SUPPORTED_PACKAGE_MANAGERS = [
2993
- 'npm',
2994
- 'yarn',
2995
- 'pnpm',
2996
- 'bun'
2997
- ];
2998
- async function getPackageManagerVersion(pm) {
2999
- try {
3000
- const { execSync } = await import("node:child_process");
3001
- const version = execSync(`${pm} --version`).toString().trim();
3002
- return version;
3003
- } catch {
3004
- return null;
3005
- }
3006
- }
3007
- async function detectPackageManager(projectRoot, logger) {
3008
- try {
3009
- logger?.debug('Detecting package manager');
3010
- const pm = await (0, __rspack_external_package_manager_detector_detect_94d6a9ae.detect)({
3011
- cwd: projectRoot
3012
- });
3013
- if (!pm) throw new Error('No package manager detected');
3014
- logger?.debug(`Detected package manager: ${pm.name}`);
3015
- if (!SUPPORTED_PACKAGE_MANAGERS.includes(pm.name)) throw new Error(`Unsupported package manager: ${pm.name}`);
3016
- return {
3017
- name: pm.name,
3018
- version: pm.version ?? null
3019
- };
3020
- } catch (error) {
3021
- logger?.error(`Error detecting package manager: ${error instanceof Error ? error.message : String(error)}`);
3022
- }
3023
- const selectedPackageManager = await prompts_.select({
3024
- message: 'Please select your package manager:',
3025
- options: [
3026
- {
3027
- value: 'npm',
3028
- label: 'npm'
3029
- },
3030
- {
3031
- value: 'yarn',
3032
- label: 'yarn'
3033
- },
3034
- {
3035
- value: 'pnpm',
3036
- label: 'pnpm'
3037
- },
3038
- {
3039
- value: 'bun',
3040
- label: 'bun'
3041
- }
3042
- ],
3043
- initialValue: 'npm'
3044
- });
3045
- if (prompts_.isCancel(selectedPackageManager)) {
3046
- logger?.debug('Package manager selection cancelled by user');
3047
- logger?.failed('Package manager selection cancelled. Exiting.');
3048
- process.exit(0);
3049
- }
3050
- const version = await getPackageManagerVersion(selectedPackageManager);
3051
- logger?.debug(`User selected package manager: ${selectedPackageManager} (version: ${version ?? 'unknown'})`);
3052
- return {
3053
- name: selectedPackageManager,
3054
- version
3055
- };
3056
- }
3057
- const globalFlags = [
3058
- {
3059
- names: [
3060
- '--help',
3061
- '-h'
3062
- ],
3063
- description: 'Show this help message.',
3064
- type: 'special',
3065
- expectsValue: false
3066
- },
3067
- {
3068
- names: [
3069
- '--version',
3070
- '-v'
3071
- ],
3072
- description: 'Show the CLI version.',
3073
- type: 'special',
3074
- expectsValue: false
3075
- },
3076
- {
3077
- names: [
3078
- '--logger'
3079
- ],
3080
- description: 'Set log level (fatal, error, warn, info, debug).',
3081
- type: 'string',
3082
- expectsValue: true
3083
- },
3084
- {
3085
- names: [
3086
- '--config'
3087
- ],
3088
- description: 'Specify path to configuration file.',
3089
- type: 'string',
3090
- expectsValue: true
3091
- },
3092
- {
3093
- names: [
3094
- '-y'
3095
- ],
3096
- description: 'Skip confirmation prompts (use with caution).',
3097
- type: 'boolean',
3098
- expectsValue: false
3099
- },
3100
- {
3101
- names: [
3102
- '--no-telemetry'
3103
- ],
3104
- description: 'Disable telemetry data collection.',
3105
- type: 'boolean',
3106
- expectsValue: false
3107
- },
3108
- {
3109
- names: [
3110
- '--telemetry-debug'
3111
- ],
3112
- description: 'Enable debug mode for telemetry (shows detailed telemetry logs).',
3113
- type: 'boolean',
3114
- expectsValue: false
3115
- }
3116
- ];
3117
- function parseCliArgs(rawArgs, commands) {
3118
- const parsedFlags = {};
3119
- const potentialCommandArgsAndUndefined = [];
3120
- let commandName;
3121
- const commandArgs = [];
3122
- for (const flag of globalFlags){
3123
- const primaryName = flag.names[0]?.replace(/^--/, '').replace(/^-/, '');
3124
- if (primaryName) parsedFlags[primaryName] = 'boolean' === flag.type ? false : void 0;
3125
- }
3126
- for(let i = 0; i < rawArgs.length; i++){
3127
- const arg = rawArgs[i];
3128
- if ('string' != typeof arg) continue;
3129
- let argIsFlagOrValue = false;
3130
- for (const flag of globalFlags)if (flag.names.includes(arg)) {
3131
- const primaryName = flag.names[0]?.replace(/^--/, '').replace(/^-/, '');
3132
- if (primaryName) {
3133
- argIsFlagOrValue = true;
3134
- if ('boolean' === flag.type) parsedFlags[primaryName] = true;
3135
- else if (flag.expectsValue) {
3136
- const nextArg = rawArgs[i + 1];
3137
- if (nextArg && !nextArg.startsWith('-')) {
3138
- parsedFlags[primaryName] = nextArg;
3139
- i++;
3140
- } else prompts_.log.warn((0, utils_logger.$e)('warn', `Flag ${arg} expects a value, but none was found or the next item is a flag.`));
3141
- } else parsedFlags[primaryName] = true;
3142
- }
3143
- break;
3144
- }
3145
- if (!argIsFlagOrValue) potentialCommandArgsAndUndefined.push(arg);
3146
- }
3147
- const potentialCommandArgs = potentialCommandArgsAndUndefined.filter((arg)=>'string' == typeof arg);
3148
- commandName = potentialCommandArgs.find((arg)=>commands.some((cmd)=>cmd.name === arg));
3149
- for (const arg of potentialCommandArgs)if (arg !== commandName) commandArgs.push(arg);
3150
- return {
3151
- commandName,
3152
- commandArgs,
3153
- parsedFlags
3154
- };
3155
- }
3156
- function createUserInteraction(context) {
3157
- const { logger, error } = context;
3158
- return {
3159
- confirm: async (message, initialValue)=>{
3160
- logger.debug(`Confirm action: "${message}", Initial: ${initialValue}`);
3161
- const confirmed = await prompts_.confirm({
3162
- message,
3163
- initialValue
3164
- });
3165
- if (prompts_.isCancel(confirmed)) {
3166
- error.handleCancel();
3167
- return false;
3168
- }
3169
- logger.debug(`Confirmation result: ${confirmed}`);
3170
- return confirmed;
3171
- }
3172
- };
3173
- }
3174
- async function createCliContext(rawArgs, cwd, commands) {
3175
- const { commandName, commandArgs, parsedFlags } = parseCliArgs(rawArgs, commands);
3176
- let desiredLogLevel = 'info';
3177
- const levelArg = parsedFlags.logger;
3178
- if ('string' == typeof levelArg) if (utils_logger.U0.includes(levelArg)) desiredLogLevel = levelArg;
3179
- else console.warn(`[CLI Setup] Invalid log level '${levelArg}' provided via --logger. Using default 'info'.`);
3180
- else if (true === levelArg) console.warn("[CLI Setup] --logger flag found but no level specified. Using default 'info'.");
3181
- const logger = (0, utils_logger.xw)(desiredLogLevel);
3182
- logger.debug(`Logger initialized with level: ${desiredLogLevel}`);
3183
- const baseContext = {
3184
- logger,
3185
- flags: parsedFlags,
3186
- commandName,
3187
- commandArgs,
3188
- cwd
3189
- };
3190
- const context = baseContext;
3191
- context.error = createErrorHandlers(context);
3192
- const userInteraction = createUserInteraction(context);
3193
- context.confirm = userInteraction.confirm;
3194
- context.fs = createFileSystem(context);
3195
- context.projectRoot = await detectProjectRoot(cwd, logger);
3196
- context.framework = await detectFramework(context.projectRoot, logger);
3197
- context.packageManager = await detectPackageManager(context.projectRoot, logger);
3198
- const telemetryDisabled = true === parsedFlags['no-telemetry'];
3199
- const telemetryDebug = true === parsedFlags['telemetry-debug'];
3200
- try {
3201
- context.telemetry = createTelemetry({
3202
- disabled: telemetryDisabled,
3203
- debug: telemetryDebug,
3204
- defaultProperties: {
3205
- cliVersion: context.fs.getPackageInfo().version,
3206
- framework: context.framework.framework ?? 'unknown',
3207
- frameworkVersion: context.framework.frameworkVersion ?? 'unknown',
3208
- packageManager: context.packageManager.name,
3209
- packageManagerVersion: context.packageManager.version ?? 'unknown',
3210
- hasReact: context.framework.hasReact,
3211
- reactVersion: context.framework.reactVersion ?? 'unknown',
3212
- package: context.framework.pkg ?? 'unknown'
3213
- },
3214
- logger: context.logger
3215
- });
3216
- if (telemetryDisabled) logger.debug('Telemetry is disabled by user preference');
3217
- else if (telemetryDebug) logger.debug('Telemetry initialized with debug mode enabled');
3218
- else logger.debug('Telemetry initialized');
3219
- } catch {
3220
- logger.warn('Failed to initialize telemetry, continuing with telemetry disabled');
3221
- context.telemetry = createTelemetry({
3222
- disabled: true,
3223
- logger: context.logger
3224
- });
3225
- }
3226
- logger.debug('CLI context fully initialized with all utilities');
3227
- return context;
3228
- }
3229
- const src_commands = [
3230
- {
3231
- name: 'generate',
3232
- label: 'Generate (Recommended)',
3233
- hint: 'Add c15t to your project',
3234
- description: 'Setup your c15t project',
3235
- action: (context)=>generate(context)
3236
- },
3237
- {
3238
- name: 'self-host',
3239
- label: 'Self Host',
3240
- hint: 'Host c15t backend on your own infra',
3241
- description: 'Commands for self-hosting c15t (generate, migrate).',
3242
- action: (context)=>selfHost(context)
3243
- },
3244
- {
3245
- name: 'github',
3246
- label: 'GitHub',
3247
- hint: 'Star us on GitHub',
3248
- description: 'Open our GitHub repository to give us a star.',
3249
- action: async (context)=>{
3250
- const { logger } = context;
3251
- logger.note(`We're building c15t as an ${external_picocolors_["default"].bold('open source')} project to make consent management more accessible.\nIf you find this useful, we'd really appreciate a GitHub star - it helps others discover the project!`, 'Star Us on GitHub');
3252
- await (0, __rspack_external_open["default"])(constants.tl.GITHUB);
3253
- logger.success('Thank you for your support!');
3254
- }
3255
- },
3256
- {
3257
- name: 'docs',
3258
- label: 'c15t docs',
3259
- hint: 'Open documentation',
3260
- description: 'Open the c15t documentation in your browser.',
3261
- action: async (context)=>{
3262
- const { logger } = context;
3263
- await (0, __rspack_external_open["default"])(`${constants.tl.DOCS}?ref=cli`);
3264
- logger.success('Documentation opened in your browser.');
3265
- }
3266
- }
3267
- ];
3268
- async function main() {
3269
- const rawArgs = process.argv.slice(2);
3270
- const cwd = process.cwd();
3271
- const context = await createCliContext(rawArgs, cwd, src_commands);
3272
- const { logger, flags, commandName, commandArgs, error, telemetry } = context;
3273
- const packageInfo = context.fs.getPackageInfo();
3274
- const version = packageInfo.version;
3275
- if (!telemetry.isDisabled()) logger.note(`c15t collects anonymous usage data to help improve the CLI.
3276
- This data is not personally identifiable and helps us prioritize features.
3277
- To disable telemetry, use the ${external_picocolors_["default"].cyan('--no-telemetry')}
3278
- flag or set ${external_picocolors_["default"].cyan('C15T_TELEMETRY_DISABLED=1')} in your environment.`, `${(0, utils_logger.$e)('info', 'Telemetry Notice')}`);
3279
- try {
3280
- telemetry.trackEvent(TelemetryEventName.CLI_INVOKED, {
3281
- version,
3282
- nodeVersion: process.version,
3283
- platform: process.platform
3284
- });
3285
- telemetry.flushSync();
3286
- } catch (error) {
3287
- logger.debug('Failed to track CLI invocation:', error);
3288
- }
3289
- if (flags.version) {
3290
- logger.debug('Version flag detected');
3291
- logger.message(`c15t CLI version ${version}`);
3292
- telemetry.trackEvent(TelemetryEventName.VERSION_DISPLAYED, {
3293
- version
3294
- });
3295
- telemetry.flushSync();
3296
- await telemetry.shutdown();
3297
- process.exit(0);
3298
- }
3299
- if (flags.help) {
3300
- logger.debug('Help flag detected. Displaying help and exiting.');
3301
- telemetry.trackEvent(TelemetryEventName.HELP_DISPLAYED, {
3302
- version
3303
- });
3304
- telemetry.flushSync();
3305
- showHelpMenu(context, version, src_commands, globalFlags);
3306
- await telemetry.shutdown();
3307
- process.exit(0);
3308
- }
3309
- logger.debug('Raw process arguments:', process.argv);
3310
- logger.debug('Parsed command name:', commandName);
3311
- logger.debug('Parsed command args:', commandArgs);
3312
- logger.debug('Parsed global flags:', flags);
3313
- await displayIntro(context, version);
3314
- logger.debug(`Current working directory: ${cwd}`);
3315
- logger.debug(`Config path flag: ${flags.config}`);
3316
- try {
3317
- if (commandName) {
3318
- const command = src_commands.find((cmd)=>cmd.name === commandName);
3319
- if (command) {
3320
- logger.info(`Executing command: ${command.name}`);
3321
- telemetry.trackCommand(command.name, commandArgs, flags);
3322
- await command.action(context);
3323
- telemetry.trackEvent(TelemetryEventName.COMMAND_SUCCEEDED, {
3324
- command: command.name,
3325
- executionTime: Date.now() - performance.now()
3326
- });
3327
- telemetry.flushSync();
3328
- } else {
3329
- logger.error(`Unknown command: ${commandName}`);
3330
- telemetry.trackEvent(TelemetryEventName.COMMAND_UNKNOWN, {
3331
- unknownCommand: commandName
3332
- });
3333
- telemetry.flushSync();
3334
- logger.info('Run c15t --help to see available commands.');
3335
- await telemetry.shutdown();
3336
- process.exit(1);
3337
- }
3338
- } else {
3339
- logger.debug('No command specified, entering interactive selection.');
3340
- telemetry.trackEvent(TelemetryEventName.INTERACTIVE_MENU_OPENED, {});
3341
- const promptOptions = src_commands.map((cmd)=>({
3342
- value: cmd.name,
3343
- label: cmd.label,
3344
- hint: cmd.hint
3345
- }));
3346
- promptOptions.push({
3347
- value: 'exit',
3348
- label: 'exit',
3349
- hint: 'Close the CLI'
3350
- });
3351
- const selectedCommandName = await prompts_.select({
3352
- message: (0, utils_logger.$e)('info', 'Which command would you like to run?'),
3353
- options: promptOptions
3354
- });
3355
- if (prompts_.isCancel(selectedCommandName) || 'exit' === selectedCommandName) {
3356
- logger.debug('Interactive selection cancelled or exit chosen.');
3357
- telemetry.trackEvent(TelemetryEventName.INTERACTIVE_MENU_EXITED, {
3358
- action: prompts_.isCancel(selectedCommandName) ? 'cancelled' : 'exit'
3359
- });
3360
- context.error.handleCancel('Operation cancelled.', {
3361
- command: 'interactive_menu',
3362
- stage: 'exit'
3363
- });
3364
- } else {
3365
- const selectedCommand = src_commands.find((cmd)=>cmd.name === selectedCommandName);
3366
- if (selectedCommand) {
3367
- logger.debug(`User selected command: ${selectedCommand.name}`);
3368
- telemetry.trackCommand(selectedCommand.name, [], flags);
3369
- await selectedCommand.action(context);
3370
- telemetry.trackEvent(TelemetryEventName.COMMAND_SUCCEEDED, {
3371
- command: selectedCommand.name,
3372
- executionTime: Date.now() - performance.now()
3373
- });
3374
- telemetry.flushSync();
3375
- } else {
3376
- telemetry.trackEvent(TelemetryEventName.COMMAND_UNKNOWN, {
3377
- unknownCommand: String(selectedCommandName)
3378
- });
3379
- telemetry.flushSync();
3380
- error.handleError(new Error(`Command '${selectedCommandName}' not found`), 'An internal error occurred');
3381
- }
3382
- }
3383
- }
3384
- logger.debug('Command execution completed');
3385
- telemetry.trackEvent(TelemetryEventName.CLI_COMPLETED, {
3386
- success: true
3387
- });
3388
- telemetry.flushSync();
3389
- } catch (executionError) {
3390
- telemetry.trackEvent(TelemetryEventName.COMMAND_FAILED, {
3391
- command: commandName,
3392
- error: executionError instanceof Error ? executionError.message : String(executionError)
3393
- });
3394
- telemetry.flushSync();
3395
- error.handleError(executionError, 'An unexpected error occurred during command execution');
3396
- }
3397
- await telemetry.shutdown();
3398
- }
3399
- main();
3400
- export { main };
2
+ export { main } from "./145.mjs";