@embeddables/cli 0.8.0 → 0.8.1

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 (255) hide show
  1. package/dist/auth/index.d.ts +43 -0
  2. package/dist/auth/index.d.ts.map +1 -0
  3. package/dist/auth/index.js +102 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +210 -0
  7. package/dist/command-history.d.ts +13 -0
  8. package/dist/command-history.d.ts.map +1 -0
  9. package/dist/command-history.js +34 -0
  10. package/dist/commands/branch.d.ts +4 -0
  11. package/dist/commands/branch.d.ts.map +1 -0
  12. package/dist/commands/branch.js +67 -0
  13. package/dist/commands/build-workbench.d.ts +5 -0
  14. package/dist/commands/build-workbench.d.ts.map +1 -0
  15. package/dist/commands/build-workbench.js +116 -0
  16. package/dist/commands/build.d.ts +8 -0
  17. package/dist/commands/build.d.ts.map +1 -0
  18. package/dist/commands/build.js +60 -0
  19. package/dist/commands/builder-open.d.ts +4 -0
  20. package/dist/commands/builder-open.d.ts.map +1 -0
  21. package/dist/commands/builder-open.js +74 -0
  22. package/dist/commands/dev.d.ts +12 -0
  23. package/dist/commands/dev.d.ts.map +1 -0
  24. package/dist/commands/dev.js +226 -0
  25. package/dist/commands/diff.d.ts +76 -0
  26. package/dist/commands/diff.d.ts.map +1 -0
  27. package/dist/commands/diff.js +653 -0
  28. package/dist/commands/experiments-connect.d.ts +6 -0
  29. package/dist/commands/experiments-connect.d.ts.map +1 -0
  30. package/dist/commands/experiments-connect.js +140 -0
  31. package/dist/commands/feedback.d.ts +29 -0
  32. package/dist/commands/feedback.d.ts.map +1 -0
  33. package/dist/commands/feedback.js +267 -0
  34. package/dist/commands/init.d.ts +5 -0
  35. package/dist/commands/init.d.ts.map +1 -0
  36. package/dist/commands/init.js +384 -0
  37. package/dist/commands/inspect.d.ts +9 -0
  38. package/dist/commands/inspect.d.ts.map +1 -0
  39. package/dist/commands/inspect.js +293 -0
  40. package/dist/commands/login.d.ts +2 -0
  41. package/dist/commands/login.d.ts.map +1 -0
  42. package/dist/commands/login.js +117 -0
  43. package/dist/commands/logout.d.ts +2 -0
  44. package/dist/commands/logout.d.ts.map +1 -0
  45. package/dist/commands/logout.js +19 -0
  46. package/dist/commands/pull.d.ts +16 -0
  47. package/dist/commands/pull.d.ts.map +1 -0
  48. package/dist/commands/pull.js +395 -0
  49. package/dist/commands/save.d.ts +30 -0
  50. package/dist/commands/save.d.ts.map +1 -0
  51. package/dist/commands/save.js +597 -0
  52. package/dist/commands/upgrade.d.ts +2 -0
  53. package/dist/commands/upgrade.d.ts.map +1 -0
  54. package/dist/commands/upgrade.js +50 -0
  55. package/dist/compiler/errors.d.ts +20 -0
  56. package/dist/compiler/errors.d.ts.map +1 -0
  57. package/dist/compiler/errors.js +35 -0
  58. package/dist/compiler/evalStatic.d.ts +3 -0
  59. package/dist/compiler/evalStatic.d.ts.map +1 -0
  60. package/dist/compiler/evalStatic.js +57 -0
  61. package/dist/compiler/flatten.js +1 -0
  62. package/dist/compiler/helpers/duplicateIds.d.ts +9 -0
  63. package/dist/compiler/helpers/duplicateIds.d.ts.map +1 -0
  64. package/dist/compiler/helpers/duplicateIds.js +71 -0
  65. package/dist/compiler/helpers/numericLeadingKeys.d.ts +8 -0
  66. package/dist/compiler/helpers/numericLeadingKeys.d.ts.map +1 -0
  67. package/dist/compiler/helpers/numericLeadingKeys.js +17 -0
  68. package/dist/compiler/index.d.ts +18 -0
  69. package/dist/compiler/index.d.ts.map +1 -0
  70. package/dist/compiler/index.js +1272 -0
  71. package/dist/compiler/parsePage.d.ts +15 -0
  72. package/dist/compiler/parsePage.d.ts.map +1 -0
  73. package/dist/compiler/parsePage.js +654 -0
  74. package/dist/compiler/registry.d.ts +4 -0
  75. package/dist/compiler/registry.d.ts.map +1 -0
  76. package/dist/compiler/registry.js +44 -0
  77. package/dist/compiler/reverse.d.ts +23 -0
  78. package/dist/compiler/reverse.d.ts.map +1 -0
  79. package/dist/compiler/reverse.js +1920 -0
  80. package/dist/compiler/types.d.ts +21 -0
  81. package/dist/compiler/types.d.ts.map +1 -0
  82. package/dist/compiler/types.js +1 -0
  83. package/dist/components/index.d.ts +21 -0
  84. package/dist/components/index.d.ts.map +1 -0
  85. package/dist/components/index.js +21 -0
  86. package/dist/components/primitives/BaseComponent.d.ts +33 -0
  87. package/dist/components/primitives/BaseComponent.d.ts.map +1 -0
  88. package/dist/components/primitives/BaseComponent.js +26 -0
  89. package/dist/components/primitives/BookMeeting.d.ts +18 -0
  90. package/dist/components/primitives/BookMeeting.d.ts.map +1 -0
  91. package/dist/components/primitives/BookMeeting.js +5 -0
  92. package/dist/components/primitives/Chart.d.ts +41 -0
  93. package/dist/components/primitives/Chart.d.ts.map +1 -0
  94. package/dist/components/primitives/Chart.js +5 -0
  95. package/dist/components/primitives/Container.d.ts +8 -0
  96. package/dist/components/primitives/Container.d.ts.map +1 -0
  97. package/dist/components/primitives/Container.js +5 -0
  98. package/dist/components/primitives/CustomButton.d.ts +37 -0
  99. package/dist/components/primitives/CustomButton.d.ts.map +1 -0
  100. package/dist/components/primitives/CustomButton.js +10 -0
  101. package/dist/components/primitives/CustomHTML.d.ts +8 -0
  102. package/dist/components/primitives/CustomHTML.d.ts.map +1 -0
  103. package/dist/components/primitives/CustomHTML.js +5 -0
  104. package/dist/components/primitives/FileUpload.d.ts +18 -0
  105. package/dist/components/primitives/FileUpload.d.ts.map +1 -0
  106. package/dist/components/primitives/FileUpload.js +16 -0
  107. package/dist/components/primitives/InputBox.d.ts +34 -0
  108. package/dist/components/primitives/InputBox.d.ts.map +1 -0
  109. package/dist/components/primitives/InputBox.js +25 -0
  110. package/dist/components/primitives/Lottie.d.ts +11 -0
  111. package/dist/components/primitives/Lottie.d.ts.map +1 -0
  112. package/dist/components/primitives/Lottie.js +5 -0
  113. package/dist/components/primitives/MediaEmbed.d.ts +13 -0
  114. package/dist/components/primitives/MediaEmbed.d.ts.map +1 -0
  115. package/dist/components/primitives/MediaEmbed.js +6 -0
  116. package/dist/components/primitives/MediaImage.d.ts +8 -0
  117. package/dist/components/primitives/MediaImage.d.ts.map +1 -0
  118. package/dist/components/primitives/MediaImage.js +5 -0
  119. package/dist/components/primitives/OptionSelector.d.ts +38 -0
  120. package/dist/components/primitives/OptionSelector.d.ts.map +1 -0
  121. package/dist/components/primitives/OptionSelector.js +8 -0
  122. package/dist/components/primitives/PaypalCheckout.d.ts +25 -0
  123. package/dist/components/primitives/PaypalCheckout.d.ts.map +1 -0
  124. package/dist/components/primitives/PaypalCheckout.js +5 -0
  125. package/dist/components/primitives/PlainText.d.ts +6 -0
  126. package/dist/components/primitives/PlainText.d.ts.map +1 -0
  127. package/dist/components/primitives/PlainText.js +5 -0
  128. package/dist/components/primitives/ProgressBar.d.ts +15 -0
  129. package/dist/components/primitives/ProgressBar.d.ts.map +1 -0
  130. package/dist/components/primitives/ProgressBar.js +5 -0
  131. package/dist/components/primitives/RichText.d.ts +6 -0
  132. package/dist/components/primitives/RichText.d.ts.map +1 -0
  133. package/dist/components/primitives/RichText.js +5 -0
  134. package/dist/components/primitives/RichTextMarkdown.d.ts +6 -0
  135. package/dist/components/primitives/RichTextMarkdown.d.ts.map +1 -0
  136. package/dist/components/primitives/RichTextMarkdown.js +5 -0
  137. package/dist/components/primitives/Rive.d.ts +16 -0
  138. package/dist/components/primitives/Rive.d.ts.map +1 -0
  139. package/dist/components/primitives/Rive.js +8 -0
  140. package/dist/components/primitives/StripeCheckout.d.ts +52 -0
  141. package/dist/components/primitives/StripeCheckout.d.ts.map +1 -0
  142. package/dist/components/primitives/StripeCheckout.js +5 -0
  143. package/dist/components/primitives/StripeCheckout2.d.ts +30 -0
  144. package/dist/components/primitives/StripeCheckout2.d.ts.map +1 -0
  145. package/dist/components/primitives/StripeCheckout2.js +7 -0
  146. package/dist/config/index.d.ts +23 -0
  147. package/dist/config/index.d.ts.map +1 -0
  148. package/dist/config/index.js +42 -0
  149. package/dist/constants.d.ts +9 -0
  150. package/dist/constants.d.ts.map +1 -0
  151. package/dist/constants.js +9 -0
  152. package/dist/helpers/TEMP helpers file.d.ts +1 -0
  153. package/dist/helpers/TEMP helpers file.d.ts.map +1 -0
  154. package/dist/helpers/TEMP helpers file.js +1 -0
  155. package/dist/helpers/dates.d.ts +5 -0
  156. package/dist/helpers/dates.d.ts.map +1 -0
  157. package/dist/helpers/dates.js +7 -0
  158. package/dist/helpers/json.d.ts +47 -0
  159. package/dist/helpers/json.d.ts.map +1 -0
  160. package/dist/helpers/json.js +622 -0
  161. package/dist/helpers/prompt.d.ts +15 -0
  162. package/dist/helpers/prompt.d.ts.map +1 -0
  163. package/dist/helpers/prompt.js +35 -0
  164. package/dist/helpers/utils.d.ts +13 -0
  165. package/dist/helpers/utils.d.ts.map +1 -0
  166. package/dist/helpers/utils.js +28 -0
  167. package/dist/logger.d.ts +11 -0
  168. package/dist/logger.d.ts.map +1 -0
  169. package/dist/logger.js +21 -0
  170. package/dist/patches/prompts-escape.d.ts +14 -0
  171. package/dist/patches/prompts-escape.d.ts.map +1 -0
  172. package/dist/patches/prompts-escape.js +23 -0
  173. package/dist/prompts/branches.d.ts +20 -0
  174. package/dist/prompts/branches.d.ts.map +1 -0
  175. package/dist/prompts/branches.js +86 -0
  176. package/dist/prompts/embeddables.d.ts +43 -0
  177. package/dist/prompts/embeddables.d.ts.map +1 -0
  178. package/dist/prompts/embeddables.js +200 -0
  179. package/dist/prompts/experiments.d.ts +28 -0
  180. package/dist/prompts/experiments.d.ts.map +1 -0
  181. package/dist/prompts/experiments.js +89 -0
  182. package/dist/prompts/index.d.ts +11 -0
  183. package/dist/prompts/index.d.ts.map +1 -0
  184. package/dist/prompts/index.js +6 -0
  185. package/dist/prompts/projects.d.ts +22 -0
  186. package/dist/prompts/projects.d.ts.map +1 -0
  187. package/dist/prompts/projects.js +92 -0
  188. package/dist/prompts/versions.d.ts +18 -0
  189. package/dist/prompts/versions.d.ts.map +1 -0
  190. package/dist/prompts/versions.js +95 -0
  191. package/dist/proxy/injectApiInterceptor.d.ts +6 -0
  192. package/dist/proxy/injectApiInterceptor.d.ts.map +1 -0
  193. package/dist/proxy/injectApiInterceptor.js +66 -0
  194. package/dist/proxy/injectReload.d.ts +2 -0
  195. package/dist/proxy/injectReload.d.ts.map +1 -0
  196. package/dist/proxy/injectReload.js +14 -0
  197. package/dist/proxy/injectWorkbench.d.ts +5 -0
  198. package/dist/proxy/injectWorkbench.d.ts.map +1 -0
  199. package/dist/proxy/injectWorkbench.js +22 -0
  200. package/dist/proxy/server.d.ts +11 -0
  201. package/dist/proxy/server.d.ts.map +1 -0
  202. package/dist/proxy/server.js +304 -0
  203. package/dist/proxy/sse.d.ts +5 -0
  204. package/dist/proxy/sse.d.ts.map +1 -0
  205. package/dist/proxy/sse.js +17 -0
  206. package/dist/sentry-context.d.ts +48 -0
  207. package/dist/sentry-context.d.ts.map +1 -0
  208. package/dist/sentry-context.js +156 -0
  209. package/dist/stdout.d.ts +61 -0
  210. package/dist/stdout.d.ts.map +1 -0
  211. package/dist/stdout.js +163 -0
  212. package/dist/types-builder.d.ts +800 -0
  213. package/dist/types-builder.d.ts.map +1 -0
  214. package/dist/types-builder.js +20 -0
  215. package/dist/workbench/ActionsPanel.d.ts +6 -0
  216. package/dist/workbench/ActionsPanel.d.ts.map +1 -0
  217. package/dist/workbench/ActionsPanel.js +47 -0
  218. package/dist/workbench/AutofillPanel.d.ts +6 -0
  219. package/dist/workbench/AutofillPanel.d.ts.map +1 -0
  220. package/dist/workbench/AutofillPanel.js +543 -0
  221. package/dist/workbench/ComputedFieldsPanel.d.ts +6 -0
  222. package/dist/workbench/ComputedFieldsPanel.d.ts.map +1 -0
  223. package/dist/workbench/ComputedFieldsPanel.js +31 -0
  224. package/dist/workbench/ExperimentsPanel.d.ts +6 -0
  225. package/dist/workbench/ExperimentsPanel.d.ts.map +1 -0
  226. package/dist/workbench/ExperimentsPanel.js +182 -0
  227. package/dist/workbench/FieldEditorPanel.d.ts +9 -0
  228. package/dist/workbench/FieldEditorPanel.d.ts.map +1 -0
  229. package/dist/workbench/FieldEditorPanel.js +650 -0
  230. package/dist/workbench/InspectorPanel.d.ts +6 -0
  231. package/dist/workbench/InspectorPanel.d.ts.map +1 -0
  232. package/dist/workbench/InspectorPanel.js +341 -0
  233. package/dist/workbench/PageNavigator.d.ts +6 -0
  234. package/dist/workbench/PageNavigator.d.ts.map +1 -0
  235. package/dist/workbench/PageNavigator.js +123 -0
  236. package/dist/workbench/SchemaPanel.d.ts +6 -0
  237. package/dist/workbench/SchemaPanel.d.ts.map +1 -0
  238. package/dist/workbench/SchemaPanel.js +222 -0
  239. package/dist/workbench/UserDataPanel.d.ts +6 -0
  240. package/dist/workbench/UserDataPanel.d.ts.map +1 -0
  241. package/dist/workbench/UserDataPanel.js +350 -0
  242. package/dist/workbench/WorkbenchApp.d.ts +7 -0
  243. package/dist/workbench/WorkbenchApp.d.ts.map +1 -0
  244. package/dist/workbench/WorkbenchApp.js +193 -0
  245. package/dist/workbench/cloudflare-worker/README.md +31 -0
  246. package/dist/workbench/cloudflare-worker/public/workbench.css +1614 -0
  247. package/dist/workbench/cloudflare-worker/public/workbench.js +77 -0
  248. package/dist/workbench/cloudflare-worker/worker.js +40 -0
  249. package/dist/workbench/cloudflare-worker/wrangler.toml +10 -0
  250. package/dist/workbench/index.d.ts +10 -0
  251. package/dist/workbench/index.d.ts.map +1 -0
  252. package/dist/workbench/index.js +44 -0
  253. package/dist/workbench/workbench.css +1614 -0
  254. package/dist/workbench/workbench.js +77 -0
  255. package/package.json +1 -1
@@ -0,0 +1,140 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { isLoggedIn } from '../auth/index.js';
4
+ import { getProjectId, writeProjectConfig } from '../config/index.js';
5
+ import { promptForProject, promptForLocalEmbeddable, promptForExperiment, } from '../prompts/index.js';
6
+ import { createLogger, exit } from '../logger.js';
7
+ import { getSentryContextFromEmbeddableConfig, getSentryContextFromProjectConfig, setSentryContext, } from '../sentry-context.js';
8
+ import * as stdout from '../stdout.js';
9
+ import { inferEmbeddableFromCwd } from '../helpers/utils.js';
10
+ export async function runExperimentsConnect(opts) {
11
+ const logger = createLogger('runExperimentsConnect');
12
+ try {
13
+ await runExperimentsConnectInner(opts);
14
+ }
15
+ catch (error) {
16
+ if (error instanceof Error) {
17
+ stdout.error(`Connect failed: ${error.message}`);
18
+ }
19
+ else {
20
+ stdout.error('Connect failed with an unexpected error.');
21
+ }
22
+ logger.error('experiments connect failed', {
23
+ message: error instanceof Error ? error.message : 'unexpected error',
24
+ });
25
+ await exit(1);
26
+ }
27
+ }
28
+ async function runExperimentsConnectInner(opts) {
29
+ const logger = createLogger('runExperimentsConnect');
30
+ // 1. Check login (needed for fetching experiments from Supabase)
31
+ if (!isLoggedIn()) {
32
+ stdout.warn('Not logged in.');
33
+ stdout.dim('Run "embeddables login" first.');
34
+ logger.error('not logged in');
35
+ await exit(1);
36
+ }
37
+ // 2. Get project ID (needed for experiment list)
38
+ let projectId = getProjectId();
39
+ if (!projectId) {
40
+ stdout.step('No project configured. Fetching projects…');
41
+ const selectedProject = await promptForProject();
42
+ if (!selectedProject) {
43
+ await exit(1);
44
+ return;
45
+ }
46
+ projectId = selectedProject.id;
47
+ writeProjectConfig({
48
+ org_id: selectedProject.org_id || undefined,
49
+ org_title: selectedProject.org_title || undefined,
50
+ project_id: projectId,
51
+ project_name: selectedProject.title || undefined,
52
+ });
53
+ stdout.success('Saved project to embeddables.json');
54
+ stdout.gap();
55
+ }
56
+ // 4. Get embeddable ID (from option, cwd inference, or interactive prompt)
57
+ const inferred = inferEmbeddableFromCwd();
58
+ let embeddableId = opts.id ?? inferred?.embeddableId;
59
+ if (inferred && !opts.id && embeddableId) {
60
+ process.chdir(inferred.projectRoot);
61
+ }
62
+ setSentryContext(getSentryContextFromProjectConfig());
63
+ if (!embeddableId) {
64
+ const selected = await promptForLocalEmbeddable({
65
+ message: 'Select an embeddable to connect the experiment to:',
66
+ });
67
+ if (!selected) {
68
+ await exit(1);
69
+ return;
70
+ }
71
+ embeddableId = selected;
72
+ stdout.gap();
73
+ }
74
+ if (embeddableId) {
75
+ setSentryContext({
76
+ embeddable: { id: embeddableId },
77
+ ...getSentryContextFromEmbeddableConfig(embeddableId),
78
+ });
79
+ }
80
+ // 5. Get experiment_id and experiment_key (from opts or interactive prompt)
81
+ let experimentId = opts.experimentId;
82
+ let experimentKey = opts.experimentKey;
83
+ if (experimentId && !experimentKey) {
84
+ stdout.error('When using --experiment-id, --experiment-key is also required.');
85
+ logger.error('missing experiment-key flag');
86
+ await exit(1);
87
+ }
88
+ if (experimentKey && !experimentId) {
89
+ stdout.error('When using --experiment-key, --experiment-id is also required.');
90
+ logger.error('missing experiment-id flag');
91
+ await exit(1);
92
+ }
93
+ if (!experimentId || !experimentKey) {
94
+ const selected = await stdout.withSpinner('Fetching experiments…', async () => {
95
+ return promptForExperiment(projectId, {
96
+ message: 'Select an experiment to connect:',
97
+ excludeConnectedTo: embeddableId,
98
+ });
99
+ }, { successText: 'Experiments loaded' });
100
+ if (!selected) {
101
+ await exit(1);
102
+ return;
103
+ }
104
+ experimentId = selected.experiment_id;
105
+ experimentKey = selected.experiment_key;
106
+ stdout.gap();
107
+ }
108
+ // 6. Read config.json
109
+ const configPath = path.join('embeddables', embeddableId, 'config.json');
110
+ if (!fs.existsSync(configPath)) {
111
+ stdout.error(`No config.json found at ${configPath}`);
112
+ stdout.dim('Run "embeddables pull" or "embeddables init" first.');
113
+ logger.error('config not found', { configPath });
114
+ await exit(1);
115
+ }
116
+ let config;
117
+ try {
118
+ const content = fs.readFileSync(configPath, 'utf8');
119
+ config = JSON.parse(content);
120
+ }
121
+ catch {
122
+ stdout.error('Failed to parse config.json.');
123
+ logger.error('failed to parse config');
124
+ await exit(1);
125
+ return;
126
+ }
127
+ // 7. Append to connected_experiments
128
+ const connectedExperiments = Array.isArray(config.connected_experiments) ? [...config.connected_experiments] : [];
129
+ const alreadyConnected = connectedExperiments.some((e) => e.experiment_id === experimentId && e.experiment_key === experimentKey);
130
+ if (alreadyConnected) {
131
+ stdout.warn(`Experiment "${experimentKey}" is already connected to this embeddable.`);
132
+ return;
133
+ }
134
+ connectedExperiments.push({ experiment_id: experimentId, experiment_key: experimentKey });
135
+ config.connected_experiments = connectedExperiments;
136
+ // 8. Write the modified config back
137
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
138
+ stdout.success(`Connected experiment "${experimentKey}" to embeddable`);
139
+ stdout.dim('Run "embeddables save" to persist to the cloud.');
140
+ }
@@ -0,0 +1,29 @@
1
+ export type FeedbackCategory = 'cli' | 'ai' | 'compiler' | 'other';
2
+ export interface RunFeedbackOptions {
3
+ message?: string;
4
+ positive?: boolean;
5
+ negative?: boolean;
6
+ category?: FeedbackCategory;
7
+ }
8
+ export declare function runFeedback(opts: RunFeedbackOptions): Promise<void>;
9
+ export interface FeedbackContext {
10
+ userEmail?: string;
11
+ userName?: string;
12
+ cliVersion?: string;
13
+ nodeVersion?: string;
14
+ platform?: string;
15
+ osRelease?: string;
16
+ arch?: string;
17
+ projectId?: string;
18
+ projectName?: string;
19
+ orgId?: string;
20
+ orgName?: string;
21
+ embeddableId?: string;
22
+ lastCommand?: Record<string, unknown>;
23
+ gitBranch?: string;
24
+ gitDirty?: boolean;
25
+ aiTool?: string;
26
+ }
27
+ export declare function collectFeedbackContext(): FeedbackContext;
28
+ export declare function detectAiTool(): string | undefined;
29
+ //# sourceMappingURL=feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../src/commands/feedback.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,IAAI,GAAG,UAAU,GAAG,OAAO,CAAA;AAElE,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAC5B;AAID,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsIzE;AAID,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,sBAAsB,IAAI,eAAe,CA+FxD;AAED,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CA0BjD"}
@@ -0,0 +1,267 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { execSync } from 'node:child_process';
5
+ import * as Sentry from '@sentry/node';
6
+ import { createLogger } from '../logger.js';
7
+ import * as stdout from '../stdout.js';
8
+ import { prompt } from '../helpers/prompt.js';
9
+ import { readProjectConfig } from '../config/index.js';
10
+ import { getLastHistoryEntry } from '../command-history.js';
11
+ import { getSentryContextFromEmbeddableConfig, setSentryContext } from '../sentry-context.js';
12
+ const logger = createLogger('runFeedback');
13
+ const VALID_CATEGORIES = new Set(['cli', 'ai', 'compiler', 'other']);
14
+ export async function runFeedback(opts) {
15
+ // 1. Resolve message
16
+ let message = opts.message;
17
+ if (!message) {
18
+ const res = await prompt({
19
+ type: 'text',
20
+ name: 'value',
21
+ message: "What's your feedback?",
22
+ });
23
+ message = res.value?.trim();
24
+ if (!message) {
25
+ stdout.warn('No feedback provided.');
26
+ return;
27
+ }
28
+ }
29
+ // 2. Resolve sentiment
30
+ let sentiment;
31
+ if (opts.positive) {
32
+ sentiment = 'positive';
33
+ }
34
+ else if (opts.negative) {
35
+ sentiment = 'negative';
36
+ }
37
+ else if (!opts.message) {
38
+ const res = await prompt({
39
+ type: 'select',
40
+ name: 'value',
41
+ message: 'Was this positive or negative?',
42
+ choices: [
43
+ { title: '👍 Positive', value: 'positive' },
44
+ { title: '👎 Negative', value: 'negative' },
45
+ ],
46
+ });
47
+ sentiment = res.value === 'positive' ? 'positive' : 'negative';
48
+ }
49
+ else {
50
+ sentiment = 'negative';
51
+ }
52
+ // 3. Resolve category
53
+ let category = opts.category;
54
+ if (category && !VALID_CATEGORIES.has(category)) {
55
+ stdout.warn(`Invalid category "${category}". Must be one of: cli, ai, compiler, other`);
56
+ category = undefined;
57
+ }
58
+ if (!category && !opts.message) {
59
+ const res = await prompt({
60
+ type: 'select',
61
+ name: 'value',
62
+ message: 'Which area does this relate to?',
63
+ choices: [
64
+ { title: 'CLI command', value: 'cli' },
65
+ { title: 'AI prompts', value: 'ai' },
66
+ { title: 'Compiler', value: 'compiler' },
67
+ { title: 'Other', value: 'other' },
68
+ ],
69
+ });
70
+ category = res.value || undefined;
71
+ }
72
+ // 4. Collect context
73
+ const context = collectFeedbackContext();
74
+ // 5. Set Sentry context and send
75
+ Sentry.setTag('feedback.sentiment', sentiment);
76
+ if (category)
77
+ Sentry.setTag('feedback.category', category);
78
+ Sentry.setContext('feedback', {
79
+ sentiment,
80
+ category: category ?? null,
81
+ });
82
+ if (context.cliVersion)
83
+ Sentry.setTag('cli.version', context.cliVersion);
84
+ if (context.nodeVersion)
85
+ Sentry.setTag('node.version', context.nodeVersion);
86
+ if (context.platform)
87
+ Sentry.setTag('os.platform', context.platform);
88
+ if (context.arch)
89
+ Sentry.setTag('os.arch', context.arch);
90
+ Sentry.setContext('environment', {
91
+ cliVersion: context.cliVersion ?? null,
92
+ nodeVersion: context.nodeVersion ?? null,
93
+ platform: context.platform ?? null,
94
+ osRelease: context.osRelease ?? null,
95
+ arch: context.arch ?? null,
96
+ });
97
+ if (context.projectId || context.orgId) {
98
+ setSentryContext({
99
+ project: context.projectId
100
+ ? { id: context.projectId, title: context.projectName ?? null }
101
+ : undefined,
102
+ org: context.orgId ? { id: context.orgId, title: context.orgName ?? null } : undefined,
103
+ });
104
+ }
105
+ if (context.embeddableId) {
106
+ const embCtx = getSentryContextFromEmbeddableConfig(context.embeddableId);
107
+ setSentryContext({
108
+ embeddable: { id: context.embeddableId },
109
+ ...embCtx,
110
+ });
111
+ }
112
+ if (context.lastCommand) {
113
+ Sentry.setContext('lastCommand', context.lastCommand);
114
+ }
115
+ Sentry.setContext('git', {
116
+ branch: context.gitBranch ?? null,
117
+ dirty: context.gitDirty ?? null,
118
+ });
119
+ if (context.aiTool) {
120
+ Sentry.setTag('ai.tool', context.aiTool);
121
+ Sentry.setContext('ai', { tool: context.aiTool });
122
+ }
123
+ Sentry.captureFeedback({
124
+ message,
125
+ email: context.userEmail ?? undefined,
126
+ name: context.userName ?? undefined,
127
+ });
128
+ await Sentry.flush(5000);
129
+ // 6. Show confirmation
130
+ stdout.gap();
131
+ const icon = sentiment === 'positive' ? '👍' : '👎';
132
+ stdout.success(`Feedback sent ${icon}`);
133
+ stdout.dim('Thanks for helping us improve!');
134
+ logger.info('feedback sent', {
135
+ sentiment,
136
+ category: category ?? 'none',
137
+ hasEmail: !!context.userEmail,
138
+ messageLength: message.length,
139
+ });
140
+ }
141
+ export function collectFeedbackContext() {
142
+ const ctx = {};
143
+ // User email from auth (best effort, no await — read sync from file)
144
+ try {
145
+ const authPath = path.join(os.homedir(), '.embeddables', 'auth.json');
146
+ if (fs.existsSync(authPath)) {
147
+ const raw = JSON.parse(fs.readFileSync(authPath, 'utf8'));
148
+ if (raw.access_token && typeof raw.access_token === 'string') {
149
+ const payload = JSON.parse(Buffer.from(raw.access_token.split('.')[1], 'base64').toString());
150
+ if (typeof payload.email === 'string')
151
+ ctx.userEmail = payload.email;
152
+ if (typeof payload.name === 'string')
153
+ ctx.userName = payload.name;
154
+ }
155
+ }
156
+ }
157
+ catch {
158
+ // auth not available — fine
159
+ }
160
+ // CLI version
161
+ try {
162
+ const pkgPath = path.join(path.dirname(new URL(import.meta.url).pathname), '..', 'package.json');
163
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
164
+ if (typeof pkg.version === 'string')
165
+ ctx.cliVersion = pkg.version;
166
+ }
167
+ catch {
168
+ // ignore
169
+ }
170
+ // Node / OS
171
+ ctx.nodeVersion = process.version;
172
+ ctx.platform = process.platform;
173
+ ctx.osRelease = os.release();
174
+ ctx.arch = process.arch;
175
+ // Project config
176
+ try {
177
+ const config = readProjectConfig();
178
+ if (config?.project_id)
179
+ ctx.projectId = config.project_id;
180
+ if (config?.project_name)
181
+ ctx.projectName = config.project_name;
182
+ if (config?.org_id)
183
+ ctx.orgId = config.org_id;
184
+ if (config?.org_title)
185
+ ctx.orgName = config.org_title;
186
+ }
187
+ catch {
188
+ // ignore
189
+ }
190
+ // Embeddable ID (first local embeddable found)
191
+ try {
192
+ const embeddablesDir = 'embeddables';
193
+ if (fs.existsSync(embeddablesDir)) {
194
+ const entries = fs.readdirSync(embeddablesDir, { withFileTypes: true });
195
+ const firstDir = entries.find((e) => e.isDirectory());
196
+ if (firstDir)
197
+ ctx.embeddableId = firstDir.name;
198
+ }
199
+ }
200
+ catch {
201
+ // ignore
202
+ }
203
+ // Last CLI command
204
+ try {
205
+ const last = getLastHistoryEntry();
206
+ if (last) {
207
+ ctx.lastCommand = { ...last };
208
+ }
209
+ }
210
+ catch {
211
+ // ignore
212
+ }
213
+ // Git branch
214
+ try {
215
+ ctx.gitBranch = execSync('git rev-parse --abbrev-ref HEAD', {
216
+ encoding: 'utf8',
217
+ timeout: 3000,
218
+ stdio: ['pipe', 'pipe', 'pipe'],
219
+ }).trim();
220
+ }
221
+ catch {
222
+ // not in a git repo
223
+ }
224
+ // Git dirty
225
+ try {
226
+ const status = execSync('git status --porcelain', {
227
+ encoding: 'utf8',
228
+ timeout: 3000,
229
+ stdio: ['pipe', 'pipe', 'pipe'],
230
+ }).trim();
231
+ ctx.gitDirty = status.length > 0;
232
+ }
233
+ catch {
234
+ // not in a git repo
235
+ }
236
+ // AI tool detection
237
+ ctx.aiTool = detectAiTool();
238
+ return ctx;
239
+ }
240
+ export function detectAiTool() {
241
+ const envChecks = [
242
+ ['CURSOR_', 'cursor'],
243
+ ['CLAUDE_', 'claude-code'],
244
+ ['WINDSURF_', 'windsurf'],
245
+ ];
246
+ for (const [prefix, name] of envChecks) {
247
+ for (const key of Object.keys(process.env)) {
248
+ if (key.startsWith(prefix))
249
+ return name;
250
+ }
251
+ }
252
+ const dirChecks = [
253
+ ['.cursor', 'cursor'],
254
+ ['.claude', 'claude-code'],
255
+ ['.windsurf', 'windsurf'],
256
+ ];
257
+ for (const [dir, name] of dirChecks) {
258
+ try {
259
+ if (fs.existsSync(path.join(process.cwd(), dir)))
260
+ return name;
261
+ }
262
+ catch {
263
+ // ignore
264
+ }
265
+ }
266
+ return undefined;
267
+ }
@@ -0,0 +1,5 @@
1
+ export declare function runInit(opts: {
2
+ projectId?: string;
3
+ yes?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAoIA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAkSxE"}