@bagelink/workspace 1.7.3 → 1.7.8
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/README.md +236 -8
- package/bin/bgl.ts +102 -4
- package/dist/bin/bgl.cjs +80 -5
- package/dist/bin/bgl.mjs +80 -5
- package/dist/index.cjs +18 -42
- package/dist/index.d.cts +41 -1
- package/dist/index.d.mts +41 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.mjs +4 -36
- package/dist/shared/workspace.BMTTo3s8.cjs +993 -0
- package/dist/shared/workspace.COhZ__uF.mjs +973 -0
- package/package.json +15 -4
- package/src/detect.ts +90 -0
- package/src/index.ts +5 -0
- package/src/init.ts +36 -9
- package/src/lint.ts +235 -0
- package/src/sdk.ts +175 -0
- package/src/workspace.ts +505 -0
- package/templates/dev-runner.ts +61 -0
- package/dist/shared/workspace.BaaKkm9b.mjs +0 -182
- package/dist/shared/workspace.CkP5t0--.cjs +0 -190
|
@@ -0,0 +1,993 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const node_fs = require('node:fs');
|
|
4
|
+
const node_path = require('node:path');
|
|
5
|
+
const process = require('node:process');
|
|
6
|
+
const prompts = require('prompts');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
9
|
+
|
|
10
|
+
const process__default = /*#__PURE__*/_interopDefaultCompat(process);
|
|
11
|
+
const prompts__default = /*#__PURE__*/_interopDefaultCompat(prompts);
|
|
12
|
+
|
|
13
|
+
function generateNetlifyRedirect(config) {
|
|
14
|
+
const redirect = `[[redirects]]
|
|
15
|
+
from = "${config.proxy}/*"
|
|
16
|
+
to = "${config.host}/:splat"
|
|
17
|
+
status = 200
|
|
18
|
+
force = true
|
|
19
|
+
headers = {X-From = "Netlify"}
|
|
20
|
+
`;
|
|
21
|
+
return redirect;
|
|
22
|
+
}
|
|
23
|
+
function generateNetlifyConfig(config, additionalConfig) {
|
|
24
|
+
const redirect = generateNetlifyRedirect(config);
|
|
25
|
+
if (additionalConfig !== void 0 && additionalConfig !== "") {
|
|
26
|
+
return `${redirect}
|
|
27
|
+
${additionalConfig}`;
|
|
28
|
+
}
|
|
29
|
+
return redirect;
|
|
30
|
+
}
|
|
31
|
+
function writeNetlifyConfig(config, outPath = "./netlify.toml", additionalConfig) {
|
|
32
|
+
const content = generateNetlifyConfig(config, additionalConfig);
|
|
33
|
+
const resolvedPath = node_path.resolve(outPath);
|
|
34
|
+
node_fs.writeFileSync(resolvedPath, content, "utf-8");
|
|
35
|
+
console.log(`\u2713 Generated netlify.toml at ${resolvedPath}`);
|
|
36
|
+
}
|
|
37
|
+
function setBuildEnvVars(config) {
|
|
38
|
+
process__default.env.BGL_PROXY_PATH = config.proxy;
|
|
39
|
+
process__default.env.BGL_API_HOST = config.host;
|
|
40
|
+
if (config.openapi_url !== void 0 && config.openapi_url !== "") {
|
|
41
|
+
process__default.env.BGL_OPENAPI_URL = config.openapi_url;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function generateWorkspaceConfig(root = process__default.cwd(), configFile = "bgl.config.ts") {
|
|
46
|
+
console.log("\n\u{1F527} No bgl.config.ts found. Let's create one!\n");
|
|
47
|
+
const response = await prompts__default([
|
|
48
|
+
{
|
|
49
|
+
type: "text",
|
|
50
|
+
name: "projectId",
|
|
51
|
+
message: "What is your Bagel project ID?",
|
|
52
|
+
initial: "my-project",
|
|
53
|
+
validate: (value) => value.length > 0 ? true : "Project ID is required"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
type: "confirm",
|
|
57
|
+
name: "useCustomHost",
|
|
58
|
+
message: "Use custom production host?",
|
|
59
|
+
initial: false
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
type: (prev) => prev ? "text" : null,
|
|
63
|
+
name: "customHost",
|
|
64
|
+
message: "Enter production host URL:",
|
|
65
|
+
initial: "https://api.example.com"
|
|
66
|
+
}
|
|
67
|
+
]);
|
|
68
|
+
if (!response || !response.projectId) {
|
|
69
|
+
console.log("\n\u274C Config generation cancelled.\n");
|
|
70
|
+
process__default.exit(1);
|
|
71
|
+
}
|
|
72
|
+
const productionHost = response.useCustomHost === true ? response.customHost : `https://${response.projectId}.bagel.to`;
|
|
73
|
+
const configContent = `import { defineWorkspace } from '@bagelink/workspace'
|
|
74
|
+
import type { WorkspaceConfig, WorkspaceEnvironment } from '@bagelink/workspace'
|
|
75
|
+
|
|
76
|
+
const configs: Record<WorkspaceEnvironment, WorkspaceConfig> = {
|
|
77
|
+
localhost: {
|
|
78
|
+
host: 'http://localhost:8000',
|
|
79
|
+
proxy: '/api',
|
|
80
|
+
openapi_url: 'http://localhost:8000/openapi.json',
|
|
81
|
+
},
|
|
82
|
+
development: {
|
|
83
|
+
host: '${productionHost}',
|
|
84
|
+
proxy: '/api',
|
|
85
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
86
|
+
},
|
|
87
|
+
production: {
|
|
88
|
+
host: '${productionHost}',
|
|
89
|
+
proxy: '/api',
|
|
90
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default defineWorkspace(configs)
|
|
95
|
+
`;
|
|
96
|
+
const configPath = node_path.resolve(root, configFile);
|
|
97
|
+
node_fs.writeFileSync(configPath, configContent, "utf-8");
|
|
98
|
+
console.log(`
|
|
99
|
+
\u2705 Created ${configFile}`);
|
|
100
|
+
console.log(` Production host: ${productionHost}`);
|
|
101
|
+
console.log(` Local dev host: http://localhost:8000
|
|
102
|
+
`);
|
|
103
|
+
const setupResponse = await prompts__default([
|
|
104
|
+
{
|
|
105
|
+
type: "confirm",
|
|
106
|
+
name: "updatePackageJson",
|
|
107
|
+
message: "Add/update dev scripts in package.json?",
|
|
108
|
+
initial: true
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: "confirm",
|
|
112
|
+
name: "updateViteConfig",
|
|
113
|
+
message: "Create/update vite.config.ts?",
|
|
114
|
+
initial: true
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
type: "confirm",
|
|
118
|
+
name: "generateNetlify",
|
|
119
|
+
message: "Generate netlify.toml for deployment?",
|
|
120
|
+
initial: true
|
|
121
|
+
}
|
|
122
|
+
]);
|
|
123
|
+
if (setupResponse.updatePackageJson) {
|
|
124
|
+
updatePackageJsonScripts(root);
|
|
125
|
+
}
|
|
126
|
+
if (setupResponse.updateViteConfig) {
|
|
127
|
+
updateViteConfig(root);
|
|
128
|
+
}
|
|
129
|
+
if (setupResponse.generateNetlify) {
|
|
130
|
+
const prodConfig = {
|
|
131
|
+
host: productionHost,
|
|
132
|
+
proxy: "/api"
|
|
133
|
+
};
|
|
134
|
+
writeNetlifyConfig(prodConfig, node_path.resolve(root, "netlify.toml"));
|
|
135
|
+
}
|
|
136
|
+
console.log("\n\u{1F4A1} You can edit these files to customize your configuration.\n");
|
|
137
|
+
}
|
|
138
|
+
function generateWorkspaceConfigSync(projectId, root = process__default.cwd(), configFile = "bgl.config.ts", customHost) {
|
|
139
|
+
const productionHost = customHost ?? `https://${projectId}.bagel.to`;
|
|
140
|
+
const configContent = `import { defineWorkspace } from '@bagelink/workspace'
|
|
141
|
+
import type { WorkspaceConfig, WorkspaceEnvironment } from '@bagelink/workspace'
|
|
142
|
+
|
|
143
|
+
const configs: Record<WorkspaceEnvironment, WorkspaceConfig> = {
|
|
144
|
+
localhost: {
|
|
145
|
+
host: 'http://localhost:8000',
|
|
146
|
+
proxy: '/api',
|
|
147
|
+
openapi_url: 'http://localhost:8000/openapi.json',
|
|
148
|
+
},
|
|
149
|
+
development: {
|
|
150
|
+
host: '${productionHost}',
|
|
151
|
+
proxy: '/api',
|
|
152
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
153
|
+
},
|
|
154
|
+
production: {
|
|
155
|
+
host: '${productionHost}',
|
|
156
|
+
proxy: '/api',
|
|
157
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
158
|
+
},
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export default defineWorkspace(configs)
|
|
162
|
+
`;
|
|
163
|
+
const configPath = node_path.resolve(root, configFile);
|
|
164
|
+
node_fs.writeFileSync(configPath, configContent, "utf-8");
|
|
165
|
+
console.log(`\u2705 Created ${configPath}`);
|
|
166
|
+
}
|
|
167
|
+
function updatePackageJsonScripts(root) {
|
|
168
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
169
|
+
if (!node_fs.existsSync(packageJsonPath)) {
|
|
170
|
+
console.log("\u26A0\uFE0F No package.json found, skipping script update");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
|
|
175
|
+
if (!packageJson.scripts) {
|
|
176
|
+
packageJson.scripts = {};
|
|
177
|
+
}
|
|
178
|
+
const scriptsToAdd = {
|
|
179
|
+
"dev": "vite",
|
|
180
|
+
"dev:local": "vite --mode localhost",
|
|
181
|
+
"build": "vite build",
|
|
182
|
+
"preview": "vite preview"
|
|
183
|
+
};
|
|
184
|
+
let modified = false;
|
|
185
|
+
for (const [key, value] of Object.entries(scriptsToAdd)) {
|
|
186
|
+
if (key === "dev" || key === "dev:local") {
|
|
187
|
+
if (packageJson.scripts[key] !== value) {
|
|
188
|
+
packageJson.scripts[key] = value;
|
|
189
|
+
modified = true;
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
if (!packageJson.scripts[key]) {
|
|
193
|
+
packageJson.scripts[key] = value;
|
|
194
|
+
modified = true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (modified) {
|
|
199
|
+
node_fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
200
|
+
`, "utf-8");
|
|
201
|
+
console.log("\u2705 Updated package.json with dev scripts");
|
|
202
|
+
} else {
|
|
203
|
+
console.log("\u2139\uFE0F Scripts already up to date in package.json");
|
|
204
|
+
}
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error("\u274C Failed to update package.json:", error);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function updateViteConfig(root) {
|
|
210
|
+
const viteConfigPath = node_path.resolve(root, "vite.config.ts");
|
|
211
|
+
const viteConfigExists = node_fs.existsSync(viteConfigPath);
|
|
212
|
+
if (viteConfigExists) {
|
|
213
|
+
const existingConfig = node_fs.readFileSync(viteConfigPath, "utf-8");
|
|
214
|
+
if (existingConfig.includes("@bagelink/workspace")) {
|
|
215
|
+
console.log("\u2139\uFE0F vite.config.ts already configured");
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
console.log("\u26A0\uFE0F vite.config.ts exists. Please manually add the workspace configuration.");
|
|
219
|
+
console.log(" See: https://github.com/bageldb/bagelink/tree/master/packages/workspace#readme");
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const viteConfigContent = `import { defineConfig } from 'vite'
|
|
223
|
+
import { createViteProxy } from '@bagelink/workspace'
|
|
224
|
+
import workspace from './bgl.config'
|
|
225
|
+
|
|
226
|
+
// https://vitejs.dev/config/
|
|
227
|
+
export default defineConfig(({ mode }) => {
|
|
228
|
+
const config = workspace(mode as 'localhost' | 'development' | 'production')
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
server: {
|
|
232
|
+
proxy: createViteProxy(config),
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
`;
|
|
237
|
+
node_fs.writeFileSync(viteConfigPath, viteConfigContent, "utf-8");
|
|
238
|
+
console.log("\u2705 Created vite.config.ts");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function setupLint(root = process__default.cwd(), isWorkspace = false) {
|
|
242
|
+
console.log("\n\u{1F50D} Setting up linting...\n");
|
|
243
|
+
const response = await prompts__default([
|
|
244
|
+
{
|
|
245
|
+
type: "multiselect",
|
|
246
|
+
name: "configs",
|
|
247
|
+
message: "Select configurations to set up:",
|
|
248
|
+
choices: [
|
|
249
|
+
{ title: "ESLint", value: "eslint", selected: true },
|
|
250
|
+
{ title: "Prettier", value: "prettier", selected: true },
|
|
251
|
+
{ title: "EditorConfig", value: "editorconfig", selected: true },
|
|
252
|
+
{ title: "Git Hooks", value: "githooks", selected: false }
|
|
253
|
+
]
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
type: "confirm",
|
|
257
|
+
name: "installDeps",
|
|
258
|
+
message: "Install dependencies?",
|
|
259
|
+
initial: true
|
|
260
|
+
}
|
|
261
|
+
]);
|
|
262
|
+
if (!response || !response.configs) {
|
|
263
|
+
console.log("\n\u274C Setup cancelled.\n");
|
|
264
|
+
process__default.exit(1);
|
|
265
|
+
}
|
|
266
|
+
const { configs, installDeps } = response;
|
|
267
|
+
if (configs.includes("eslint")) {
|
|
268
|
+
createEslintConfig(root, isWorkspace);
|
|
269
|
+
}
|
|
270
|
+
if (configs.includes("prettier")) {
|
|
271
|
+
createPrettierConfig(root);
|
|
272
|
+
}
|
|
273
|
+
if (configs.includes("editorconfig")) {
|
|
274
|
+
createEditorConfig(root);
|
|
275
|
+
}
|
|
276
|
+
if (configs.includes("githooks")) {
|
|
277
|
+
createGitHooks(root);
|
|
278
|
+
}
|
|
279
|
+
updatePackageJsonLint(root, configs);
|
|
280
|
+
if (installDeps) {
|
|
281
|
+
console.log("\n\u{1F4E6} Installing dependencies...");
|
|
282
|
+
console.log("Run: bun add -D @bagelink/lint-config eslint prettier typescript");
|
|
283
|
+
}
|
|
284
|
+
console.log("\n\u2705 Linting setup complete!");
|
|
285
|
+
console.log("\nAvailable commands:");
|
|
286
|
+
console.log(" bun run lint - Run linter");
|
|
287
|
+
console.log(" bun run lint:fix - Fix linting issues");
|
|
288
|
+
console.log(" bun run format - Format code with Prettier");
|
|
289
|
+
console.log("");
|
|
290
|
+
}
|
|
291
|
+
function createEslintConfig(root, isWorkspace) {
|
|
292
|
+
const configPath = node_path.resolve(root, "eslint.config.js");
|
|
293
|
+
const config = isWorkspace ? `import { defineConfig } from '@bagelink/lint-config/eslint'
|
|
294
|
+
|
|
295
|
+
export default defineConfig({
|
|
296
|
+
// Workspace-level ESLint config
|
|
297
|
+
ignores: ['**/dist/**', '**/node_modules/**', '**/.bun-cache/**'],
|
|
298
|
+
})
|
|
299
|
+
` : `import vue3Config from '@bagelink/lint-config/eslint/vue3'
|
|
300
|
+
|
|
301
|
+
export default vue3Config
|
|
302
|
+
`;
|
|
303
|
+
node_fs.writeFileSync(configPath, config);
|
|
304
|
+
console.log("\u2705 Created eslint.config.js");
|
|
305
|
+
}
|
|
306
|
+
function createPrettierConfig(root) {
|
|
307
|
+
const configPath = node_path.resolve(root, ".prettierrc");
|
|
308
|
+
const config = {
|
|
309
|
+
semi: false,
|
|
310
|
+
singleQuote: true,
|
|
311
|
+
tabWidth: 2,
|
|
312
|
+
useTabs: true,
|
|
313
|
+
trailingComma: "all",
|
|
314
|
+
printWidth: 100,
|
|
315
|
+
arrowParens: "avoid"
|
|
316
|
+
};
|
|
317
|
+
node_fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
318
|
+
`);
|
|
319
|
+
console.log("\u2705 Created .prettierrc");
|
|
320
|
+
const ignorePath = node_path.resolve(root, ".prettierignore");
|
|
321
|
+
const ignore = `dist
|
|
322
|
+
node_modules
|
|
323
|
+
.bun-cache
|
|
324
|
+
*.min.js
|
|
325
|
+
*.min.css
|
|
326
|
+
`;
|
|
327
|
+
node_fs.writeFileSync(ignorePath, ignore);
|
|
328
|
+
console.log("\u2705 Created .prettierignore");
|
|
329
|
+
}
|
|
330
|
+
function createEditorConfig(root) {
|
|
331
|
+
const configPath = node_path.resolve(root, ".editorconfig");
|
|
332
|
+
const config = `root = true
|
|
333
|
+
|
|
334
|
+
[*]
|
|
335
|
+
charset = utf-8
|
|
336
|
+
indent_style = tab
|
|
337
|
+
indent_size = 2
|
|
338
|
+
end_of_line = lf
|
|
339
|
+
insert_final_newline = true
|
|
340
|
+
trim_trailing_whitespace = true
|
|
341
|
+
|
|
342
|
+
[*.md]
|
|
343
|
+
trim_trailing_whitespace = false
|
|
344
|
+
|
|
345
|
+
[*.{json,yml,yaml}]
|
|
346
|
+
indent_style = space
|
|
347
|
+
indent_size = 2
|
|
348
|
+
`;
|
|
349
|
+
node_fs.writeFileSync(configPath, config);
|
|
350
|
+
console.log("\u2705 Created .editorconfig");
|
|
351
|
+
}
|
|
352
|
+
function createGitHooks(root) {
|
|
353
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
354
|
+
if (!node_fs.existsSync(packageJsonPath)) {
|
|
355
|
+
console.warn("\u26A0\uFE0F No package.json found, skipping git hooks");
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const lintStagedConfig = {
|
|
359
|
+
"*.{js,jsx,ts,tsx,vue}": ["eslint --fix"],
|
|
360
|
+
"*.{json,md,yml,yaml}": ["prettier --write"]
|
|
361
|
+
};
|
|
362
|
+
node_fs.writeFileSync(
|
|
363
|
+
node_path.resolve(root, ".lintstagedrc"),
|
|
364
|
+
`${JSON.stringify(lintStagedConfig, null, 2)}
|
|
365
|
+
`
|
|
366
|
+
);
|
|
367
|
+
console.log("\u2705 Created .lintstagedrc");
|
|
368
|
+
console.log("\u2139\uFE0F Add simple-git-hooks and lint-staged to devDependencies");
|
|
369
|
+
console.log(" Then run: npx simple-git-hooks");
|
|
370
|
+
}
|
|
371
|
+
function updatePackageJsonLint(root, configs) {
|
|
372
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
373
|
+
if (!node_fs.existsSync(packageJsonPath)) {
|
|
374
|
+
console.warn("\u26A0\uFE0F No package.json found");
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
try {
|
|
378
|
+
const packageJson = JSON.parse(
|
|
379
|
+
node_fs.readFileSync(packageJsonPath, "utf-8")
|
|
380
|
+
);
|
|
381
|
+
if (!packageJson.scripts) {
|
|
382
|
+
packageJson.scripts = {};
|
|
383
|
+
}
|
|
384
|
+
if (configs.includes("eslint")) {
|
|
385
|
+
if (!packageJson.scripts.lint) {
|
|
386
|
+
packageJson.scripts.lint = "eslint .";
|
|
387
|
+
}
|
|
388
|
+
if (!packageJson.scripts["lint:fix"]) {
|
|
389
|
+
packageJson.scripts["lint:fix"] = "eslint . --fix";
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (configs.includes("prettier")) {
|
|
393
|
+
if (!packageJson.scripts.format) {
|
|
394
|
+
packageJson.scripts.format = "prettier --write .";
|
|
395
|
+
}
|
|
396
|
+
if (!packageJson.scripts["format:check"]) {
|
|
397
|
+
packageJson.scripts["format:check"] = "prettier --check .";
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
node_fs.writeFileSync(
|
|
401
|
+
packageJsonPath,
|
|
402
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
403
|
+
`
|
|
404
|
+
);
|
|
405
|
+
console.log("\u2705 Updated package.json with lint scripts");
|
|
406
|
+
} catch (error) {
|
|
407
|
+
console.error("\u274C Failed to update package.json:", error);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
async function generateSDK(root = process__default.cwd()) {
|
|
412
|
+
console.log("\n\u{1F527} Generating SDK from OpenAPI...\n");
|
|
413
|
+
let config = null;
|
|
414
|
+
let openApiUrl;
|
|
415
|
+
try {
|
|
416
|
+
const configPath = node_path.resolve(root, "bgl.config.ts");
|
|
417
|
+
if (node_fs.existsSync(configPath)) {
|
|
418
|
+
const module = await import(`file://${configPath}`);
|
|
419
|
+
const workspace = module.default;
|
|
420
|
+
if (typeof workspace === "function") {
|
|
421
|
+
config = workspace("development");
|
|
422
|
+
if (config?.openapi_url) {
|
|
423
|
+
openApiUrl = config.openapi_url;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
} catch {
|
|
428
|
+
}
|
|
429
|
+
const response = await prompts__default([
|
|
430
|
+
{
|
|
431
|
+
type: openApiUrl !== void 0 ? null : "text",
|
|
432
|
+
name: "openApiUrl",
|
|
433
|
+
message: "OpenAPI spec URL:",
|
|
434
|
+
initial: openApiUrl ?? "http://localhost:8000/openapi.json"
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
type: "text",
|
|
438
|
+
name: "outputDir",
|
|
439
|
+
message: "Output directory:",
|
|
440
|
+
initial: "./src/api"
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
type: "confirm",
|
|
444
|
+
name: "splitFiles",
|
|
445
|
+
message: "Split into organized files?",
|
|
446
|
+
initial: true
|
|
447
|
+
}
|
|
448
|
+
]);
|
|
449
|
+
if (!response) {
|
|
450
|
+
console.log("\n\u274C SDK generation cancelled.\n");
|
|
451
|
+
process__default.exit(1);
|
|
452
|
+
}
|
|
453
|
+
const finalUrl = openApiUrl ?? response.openApiUrl;
|
|
454
|
+
const { outputDir, splitFiles } = response;
|
|
455
|
+
console.log(`
|
|
456
|
+
\u{1F4E1} Fetching OpenAPI spec from: ${finalUrl}`);
|
|
457
|
+
console.log(`\u{1F4C1} Output directory: ${outputDir}
|
|
458
|
+
`);
|
|
459
|
+
try {
|
|
460
|
+
const { openAPI } = await import('@bagelink/sdk');
|
|
461
|
+
const { types, code } = await openAPI(finalUrl, "/api");
|
|
462
|
+
const outputPath = node_path.resolve(root, outputDir);
|
|
463
|
+
if (!node_fs.existsSync(outputPath)) {
|
|
464
|
+
node_fs.mkdirSync(outputPath, { recursive: true });
|
|
465
|
+
}
|
|
466
|
+
const typesPath = node_path.resolve(outputPath, "types.d.ts");
|
|
467
|
+
node_fs.writeFileSync(typesPath, types);
|
|
468
|
+
console.log("\u2705 Generated types.d.ts");
|
|
469
|
+
const apiPath = node_path.resolve(outputPath, "api.ts");
|
|
470
|
+
node_fs.writeFileSync(apiPath, code);
|
|
471
|
+
console.log("\u2705 Generated api.ts");
|
|
472
|
+
const indexPath = node_path.resolve(outputPath, "index.ts");
|
|
473
|
+
node_fs.writeFileSync(
|
|
474
|
+
indexPath,
|
|
475
|
+
"export * from './api'\nexport * from './types.d'\n"
|
|
476
|
+
);
|
|
477
|
+
console.log("\u2705 Generated index.ts");
|
|
478
|
+
if (splitFiles) {
|
|
479
|
+
console.log("\n\u{1F500} Splitting into organized files...");
|
|
480
|
+
console.log("\u2139\uFE0F File splitting requires @bagelink/sdk bin scripts");
|
|
481
|
+
console.log(" Keeping monolithic structure for now");
|
|
482
|
+
}
|
|
483
|
+
console.log("\n\u2705 SDK generated successfully!");
|
|
484
|
+
console.log(`
|
|
485
|
+
Import it in your code:`);
|
|
486
|
+
console.log(` import { api } from '${outputDir.replace("./src/", "./")}'`);
|
|
487
|
+
console.log("");
|
|
488
|
+
} catch (error) {
|
|
489
|
+
console.error("\n\u274C Failed to generate SDK:");
|
|
490
|
+
if (error instanceof Error) {
|
|
491
|
+
console.error(error.message);
|
|
492
|
+
} else {
|
|
493
|
+
console.error(error);
|
|
494
|
+
}
|
|
495
|
+
console.log("\nMake sure:");
|
|
496
|
+
console.log(" 1. @bagelink/sdk is installed: bun add -D @bagelink/sdk");
|
|
497
|
+
console.log(" 2. OpenAPI URL is accessible");
|
|
498
|
+
console.log(" 3. API server is running (if using localhost)");
|
|
499
|
+
process__default.exit(1);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
async function generateSDKForWorkspace(root = process__default.cwd()) {
|
|
503
|
+
console.log("\n\u{1F3E2} Generating SDK for workspace projects...\n");
|
|
504
|
+
const fs = await import('node:fs');
|
|
505
|
+
const items = fs.readdirSync(root, { withFileTypes: true });
|
|
506
|
+
const projects = items.filter(
|
|
507
|
+
(item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".")
|
|
508
|
+
).map((item) => item.name);
|
|
509
|
+
if (projects.length === 0) {
|
|
510
|
+
console.log("No projects found in workspace");
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
const response = await prompts__default({
|
|
514
|
+
type: "multiselect",
|
|
515
|
+
name: "selectedProjects",
|
|
516
|
+
message: "Select projects to generate SDK for:",
|
|
517
|
+
choices: projects.map((p) => ({ title: p, value: p, selected: true }))
|
|
518
|
+
});
|
|
519
|
+
if (!response || !response.selectedProjects || response.selectedProjects.length === 0) {
|
|
520
|
+
console.log("\n\u274C No projects selected.\n");
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
for (const project of response.selectedProjects) {
|
|
524
|
+
console.log(`
|
|
525
|
+
\u{1F4E6} Generating SDK for: ${project}`);
|
|
526
|
+
const projectPath = node_path.resolve(root, project);
|
|
527
|
+
try {
|
|
528
|
+
await generateSDK(projectPath);
|
|
529
|
+
} catch {
|
|
530
|
+
console.error(`Failed to generate SDK for ${project}`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
console.log("\n\u2705 All SDKs generated!");
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
async function initWorkspace(root = process__default.cwd()) {
|
|
537
|
+
console.log("\n\u{1F680} Creating Bagel workspace...\n");
|
|
538
|
+
const response = await prompts__default([
|
|
539
|
+
{
|
|
540
|
+
type: "text",
|
|
541
|
+
name: "workspaceName",
|
|
542
|
+
message: "Workspace name:",
|
|
543
|
+
initial: "my-workspace"
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
type: "text",
|
|
547
|
+
name: "projectId",
|
|
548
|
+
message: "Bagel project ID:",
|
|
549
|
+
initial: "my-project"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
type: "confirm",
|
|
553
|
+
name: "createFirstProject",
|
|
554
|
+
message: "Create first project?",
|
|
555
|
+
initial: true
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
type: (prev) => prev ? "text" : null,
|
|
559
|
+
name: "firstProjectName",
|
|
560
|
+
message: "First project name:",
|
|
561
|
+
initial: "web"
|
|
562
|
+
}
|
|
563
|
+
]);
|
|
564
|
+
if (!response || !response.workspaceName) {
|
|
565
|
+
console.log("\n\u274C Workspace creation cancelled.\n");
|
|
566
|
+
process__default.exit(1);
|
|
567
|
+
}
|
|
568
|
+
const { workspaceName, projectId, createFirstProject, firstProjectName } = response;
|
|
569
|
+
const workspaceDir = node_path.resolve(root, workspaceName);
|
|
570
|
+
createWorkspaceRoot(root, workspaceName, projectId);
|
|
571
|
+
createSharedPackage(workspaceDir);
|
|
572
|
+
if (createFirstProject && firstProjectName) {
|
|
573
|
+
await addProject(firstProjectName, workspaceDir);
|
|
574
|
+
}
|
|
575
|
+
console.log("\n\u2705 Workspace created successfully!");
|
|
576
|
+
console.log("\nNext steps:");
|
|
577
|
+
console.log(` cd ${workspaceName}`);
|
|
578
|
+
console.log(" bun install");
|
|
579
|
+
if (createFirstProject) {
|
|
580
|
+
console.log(` bun run dev:${firstProjectName}`);
|
|
581
|
+
} else {
|
|
582
|
+
console.log(" bgl add <project-name> # Add a project");
|
|
583
|
+
}
|
|
584
|
+
console.log("");
|
|
585
|
+
}
|
|
586
|
+
function createWorkspaceRoot(root, name, projectId) {
|
|
587
|
+
const workspaceDir = node_path.resolve(root, name);
|
|
588
|
+
if (node_fs.existsSync(workspaceDir)) {
|
|
589
|
+
console.error(`\u274C Directory ${name} already exists`);
|
|
590
|
+
process__default.exit(1);
|
|
591
|
+
}
|
|
592
|
+
node_fs.mkdirSync(workspaceDir, { recursive: true });
|
|
593
|
+
const packageJson = {
|
|
594
|
+
name,
|
|
595
|
+
private: true,
|
|
596
|
+
workspaces: ["*", "!node_modules"],
|
|
597
|
+
scripts: {
|
|
598
|
+
dev: "bun scripts/dev.ts",
|
|
599
|
+
"dev:verbose": "bun run --filter './[!shared]*' dev",
|
|
600
|
+
build: "bun run --filter './[!shared]*' build",
|
|
601
|
+
typecheck: "tsc --noEmit"
|
|
602
|
+
},
|
|
603
|
+
devDependencies: {
|
|
604
|
+
"@bagelink/workspace": "latest",
|
|
605
|
+
"typescript": "^5.0.0",
|
|
606
|
+
"vite": "latest"
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
node_fs.writeFileSync(
|
|
610
|
+
node_path.resolve(workspaceDir, "package.json"),
|
|
611
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
612
|
+
`
|
|
613
|
+
);
|
|
614
|
+
const bglConfig = `import { defineWorkspace } from '@bagelink/workspace'
|
|
615
|
+
|
|
616
|
+
export default defineWorkspace({
|
|
617
|
+
localhost: {
|
|
618
|
+
host: 'http://localhost:8000',
|
|
619
|
+
proxy: '/api',
|
|
620
|
+
openapi_url: 'http://localhost:8000/openapi.json',
|
|
621
|
+
},
|
|
622
|
+
development: {
|
|
623
|
+
host: 'https://${projectId}.bagel.to',
|
|
624
|
+
proxy: '/api',
|
|
625
|
+
openapi_url: 'https://${projectId}.bagel.to/openapi.json',
|
|
626
|
+
},
|
|
627
|
+
production: {
|
|
628
|
+
host: 'https://${projectId}.bagel.to',
|
|
629
|
+
proxy: '/api',
|
|
630
|
+
openapi_url: 'https://${projectId}.bagel.to/openapi.json',
|
|
631
|
+
},
|
|
632
|
+
})
|
|
633
|
+
`;
|
|
634
|
+
node_fs.writeFileSync(node_path.resolve(workspaceDir, "bgl.config.ts"), bglConfig);
|
|
635
|
+
const tsConfig = {
|
|
636
|
+
compilerOptions: {
|
|
637
|
+
target: "ES2020",
|
|
638
|
+
useDefineForClassFields: true,
|
|
639
|
+
module: "ESNext",
|
|
640
|
+
lib: ["ES2020", "DOM", "DOM.Iterable"],
|
|
641
|
+
skipLibCheck: true,
|
|
642
|
+
moduleResolution: "bundler",
|
|
643
|
+
allowImportingTsExtensions: true,
|
|
644
|
+
resolveJsonModule: true,
|
|
645
|
+
isolatedModules: true,
|
|
646
|
+
noEmit: true,
|
|
647
|
+
jsx: "preserve",
|
|
648
|
+
strict: true,
|
|
649
|
+
noUnusedLocals: true,
|
|
650
|
+
noUnusedParameters: true,
|
|
651
|
+
noFallthroughCasesInSwitch: true,
|
|
652
|
+
baseUrl: ".",
|
|
653
|
+
paths: {
|
|
654
|
+
"shared/*": ["./shared/*"]
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
node_fs.writeFileSync(
|
|
659
|
+
node_path.resolve(workspaceDir, "tsconfig.json"),
|
|
660
|
+
`${JSON.stringify(tsConfig, null, 2)}
|
|
661
|
+
`
|
|
662
|
+
);
|
|
663
|
+
const gitignore = `node_modules
|
|
664
|
+
dist
|
|
665
|
+
.DS_Store
|
|
666
|
+
*.local
|
|
667
|
+
.env.local
|
|
668
|
+
.vite
|
|
669
|
+
`;
|
|
670
|
+
node_fs.writeFileSync(node_path.resolve(workspaceDir, ".gitignore"), gitignore);
|
|
671
|
+
const scriptsDir = node_path.resolve(workspaceDir, "scripts");
|
|
672
|
+
node_fs.mkdirSync(scriptsDir, { recursive: true });
|
|
673
|
+
const devRunnerContent = `#!/usr/bin/env bun
|
|
674
|
+
import { spawn } from 'bun'
|
|
675
|
+
import { readdir } from 'fs/promises'
|
|
676
|
+
import { resolve } from 'path'
|
|
677
|
+
|
|
678
|
+
const projectsRoot = process.cwd()
|
|
679
|
+
const projects = (await readdir(projectsRoot, { withFileTypes: true }))
|
|
680
|
+
.filter(
|
|
681
|
+
item =>
|
|
682
|
+
item.isDirectory()
|
|
683
|
+
&& item.name !== 'node_modules'
|
|
684
|
+
&& item.name !== 'shared'
|
|
685
|
+
&& item.name !== 'scripts'
|
|
686
|
+
&& item.name !== '.git'
|
|
687
|
+
&& !item.name.startsWith('.'),
|
|
688
|
+
)
|
|
689
|
+
.map(item => item.name)
|
|
690
|
+
|
|
691
|
+
console.log(\`\\n\u{1F680} Starting \${projects.length} project\${projects.length > 1 ? 's' : ''}...\\n\`)
|
|
692
|
+
|
|
693
|
+
const urlPattern = /Local:\\s+(http:\\/\\/localhost:\\d+)/
|
|
694
|
+
|
|
695
|
+
projects.forEach((project) => {
|
|
696
|
+
const proc = spawn({
|
|
697
|
+
cmd: ['bun', 'run', 'dev'],
|
|
698
|
+
cwd: resolve(projectsRoot, project),
|
|
699
|
+
stdout: 'pipe',
|
|
700
|
+
stderr: 'pipe',
|
|
701
|
+
})
|
|
702
|
+
|
|
703
|
+
const decoder = new TextDecoder()
|
|
704
|
+
|
|
705
|
+
proc.stdout.pipeTo(
|
|
706
|
+
new WritableStream({
|
|
707
|
+
write(chunk) {
|
|
708
|
+
const text = decoder.decode(chunk)
|
|
709
|
+
const match = text.match(urlPattern)
|
|
710
|
+
if (match) {
|
|
711
|
+
console.log(\` \u2713 \${project.padEnd(15)} \u2192 \${match[1]}\`)
|
|
712
|
+
}
|
|
713
|
+
},
|
|
714
|
+
}),
|
|
715
|
+
)
|
|
716
|
+
|
|
717
|
+
proc.stderr.pipeTo(
|
|
718
|
+
new WritableStream({
|
|
719
|
+
write(chunk) {
|
|
720
|
+
const text = decoder.decode(chunk)
|
|
721
|
+
if (text.includes('error') || text.includes('Error')) {
|
|
722
|
+
console.error(\` \u2717 \${project}: \${text.trim()}\`)
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
}),
|
|
726
|
+
)
|
|
727
|
+
})
|
|
728
|
+
|
|
729
|
+
console.log('\\n\u{1F4A1} Press Ctrl+C to stop all servers\\n')
|
|
730
|
+
|
|
731
|
+
process.on('SIGINT', () => {
|
|
732
|
+
console.log('\\n\\n\u{1F44B} Stopping all servers...\\n')
|
|
733
|
+
process.exit()
|
|
734
|
+
})
|
|
735
|
+
`;
|
|
736
|
+
node_fs.writeFileSync(node_path.resolve(scriptsDir, "dev.ts"), devRunnerContent);
|
|
737
|
+
console.log(`\u2705 Created workspace: ${name}`);
|
|
738
|
+
}
|
|
739
|
+
function createSharedPackage(root) {
|
|
740
|
+
const sharedDir = node_path.resolve(root, "shared");
|
|
741
|
+
node_fs.mkdirSync(sharedDir, { recursive: true });
|
|
742
|
+
const packageJson = {
|
|
743
|
+
name: "shared",
|
|
744
|
+
version: "1.0.0",
|
|
745
|
+
type: "module",
|
|
746
|
+
exports: {
|
|
747
|
+
".": "./index.ts",
|
|
748
|
+
"./utils": "./utils/index.ts",
|
|
749
|
+
"./types": "./types/index.ts"
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
node_fs.writeFileSync(
|
|
753
|
+
node_path.resolve(sharedDir, "package.json"),
|
|
754
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
755
|
+
`
|
|
756
|
+
);
|
|
757
|
+
node_fs.writeFileSync(
|
|
758
|
+
node_path.resolve(sharedDir, "index.ts"),
|
|
759
|
+
"// Shared utilities and exports\nexport * from './utils'\n"
|
|
760
|
+
);
|
|
761
|
+
node_fs.mkdirSync(node_path.resolve(sharedDir, "utils"), { recursive: true });
|
|
762
|
+
node_fs.writeFileSync(
|
|
763
|
+
node_path.resolve(sharedDir, "utils", "index.ts"),
|
|
764
|
+
"// Shared utility functions\nexport function formatDate(date: Date): string {\n return date.toISOString()\n}\n"
|
|
765
|
+
);
|
|
766
|
+
node_fs.mkdirSync(node_path.resolve(sharedDir, "types"), { recursive: true });
|
|
767
|
+
node_fs.writeFileSync(
|
|
768
|
+
node_path.resolve(sharedDir, "types", "index.ts"),
|
|
769
|
+
"// Shared types\nexport interface User {\n id: string\n name: string\n}\n"
|
|
770
|
+
);
|
|
771
|
+
console.log("\u2705 Created shared package");
|
|
772
|
+
}
|
|
773
|
+
async function addProject(name, root = process__default.cwd()) {
|
|
774
|
+
const projectDir = node_path.resolve(root, name);
|
|
775
|
+
if (node_fs.existsSync(projectDir)) {
|
|
776
|
+
console.error(`\u274C Project ${name} already exists`);
|
|
777
|
+
process__default.exit(1);
|
|
778
|
+
}
|
|
779
|
+
console.log(`
|
|
780
|
+
\u{1F4E6} Creating project: ${name}
|
|
781
|
+
`);
|
|
782
|
+
node_fs.mkdirSync(projectDir, { recursive: true });
|
|
783
|
+
const isWorkspace = node_fs.existsSync(node_path.resolve(root, "bgl.config.ts"));
|
|
784
|
+
const packageJson = {
|
|
785
|
+
name,
|
|
786
|
+
type: "module",
|
|
787
|
+
scripts: {
|
|
788
|
+
dev: "vite",
|
|
789
|
+
build: "vite build",
|
|
790
|
+
preview: "vite preview"
|
|
791
|
+
},
|
|
792
|
+
dependencies: {},
|
|
793
|
+
devDependencies: {
|
|
794
|
+
"@vitejs/plugin-vue": "latest",
|
|
795
|
+
"vite": "latest",
|
|
796
|
+
"vue": "latest"
|
|
797
|
+
}
|
|
798
|
+
};
|
|
799
|
+
if (isWorkspace) {
|
|
800
|
+
packageJson.dependencies.shared = "workspace:*";
|
|
801
|
+
}
|
|
802
|
+
node_fs.writeFileSync(
|
|
803
|
+
node_path.resolve(projectDir, "package.json"),
|
|
804
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
805
|
+
`
|
|
806
|
+
);
|
|
807
|
+
const bglConfigContent = isWorkspace ? `import { defineWorkspace } from '@bagelink/workspace'
|
|
808
|
+
import rootWorkspace from '../bgl.config'
|
|
809
|
+
|
|
810
|
+
export default defineWorkspace({
|
|
811
|
+
localhost: rootWorkspace('localhost'),
|
|
812
|
+
development: rootWorkspace('development'),
|
|
813
|
+
production: rootWorkspace('production'),
|
|
814
|
+
})
|
|
815
|
+
` : `import { defineWorkspace } from '@bagelink/workspace'
|
|
816
|
+
|
|
817
|
+
export default defineWorkspace({
|
|
818
|
+
localhost: {
|
|
819
|
+
host: 'http://localhost:8000',
|
|
820
|
+
proxy: '/api',
|
|
821
|
+
},
|
|
822
|
+
development: {
|
|
823
|
+
host: 'https://my-project.bagel.to',
|
|
824
|
+
proxy: '/api',
|
|
825
|
+
},
|
|
826
|
+
production: {
|
|
827
|
+
host: 'https://my-project.bagel.to',
|
|
828
|
+
proxy: '/api',
|
|
829
|
+
},
|
|
830
|
+
})
|
|
831
|
+
`;
|
|
832
|
+
node_fs.writeFileSync(node_path.resolve(projectDir, "bgl.config.ts"), bglConfigContent);
|
|
833
|
+
const viteConfig = `import { defineConfig } from 'vite'
|
|
834
|
+
import vue from '@vitejs/plugin-vue'
|
|
835
|
+
import { createViteProxy } from '@bagelink/workspace'
|
|
836
|
+
import workspace from './bgl.config'
|
|
837
|
+
|
|
838
|
+
export default defineConfig(({ mode }) => {
|
|
839
|
+
const config = workspace(mode as 'localhost' | 'development' | 'production')
|
|
840
|
+
|
|
841
|
+
return {
|
|
842
|
+
plugins: [vue()],
|
|
843
|
+
server: {
|
|
844
|
+
proxy: createViteProxy(config),
|
|
845
|
+
},
|
|
846
|
+
}
|
|
847
|
+
})
|
|
848
|
+
`;
|
|
849
|
+
node_fs.writeFileSync(node_path.resolve(projectDir, "vite.config.ts"), viteConfig);
|
|
850
|
+
const srcDir = node_path.resolve(projectDir, "src");
|
|
851
|
+
node_fs.mkdirSync(srcDir, { recursive: true });
|
|
852
|
+
const indexHtml = `<!DOCTYPE html>
|
|
853
|
+
<html lang="en">
|
|
854
|
+
<head>
|
|
855
|
+
<meta charset="UTF-8">
|
|
856
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
857
|
+
<title>${name}</title>
|
|
858
|
+
</head>
|
|
859
|
+
<body>
|
|
860
|
+
<div id="app"></div>
|
|
861
|
+
<script type="module" src="/src/main.ts"><\/script>
|
|
862
|
+
</body>
|
|
863
|
+
</html>
|
|
864
|
+
`;
|
|
865
|
+
node_fs.writeFileSync(node_path.resolve(projectDir, "index.html"), indexHtml);
|
|
866
|
+
const mainTs = `import { createApp } from 'vue'
|
|
867
|
+
import App from './App.vue'
|
|
868
|
+
|
|
869
|
+
createApp(App).mount('#app')
|
|
870
|
+
`;
|
|
871
|
+
node_fs.writeFileSync(node_path.resolve(srcDir, "main.ts"), mainTs);
|
|
872
|
+
const appVue = `<script setup lang="ts">
|
|
873
|
+
import { ref } from 'vue'
|
|
874
|
+
${isWorkspace ? "import { formatDate } from 'shared/utils'\n" : ""}
|
|
875
|
+
const count = ref(0)
|
|
876
|
+
<\/script>
|
|
877
|
+
|
|
878
|
+
<template>
|
|
879
|
+
<div>
|
|
880
|
+
<h1>${name}</h1>
|
|
881
|
+
<button @click="count++">Count: {{ count }}</button>
|
|
882
|
+
${isWorkspace ? "<p>{{ formatDate(new Date()) }}</p>" : ""}
|
|
883
|
+
</div>
|
|
884
|
+
</template>
|
|
885
|
+
`;
|
|
886
|
+
node_fs.writeFileSync(node_path.resolve(srcDir, "App.vue"), appVue);
|
|
887
|
+
console.log(`\u2705 Created project: ${name}`);
|
|
888
|
+
if (isWorkspace) {
|
|
889
|
+
updateWorkspaceScripts(root, name);
|
|
890
|
+
}
|
|
891
|
+
console.log("\nNext steps:");
|
|
892
|
+
console.log(` cd ${name}`);
|
|
893
|
+
console.log(" bun install");
|
|
894
|
+
console.log(" bun run dev");
|
|
895
|
+
console.log("");
|
|
896
|
+
}
|
|
897
|
+
function updateWorkspaceScripts(root, projectName) {
|
|
898
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
899
|
+
if (!node_fs.existsSync(packageJsonPath)) return;
|
|
900
|
+
try {
|
|
901
|
+
const packageJson = JSON.parse(
|
|
902
|
+
node_fs.readFileSync(packageJsonPath, "utf-8")
|
|
903
|
+
);
|
|
904
|
+
if (!packageJson.scripts) {
|
|
905
|
+
packageJson.scripts = {};
|
|
906
|
+
}
|
|
907
|
+
packageJson.scripts[`dev:${projectName}`] = `bun --filter ${projectName} dev`;
|
|
908
|
+
packageJson.scripts[`build:${projectName}`] = `bun --filter ${projectName} build`;
|
|
909
|
+
node_fs.writeFileSync(
|
|
910
|
+
packageJsonPath,
|
|
911
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
912
|
+
`
|
|
913
|
+
);
|
|
914
|
+
console.log(`\u2705 Added scripts: dev:${projectName}, build:${projectName}`);
|
|
915
|
+
} catch (error) {
|
|
916
|
+
console.warn("\u26A0\uFE0F Could not update workspace scripts");
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
function listProjects(root = process__default.cwd()) {
|
|
920
|
+
try {
|
|
921
|
+
const items = node_fs.readdirSync(root, { withFileTypes: true });
|
|
922
|
+
return items.filter(
|
|
923
|
+
(item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".")
|
|
924
|
+
).map((item) => item.name);
|
|
925
|
+
} catch {
|
|
926
|
+
return [];
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
function isWorkspace(root = process__default.cwd()) {
|
|
931
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
932
|
+
if (node_fs.existsSync(packageJsonPath)) {
|
|
933
|
+
try {
|
|
934
|
+
const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
|
|
935
|
+
if (packageJson.workspaces !== void 0) {
|
|
936
|
+
return true;
|
|
937
|
+
}
|
|
938
|
+
} catch {
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
try {
|
|
942
|
+
const items = node_fs.readdirSync(root, { withFileTypes: true });
|
|
943
|
+
const projectDirs = items.filter(
|
|
944
|
+
(item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && node_fs.existsSync(node_path.resolve(root, item.name, "package.json"))
|
|
945
|
+
);
|
|
946
|
+
return projectDirs.length >= 2;
|
|
947
|
+
} catch {
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
function getWorkspaceInfo(root = process__default.cwd()) {
|
|
952
|
+
const workspace = isWorkspace(root);
|
|
953
|
+
if (!workspace) {
|
|
954
|
+
return {
|
|
955
|
+
isWorkspace: false,
|
|
956
|
+
projects: [],
|
|
957
|
+
hasShared: false
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
try {
|
|
961
|
+
const items = node_fs.readdirSync(root, { withFileTypes: true });
|
|
962
|
+
const projects = items.filter(
|
|
963
|
+
(item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && node_fs.existsSync(node_path.resolve(root, item.name, "package.json"))
|
|
964
|
+
).map((item) => item.name);
|
|
965
|
+
const hasShared = node_fs.existsSync(node_path.resolve(root, "shared"));
|
|
966
|
+
return {
|
|
967
|
+
isWorkspace: true,
|
|
968
|
+
projects,
|
|
969
|
+
hasShared
|
|
970
|
+
};
|
|
971
|
+
} catch {
|
|
972
|
+
return {
|
|
973
|
+
isWorkspace: false,
|
|
974
|
+
projects: [],
|
|
975
|
+
hasShared: false
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
exports.addProject = addProject;
|
|
981
|
+
exports.generateNetlifyConfig = generateNetlifyConfig;
|
|
982
|
+
exports.generateNetlifyRedirect = generateNetlifyRedirect;
|
|
983
|
+
exports.generateSDK = generateSDK;
|
|
984
|
+
exports.generateSDKForWorkspace = generateSDKForWorkspace;
|
|
985
|
+
exports.generateWorkspaceConfig = generateWorkspaceConfig;
|
|
986
|
+
exports.generateWorkspaceConfigSync = generateWorkspaceConfigSync;
|
|
987
|
+
exports.getWorkspaceInfo = getWorkspaceInfo;
|
|
988
|
+
exports.initWorkspace = initWorkspace;
|
|
989
|
+
exports.isWorkspace = isWorkspace;
|
|
990
|
+
exports.listProjects = listProjects;
|
|
991
|
+
exports.setBuildEnvVars = setBuildEnvVars;
|
|
992
|
+
exports.setupLint = setupLint;
|
|
993
|
+
exports.writeNetlifyConfig = writeNetlifyConfig;
|