@c15t/cli 2.0.0-rc.4 → 2.0.0-rc.6

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