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