@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.
- package/dist/index.js +80 -7
- 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
|
-
|
|
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 = () =>
|
|
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);
|