@embeddable.com/init 0.1.22 → 0.1.24

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 (2) hide show
  1. package/dist/index.js +80 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9,6 +9,42 @@ import degit from "degit";
9
9
  import prompts from "prompts";
10
10
  import terminalLink from "terminal-link";
11
11
  import open from "open";
12
+
13
+ // src/analytics.ts
14
+ import crypto from "crypto";
15
+ var deviceId = crypto.randomUUID();
16
+ function getAnalyticsUrl(region) {
17
+ if (region) {
18
+ return `https://api.${region.toLowerCase()}.embeddable.com/user-analytics`;
19
+ }
20
+ return "https://api.eu.embeddable.com/user-analytics";
21
+ }
22
+ function trackEvent(name, properties, region, apiKey) {
23
+ try {
24
+ const url = getAnalyticsUrl(region);
25
+ const body = JSON.stringify({
26
+ eventType: name,
27
+ deviceId,
28
+ eventProperties: properties ?? {}
29
+ });
30
+ const headers = { "Content-Type": "application/json" };
31
+ if (apiKey) {
32
+ headers["Workspace-Api-Key"] = apiKey;
33
+ }
34
+ fetch(url, {
35
+ method: "POST",
36
+ headers,
37
+ body
38
+ }).catch(() => {
39
+ });
40
+ } catch {
41
+ }
42
+ }
43
+ async function flushAndWait(timeoutMs = 1e3) {
44
+ await new Promise((resolve) => setTimeout(resolve, timeoutMs));
45
+ }
46
+
47
+ // src/index.ts
12
48
  var REPO_URL = "embeddable-hq/remarkable-pro-boilerplate";
13
49
  var DEFAULT_FOLDER = "embeddable-repo";
14
50
  var TYPEWRITER_SPEED = 10;
@@ -17,8 +53,14 @@ var WORKSPACE_URLS = {
17
53
  EU: "https://app.eu.embeddable.com"
18
54
  };
19
55
  var INVALID_FOLDER_CHARS = /[<>:"/\\|?*\x00-\x1f]/;
20
- function exit(message) {
56
+ var exiting = false;
57
+ var currentStage = "init";
58
+ async function exit(message) {
59
+ if (exiting) return void 0;
60
+ exiting = true;
21
61
  if (message) console.log(message);
62
+ trackEvent("F1_Cli_Cancelled", { stage: currentStage });
63
+ await flushAndWait();
22
64
  printDocsHint();
23
65
  process.exit(0);
24
66
  }
@@ -62,7 +104,9 @@ var LOGO = `
62
104
  \u2580\u2580\u2588\u2588\u2588\u2588\u2580\u2580 \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D
63
105
  `;
64
106
  async function main() {
65
- const onCancel = () => exit("\nSetup cancelled.\n");
107
+ const onCancel = () => {
108
+ exit("\nSetup cancelled.\n");
109
+ };
66
110
  console.log(chalk.white(LOGO));
67
111
  await typewriter("Welcome to Embeddable!\n\n", chalk.bold, TYPEWRITER_SPEED);
68
112
  await typewriter("Embeddable stores your ", void 0, TYPEWRITER_SPEED);
@@ -85,7 +129,9 @@ async function main() {
85
129
  await typewriter(" and ", void 0, TYPEWRITER_SPEED);
86
130
  await typewriter("themes", chalk.bold, TYPEWRITER_SPEED);
87
131
  await typewriter(" (in your current directory) to help you create your first Embeddable dashboard.\n\n", void 0, TYPEWRITER_SPEED);
132
+ trackEvent("F1_Cli_Started");
88
133
  const cwd = process.cwd();
134
+ currentStage = "dir_confirm";
89
135
  const { confirmDir } = await prompts(
90
136
  {
91
137
  type: "confirm",
@@ -95,9 +141,11 @@ async function main() {
95
141
  },
96
142
  { onCancel }
97
143
  );
144
+ trackEvent("F1_Dir_Confirmed", { accepted: !!confirmDir });
98
145
  if (!confirmDir) {
99
- exit("\nRun this command from the directory where you'd like to create your project.\n");
146
+ await exit("\nRun this command from the directory where you'd like to create your project.\n");
100
147
  }
148
+ currentStage = "folder_name";
101
149
  const { folderName } = await prompts(
102
150
  {
103
151
  type: "text",
@@ -109,18 +157,23 @@ async function main() {
109
157
  { onCancel }
110
158
  );
111
159
  if (!folderName) {
112
- exit("\nSetup cancelled.\n");
160
+ await exit("\nSetup cancelled.\n");
113
161
  }
162
+ trackEvent("F1_Folder_Named");
114
163
  const projectPath = path.join(cwd, folderName);
115
164
  console.log(chalk.dim("\nDownloading boilerplate..."));
165
+ const startRepo = Date.now();
116
166
  try {
117
167
  const emitter = degit(REPO_URL, { cache: false, force: true });
118
168
  await emitter.clone(projectPath);
169
+ trackEvent("F1_Repo_Downloaded", { duration_ms: Date.now() - startRepo });
119
170
  } catch (error) {
120
171
  if (fs.existsSync(projectPath)) {
121
172
  fs.rmSync(projectPath, { recursive: true });
122
173
  }
123
174
  const message = error instanceof Error ? error.message : "Unknown error";
175
+ trackEvent("F1_Cli_Error", { stage: "repo_download", error: message });
176
+ await flushAndWait();
124
177
  console.error(chalk.red(`
125
178
  Failed to download boilerplate: ${message}
126
179
  `));
@@ -135,13 +188,18 @@ Failed to download boilerplate: ${message}
135
188
  );
136
189
  }
137
190
  console.log(chalk.dim("Installing dependencies...\n"));
191
+ const startDeps = Date.now();
138
192
  try {
139
193
  execSync("npm install", { cwd: projectPath, stdio: "inherit" });
194
+ trackEvent("F1_Deps_Installed", { duration_ms: Date.now() - startDeps });
140
195
  } catch {
196
+ trackEvent("F1_Cli_Error", { stage: "deps_install", error: "npm install failed" });
197
+ await flushAndWait();
141
198
  console.error(chalk.red("\nnpm install failed.\n"));
142
199
  printDocsHint();
143
200
  process.exit(1);
144
201
  }
202
+ currentStage = "api_key";
145
203
  console.log(`
146
204
  `);
147
205
  const { apiKey } = await prompts(
@@ -162,11 +220,13 @@ Paste your API Key here:`,
162
220
  { onCancel }
163
221
  );
164
222
  if (!apiKey) {
165
- exit("\nSetup cancelled.\n");
223
+ await exit("\nSetup cancelled.\n");
166
224
  }
225
+ trackEvent("F1_Api_Key_Entered", void 0, void 0, apiKey.trim());
167
226
  const embeddableDir = path.join(projectPath, ".embeddable");
168
227
  fs.mkdirSync(embeddableDir, { recursive: true });
169
228
  fs.writeFileSync(path.join(embeddableDir, ".api-key"), apiKey.trim());
229
+ currentStage = "region";
170
230
  console.log("");
171
231
  const regionResponse = await prompts(
172
232
  {
@@ -183,8 +243,9 @@ Paste your API Key here:`,
183
243
  );
184
244
  const region = regionResponse.region;
185
245
  if (!region) {
186
- exit("\nSetup cancelled.\n");
246
+ await exit("\nSetup cancelled.\n");
187
247
  }
248
+ trackEvent("F1_Region_Selected", { region }, region, apiKey.trim());
188
249
  if (region === "EU") {
189
250
  const configPath = path.join(projectPath, "embeddable.config.ts");
190
251
  try {
@@ -211,20 +272,28 @@ Paste your API Key here:`,
211
272
  }
212
273
  }
213
274
  console.log(chalk.dim("\nBuilding bundle..."));
275
+ const startBuild = Date.now();
214
276
  try {
215
277
  execSync("npm run embeddable:build", { cwd: projectPath, stdio: "inherit" });
278
+ trackEvent("F1_Bundle_Built", { duration_ms: Date.now() - startBuild }, region, apiKey.trim());
216
279
  } catch {
280
+ trackEvent("F1_Cli_Error", { stage: "bundle_build", error: "build failed" }, region, apiKey.trim());
281
+ await flushAndWait();
217
282
  console.error(chalk.red("\nFailed to build bundle.\n"));
218
283
  printDocsHint();
219
284
  process.exit(1);
220
285
  }
221
286
  console.log(chalk.dim("Pushing bundle to workspace..."));
287
+ const startPush = Date.now();
222
288
  try {
223
289
  execSync(
224
290
  `npm run embeddable:push -- --api-key ${apiKey.trim()} --email "no-reply@embeddable.com" --message "npx @embeddable.com/init"`,
225
291
  { cwd: projectPath, stdio: "inherit" }
226
292
  );
293
+ trackEvent("F1_Bundle_Pushed", { duration_ms: Date.now() - startPush }, region, apiKey.trim());
227
294
  } catch {
295
+ trackEvent("F1_Cli_Error", { stage: "bundle_push", error: "push failed" }, region, apiKey.trim());
296
+ await flushAndWait();
228
297
  console.error(chalk.red("\nFailed to push bundle to workspace.\n"));
229
298
  printDocsHint();
230
299
  process.exit(1);
@@ -245,9 +314,13 @@ Success!
245
314
  `);
246
315
  console.log(`Follow the guide here to create your first Embeddable dashboard: ${chalk.cyan(docsLink)}
247
316
  `);
317
+ trackEvent("F1_Cli_Completed", { region }, region, apiKey.trim());
318
+ await flushAndWait();
248
319
  await open(docsUrl);
249
320
  }
250
- main().catch((error) => {
321
+ main().catch(async (error) => {
322
+ trackEvent("F1_Cli_Error", { stage: currentStage, error: error instanceof Error ? error.message : "Unknown error" });
323
+ await flushAndWait();
251
324
  console.error(chalk.red("An unexpected error occurred:"), error);
252
325
  printDocsHint();
253
326
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embeddable.com/init",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "CLI tool for Embeddable",
5
5
  "type": "module",
6
6
  "bin": {