@embeddable.com/init 0.1.0 → 0.1.2
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 +142 -55
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -7,45 +7,71 @@ import path from "path";
|
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
import degit from "degit";
|
|
9
9
|
import prompts from "prompts";
|
|
10
|
+
import terminalLink from "terminal-link";
|
|
10
11
|
var REPO_URL = "embeddable-hq/remarkable-pro-boilerplate";
|
|
11
12
|
var DEFAULT_FOLDER = "embeddable-repo";
|
|
12
|
-
var
|
|
13
|
-
US: "https://app.us.embeddable.com
|
|
14
|
-
EU: "https://app.eu.embeddable.com
|
|
13
|
+
var WORKSPACE_URLS = {
|
|
14
|
+
US: "https://app.us.embeddable.com",
|
|
15
|
+
EU: "https://app.eu.embeddable.com"
|
|
15
16
|
};
|
|
17
|
+
var INVALID_FOLDER_CHARS = /[<>:"/\\|?*\x00-\x1f]/;
|
|
16
18
|
function exit(message) {
|
|
17
19
|
if (message) console.log(message);
|
|
18
20
|
process.exit(0);
|
|
19
21
|
}
|
|
22
|
+
function printDocsHint() {
|
|
23
|
+
const docsUrl = "https://docs.embeddable.com";
|
|
24
|
+
const docsLink = terminalLink(docsUrl, docsUrl, { fallback: (text) => text });
|
|
25
|
+
console.log(`If you get stuck, please follow our 'Quick-start guide' at ${chalk.cyan(docsLink)}
|
|
26
|
+
`);
|
|
27
|
+
}
|
|
28
|
+
function validateFolderName(value, cwd) {
|
|
29
|
+
const trimmed = value.trim();
|
|
30
|
+
if (!trimmed) return "Folder name is required";
|
|
31
|
+
if (INVALID_FOLDER_CHARS.test(trimmed)) {
|
|
32
|
+
return "Folder name contains invalid characters";
|
|
33
|
+
}
|
|
34
|
+
if (trimmed.startsWith(".") || trimmed.startsWith("-")) {
|
|
35
|
+
return "Folder name should not start with . or -";
|
|
36
|
+
}
|
|
37
|
+
if (fs.existsSync(path.join(cwd, trimmed))) {
|
|
38
|
+
return `Folder "${trimmed}" already exists`;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
function isValidUuid(value) {
|
|
43
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
44
|
+
return uuidRegex.test(value.trim());
|
|
45
|
+
}
|
|
20
46
|
async function main() {
|
|
21
|
-
|
|
47
|
+
const onCancel = () => exit("\nSetup cancelled.\n");
|
|
22
48
|
console.log(chalk.bold("\nWelcome to Embeddable!\n"));
|
|
49
|
+
console.log(`Embeddable stores your ${chalk.bold("charting components")}, ${chalk.bold("data models")} and ${chalk.bold("themes")} in code, so you have ${chalk.bold("full control")} over the ${chalk.bold("look-and-feel")} and the ${chalk.bold("data")} powering your dashboards.
|
|
50
|
+
`);
|
|
51
|
+
console.log("This tool helps you get set up to create your first Embeddable dashboard.\n");
|
|
23
52
|
const cwd = process.cwd();
|
|
24
|
-
const { confirmDir } = await prompts(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
53
|
+
const { confirmDir } = await prompts(
|
|
54
|
+
{
|
|
55
|
+
type: "confirm",
|
|
56
|
+
name: "confirmDir",
|
|
57
|
+
message: `Ok to create a new Project subfolder in your current directory ${chalk.cyan(cwd)}?`,
|
|
58
|
+
initial: true
|
|
59
|
+
},
|
|
60
|
+
{ onCancel }
|
|
61
|
+
);
|
|
33
62
|
if (!confirmDir) {
|
|
34
63
|
exit("\nRun this command from the directory where you'd like to create your project.\n");
|
|
35
64
|
}
|
|
36
|
-
const { folderName } = await prompts(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
});
|
|
65
|
+
const { folderName } = await prompts(
|
|
66
|
+
{
|
|
67
|
+
type: "text",
|
|
68
|
+
name: "folderName",
|
|
69
|
+
message: "Project folder name:",
|
|
70
|
+
initial: DEFAULT_FOLDER,
|
|
71
|
+
validate: (value) => validateFolderName(value, cwd)
|
|
72
|
+
},
|
|
73
|
+
{ onCancel }
|
|
74
|
+
);
|
|
49
75
|
if (!folderName) {
|
|
50
76
|
exit("\nSetup cancelled.\n");
|
|
51
77
|
}
|
|
@@ -62,6 +88,7 @@ async function main() {
|
|
|
62
88
|
console.error(chalk.red(`
|
|
63
89
|
Failed to download boilerplate: ${message}
|
|
64
90
|
`));
|
|
91
|
+
printDocsHint();
|
|
65
92
|
process.exit(1);
|
|
66
93
|
}
|
|
67
94
|
try {
|
|
@@ -71,57 +98,117 @@ Failed to download boilerplate: ${message}
|
|
|
71
98
|
chalk.yellow("\nWarning: Could not initialize git repository. Is git installed?")
|
|
72
99
|
);
|
|
73
100
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
101
|
+
console.log(chalk.dim("Installing dependencies...\n"));
|
|
102
|
+
try {
|
|
103
|
+
execSync("npm install", { cwd: projectPath, stdio: "inherit" });
|
|
104
|
+
} catch {
|
|
105
|
+
console.error(chalk.red("\nnpm install failed.\n"));
|
|
106
|
+
printDocsHint();
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
console.log(`
|
|
110
|
+
`);
|
|
111
|
+
const { apiKey } = await prompts(
|
|
112
|
+
{
|
|
113
|
+
type: "password",
|
|
114
|
+
name: "apiKey",
|
|
115
|
+
message: `You'll need an API Key to push this code bundle to your workspace (to create an account, head to ${chalk.cyan("https://embeddable.com/start")}).
|
|
116
|
+
Paste your API Key here:`,
|
|
117
|
+
validate: (value) => {
|
|
118
|
+
const trimmed = value.trim();
|
|
119
|
+
if (!trimmed) return "API key is required";
|
|
120
|
+
if (!isValidUuid(trimmed)) return "API key must be a valid UUID";
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{ onCancel }
|
|
125
|
+
);
|
|
126
|
+
if (!apiKey) {
|
|
127
|
+
exit("\nSetup cancelled.\n");
|
|
128
|
+
}
|
|
129
|
+
const embeddableDir = path.join(projectPath, ".embeddable");
|
|
130
|
+
fs.mkdirSync(embeddableDir, { recursive: true });
|
|
131
|
+
fs.writeFileSync(path.join(embeddableDir, ".api-key"), apiKey.trim());
|
|
132
|
+
const regionResponse = await prompts(
|
|
133
|
+
{
|
|
134
|
+
type: "select",
|
|
135
|
+
name: "region",
|
|
136
|
+
message: "Confirm your workspace region:",
|
|
137
|
+
choices: [
|
|
138
|
+
{ title: "US", value: "US" },
|
|
139
|
+
{ title: "EU", value: "EU" }
|
|
140
|
+
],
|
|
141
|
+
initial: 0
|
|
142
|
+
},
|
|
143
|
+
{ onCancel }
|
|
144
|
+
);
|
|
145
|
+
const region = regionResponse.region;
|
|
146
|
+
if (!region) {
|
|
85
147
|
exit("\nSetup cancelled.\n");
|
|
86
148
|
}
|
|
87
|
-
const region = selectedRegion;
|
|
88
149
|
if (region === "EU") {
|
|
89
150
|
const configPath = path.join(projectPath, "embeddable.config.ts");
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
);
|
|
94
|
-
} else {
|
|
95
|
-
let configContent = fs.readFileSync(configPath, "utf-8");
|
|
96
|
-
const originalContent = configContent;
|
|
97
|
-
configContent = configContent.replace(
|
|
151
|
+
try {
|
|
152
|
+
const configContent = fs.readFileSync(configPath, "utf-8");
|
|
153
|
+
let updatedContent = configContent.replace(
|
|
98
154
|
/^(\s*)region:\s*["']US["'],?/m,
|
|
99
155
|
"$1// region: 'US',"
|
|
100
156
|
);
|
|
101
|
-
|
|
157
|
+
updatedContent = updatedContent.replace(
|
|
102
158
|
/^(\s*)\/\/\s*region:\s*["']EU["'],?/m,
|
|
103
159
|
"$1region: 'EU',"
|
|
104
160
|
);
|
|
105
|
-
if (
|
|
161
|
+
if (updatedContent === configContent) {
|
|
106
162
|
console.log(
|
|
107
163
|
chalk.yellow("\nWarning: Could not update region in config file. Please set it manually.")
|
|
108
164
|
);
|
|
109
165
|
} else {
|
|
110
|
-
fs.writeFileSync(configPath,
|
|
166
|
+
fs.writeFileSync(configPath, updatedContent);
|
|
111
167
|
}
|
|
168
|
+
} catch {
|
|
169
|
+
console.log(
|
|
170
|
+
chalk.yellow("\nWarning: Could not find embeddable.config.ts to set region.")
|
|
171
|
+
);
|
|
112
172
|
}
|
|
113
173
|
}
|
|
174
|
+
console.log(chalk.dim("\nBuilding bundle...\n"));
|
|
175
|
+
try {
|
|
176
|
+
execSync("npm run embeddable:build", { cwd: projectPath, stdio: "inherit" });
|
|
177
|
+
} catch {
|
|
178
|
+
console.error(chalk.red("\nFailed to build bundle.\n"));
|
|
179
|
+
printDocsHint();
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
console.log(chalk.dim("\nPushing bundle to workspace...\n"));
|
|
183
|
+
try {
|
|
184
|
+
execSync(
|
|
185
|
+
`npm run embeddable:push -- --api-key ${apiKey.trim()} --email "no-reply@embeddable.com" --message "npx @embeddable.com/init"`,
|
|
186
|
+
{ cwd: projectPath, stdio: "inherit" }
|
|
187
|
+
);
|
|
188
|
+
} catch {
|
|
189
|
+
console.error(chalk.red("\nFailed to push bundle to workspace.\n"));
|
|
190
|
+
printDocsHint();
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
const workspaceUrl = WORKSPACE_URLS[region];
|
|
194
|
+
const workspaceLink = terminalLink(workspaceUrl, workspaceUrl, {
|
|
195
|
+
fallback: (text) => text
|
|
196
|
+
});
|
|
197
|
+
const docsUrl = "https://docs.embeddable.com/getting-started/first-embeddable";
|
|
198
|
+
const docsLink = terminalLink(docsUrl, docsUrl, {
|
|
199
|
+
fallback: (text) => text
|
|
200
|
+
});
|
|
114
201
|
console.log(chalk.green(`
|
|
115
|
-
|
|
202
|
+
Success!
|
|
116
203
|
`));
|
|
117
|
-
console.log("
|
|
118
|
-
console.log(chalk.cyan(
|
|
119
|
-
|
|
120
|
-
console.log(chalk.cyan(
|
|
121
|
-
console.log(`Sign up at: ${chalk.underline(SIGNUP_URLS[region])}
|
|
204
|
+
console.log(`You have pushed your ${chalk.bold("components")} and ${chalk.bold("data models")} to workspace.`);
|
|
205
|
+
console.log(`Head there now to build your first Embeddable: ${chalk.cyan(workspaceLink)}
|
|
206
|
+
`);
|
|
207
|
+
console.log(`Follow the guide here to create your first Embeddable dashboard: ${chalk.cyan(docsLink)}
|
|
122
208
|
`);
|
|
123
209
|
}
|
|
124
210
|
main().catch((error) => {
|
|
125
211
|
console.error(chalk.red("An unexpected error occurred:"), error);
|
|
212
|
+
printDocsHint();
|
|
126
213
|
process.exit(1);
|
|
127
214
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embeddable.com/init",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "CLI tool for Embeddable",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"chalk": "^5.3.0",
|
|
27
27
|
"degit": "^2.8.4",
|
|
28
|
-
"prompts": "^2.4.2"
|
|
28
|
+
"prompts": "^2.4.2",
|
|
29
|
+
"terminal-link": "^5.0.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"@types/degit": "^2.8.6",
|