@bagelink/workspace 1.10.7 → 1.10.9
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 +214 -9
- package/bin/bgl.ts +88 -2
- package/dist/bin/bgl.cjs +854 -14
- package/dist/bin/bgl.mjs +845 -6
- package/dist/composable.cjs +22 -0
- package/dist/composable.d.cts +52 -0
- package/dist/composable.d.mts +52 -0
- package/dist/composable.d.ts +52 -0
- package/dist/composable.mjs +19 -0
- package/dist/index.cjs +3 -160
- package/dist/index.d.cts +4 -160
- package/dist/index.d.mts +4 -160
- package/dist/index.d.ts +4 -160
- package/dist/index.mjs +2 -139
- package/dist/shared/workspace.Bc_dpzhA.mjs +500 -0
- package/dist/shared/workspace.BzlV5kcN.d.cts +50 -0
- package/dist/shared/workspace.BzlV5kcN.d.mts +50 -0
- package/dist/shared/workspace.BzlV5kcN.d.ts +50 -0
- package/dist/shared/workspace.DRlDHdPw.cjs +512 -0
- package/dist/vite.cjs +135 -0
- package/dist/vite.d.cts +98 -0
- package/dist/vite.d.mts +98 -0
- package/dist/vite.d.ts +98 -0
- package/dist/vite.mjs +125 -0
- package/env.d.ts +30 -0
- package/package.json +24 -3
- package/src/build.ts +45 -0
- package/src/composable.ts +70 -0
- package/src/dev.ts +171 -0
- package/src/index.ts +4 -78
- package/src/init.ts +72 -14
- package/src/lint.ts +90 -2
- package/src/netlify.ts +54 -3
- package/src/proxy.ts +23 -3
- package/src/sdk.ts +80 -44
- package/src/types.ts +10 -4
- package/src/vite.ts +166 -0
- package/src/workspace.ts +121 -16
- package/templates/dev-runner.ts +61 -0
- package/templates/tsconfig.app.json +23 -0
- package/dist/shared/workspace.BPEOymAx.cjs +0 -926
- package/dist/shared/workspace.DfYoqH33.mjs +0 -906
package/dist/bin/bgl.cjs
CHANGED
|
@@ -1,24 +1,811 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
const node_path = require('node:path');
|
|
4
5
|
const process = require('node:process');
|
|
5
|
-
const
|
|
6
|
-
require('
|
|
7
|
-
require('node:
|
|
8
|
-
require('prompts');
|
|
6
|
+
const node_child_process = require('node:child_process');
|
|
7
|
+
const netlify = require('../shared/workspace.DRlDHdPw.cjs');
|
|
8
|
+
const node_fs = require('node:fs');
|
|
9
|
+
const prompts = require('prompts');
|
|
9
10
|
|
|
10
11
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
11
12
|
|
|
12
13
|
const process__default = /*#__PURE__*/_interopDefaultCompat(process);
|
|
14
|
+
const prompts__default = /*#__PURE__*/_interopDefaultCompat(prompts);
|
|
15
|
+
|
|
16
|
+
async function runBuild(filter, additionalArgs = []) {
|
|
17
|
+
const argsStr = additionalArgs.length > 0 ? ` -- ${additionalArgs.join(" ")}` : "";
|
|
18
|
+
const resolvedFilters = resolveFilters$1(filter);
|
|
19
|
+
if (!resolvedFilters || resolvedFilters.length === 0) return 1;
|
|
20
|
+
const filterArgs = resolvedFilters.map((f) => `--filter '${f}'`).join(" ");
|
|
21
|
+
const command = `bun run ${filterArgs} build${argsStr}`;
|
|
22
|
+
const proc = node_child_process.spawn(command, {
|
|
23
|
+
cwd: process__default.cwd(),
|
|
24
|
+
stdio: "inherit",
|
|
25
|
+
shell: true
|
|
26
|
+
});
|
|
27
|
+
proc.on("error", (error) => {
|
|
28
|
+
console.error("Failed to start build:", error.message);
|
|
29
|
+
});
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
proc.on("exit", (code) => {
|
|
32
|
+
resolve(code || 0);
|
|
33
|
+
});
|
|
34
|
+
proc.on("error", reject);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function resolveFilters$1(filter) {
|
|
38
|
+
if (filter) return [filter];
|
|
39
|
+
const projects = netlify.listProjects();
|
|
40
|
+
if (projects.length === 0) {
|
|
41
|
+
console.error("No projects found");
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return projects.map((p) => `./${p}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isWorkspace(root = process__default.cwd()) {
|
|
48
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
49
|
+
if (node_fs.existsSync(packageJsonPath)) {
|
|
50
|
+
try {
|
|
51
|
+
const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
|
|
52
|
+
if (packageJson.workspaces !== void 0) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const items = node_fs.readdirSync(root, { withFileTypes: true });
|
|
60
|
+
const projectDirs = items.filter(
|
|
61
|
+
(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"))
|
|
62
|
+
);
|
|
63
|
+
return projectDirs.length >= 2;
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const servers = /* @__PURE__ */ new Map();
|
|
70
|
+
const projectToPort = /* @__PURE__ */ new Map();
|
|
71
|
+
const seenLines = /* @__PURE__ */ new Set();
|
|
72
|
+
const START_PORT = 5173;
|
|
73
|
+
const colors = {
|
|
74
|
+
reset: "\x1B[0m",
|
|
75
|
+
cyan: "\x1B[36m",
|
|
76
|
+
green: "\x1B[32m",
|
|
77
|
+
yellow: "\x1B[33m",
|
|
78
|
+
dim: "\x1B[2m",
|
|
79
|
+
red: "\x1B[31m"
|
|
80
|
+
};
|
|
81
|
+
function clearAndPrintServers() {
|
|
82
|
+
if (servers.size > 0) {
|
|
83
|
+
process__default.stdout.write("\x1B[2J\x1B[H");
|
|
84
|
+
}
|
|
85
|
+
console.log(`${colors.cyan}\u{1F680} Development Servers${colors.reset}
|
|
86
|
+
`);
|
|
87
|
+
const sortedServers = Array.from(servers.entries()).sort((a, b) => a[1].order - b[1].order);
|
|
88
|
+
for (const [name, info] of sortedServers) {
|
|
89
|
+
const url = `http://localhost:${info.actualPort ?? info.assignedPort}`;
|
|
90
|
+
if (info.status === "ready") {
|
|
91
|
+
console.log(`${colors.green}\u25CF${colors.reset} ${colors.cyan}${name}${colors.reset} ${colors.dim}\u2192${colors.reset} ${url}`);
|
|
92
|
+
} else {
|
|
93
|
+
console.log(`${colors.yellow}\u25CB${colors.reset} ${colors.dim}${name} (starting...)${colors.reset} ${colors.dim}${url}${colors.reset}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
console.log("");
|
|
97
|
+
}
|
|
98
|
+
async function runDev(filter, additionalArgs = []) {
|
|
99
|
+
const argsStr = additionalArgs.length > 0 ? ` -- ${additionalArgs.join(" ")}` : "";
|
|
100
|
+
const resolvedFilters = resolveFilters(filter);
|
|
101
|
+
if (!resolvedFilters || resolvedFilters.length === 0) return 1;
|
|
102
|
+
const projectNames = resolvedFilters.map((f) => f.replace("./", "")).sort();
|
|
103
|
+
projectNames.forEach((name, index) => {
|
|
104
|
+
const assignedPort = START_PORT + index;
|
|
105
|
+
servers.set(name, {
|
|
106
|
+
name,
|
|
107
|
+
assignedPort,
|
|
108
|
+
status: "starting",
|
|
109
|
+
order: index
|
|
110
|
+
});
|
|
111
|
+
projectToPort.set(name, assignedPort);
|
|
112
|
+
});
|
|
113
|
+
clearAndPrintServers();
|
|
114
|
+
const filterArgs = resolvedFilters.map((f) => `--filter '${f}'`).join(" ");
|
|
115
|
+
projectNames.join(", ");
|
|
116
|
+
const command = `bun run ${filterArgs} dev${argsStr}`;
|
|
117
|
+
const proc = node_child_process.spawn(command, {
|
|
118
|
+
cwd: process__default.cwd(),
|
|
119
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
120
|
+
shell: true
|
|
121
|
+
});
|
|
122
|
+
let stdoutBuffer = "";
|
|
123
|
+
let stderrBuffer = "";
|
|
124
|
+
function processLine(line) {
|
|
125
|
+
if (!line.trim()) return;
|
|
126
|
+
if (seenLines.has(line)) return;
|
|
127
|
+
seenLines.add(line);
|
|
128
|
+
const portMatch = line.match(/Local:\s+http:\/\/localhost:(\d+)/);
|
|
129
|
+
if (portMatch) {
|
|
130
|
+
const port = Number.parseInt(portMatch[1], 10);
|
|
131
|
+
const projectInLine = line.match(/^([\w-]+)\s+dev:/);
|
|
132
|
+
if (projectInLine) {
|
|
133
|
+
const name = projectInLine[1];
|
|
134
|
+
const info = servers.get(name);
|
|
135
|
+
if (info && !info.actualPort) {
|
|
136
|
+
info.actualPort = port;
|
|
137
|
+
info.status = "ready";
|
|
138
|
+
clearAndPrintServers();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
proc.stdout?.setEncoding("utf8");
|
|
144
|
+
proc.stderr?.setEncoding("utf8");
|
|
145
|
+
proc.stdout?.on("data", (data) => {
|
|
146
|
+
if (servers.size === 0) {
|
|
147
|
+
console.log(`${colors.dim}Receiving output...${colors.reset}`);
|
|
148
|
+
}
|
|
149
|
+
stdoutBuffer += data;
|
|
150
|
+
const lines = stdoutBuffer.split("\n");
|
|
151
|
+
stdoutBuffer = lines.pop() || "";
|
|
152
|
+
for (const line of lines) {
|
|
153
|
+
processLine(line);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
proc.stderr?.on("data", (data) => {
|
|
157
|
+
stderrBuffer += data;
|
|
158
|
+
const lines = stderrBuffer.split("\n");
|
|
159
|
+
stderrBuffer = lines.pop() || "";
|
|
160
|
+
for (const line of lines) {
|
|
161
|
+
processLine(line);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
proc.on("error", (error) => {
|
|
165
|
+
console.error(`${colors.red}Failed to start dev servers:${colors.reset}`, error.message);
|
|
166
|
+
});
|
|
167
|
+
process__default.on("SIGINT", () => {
|
|
168
|
+
proc.kill("SIGINT");
|
|
169
|
+
process__default.exit(0);
|
|
170
|
+
});
|
|
171
|
+
return new Promise((resolve, reject) => {
|
|
172
|
+
proc.on("exit", (code) => {
|
|
173
|
+
resolve(code || 0);
|
|
174
|
+
});
|
|
175
|
+
proc.on("error", reject);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function resolveFilters(filter) {
|
|
179
|
+
if (filter) return [filter];
|
|
180
|
+
const projects = netlify.listProjects();
|
|
181
|
+
if (projects.length === 0) {
|
|
182
|
+
console.error("No projects found");
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
return projects.map((p) => `./${p}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async function generateWorkspaceConfig(root = process__default.cwd(), configFile = "bgl.config.ts") {
|
|
189
|
+
console.log("\n\u{1F527} No bgl.config.ts found. Let's create one!\n");
|
|
190
|
+
const response = await prompts__default([
|
|
191
|
+
{
|
|
192
|
+
type: "text",
|
|
193
|
+
name: "projectId",
|
|
194
|
+
message: "What is your Bagel project ID?",
|
|
195
|
+
initial: "my-project",
|
|
196
|
+
validate: (value) => value.length > 0 ? true : "Project ID is required"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
type: "confirm",
|
|
200
|
+
name: "useCustomHost",
|
|
201
|
+
message: "Use custom production host?",
|
|
202
|
+
initial: false
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
type: (prev) => prev ? "text" : null,
|
|
206
|
+
name: "customHost",
|
|
207
|
+
message: "Enter production host URL:",
|
|
208
|
+
initial: "https://api.example.com"
|
|
209
|
+
}
|
|
210
|
+
]);
|
|
211
|
+
if (!response || !response.projectId) {
|
|
212
|
+
console.log("\n\u274C Config generation cancelled.\n");
|
|
213
|
+
process__default.exit(1);
|
|
214
|
+
}
|
|
215
|
+
const productionHost = response.useCustomHost === true ? response.customHost : `https://${response.projectId}.bagel.to`;
|
|
216
|
+
const configContent = `import { defineWorkspace } from '@bagelink/workspace'
|
|
217
|
+
import type { WorkspaceConfig, WorkspaceEnvironment } from '@bagelink/workspace'
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Define your workspace environments
|
|
221
|
+
* You can add as many custom environments as needed (e.g., 'staging', 'preview')
|
|
222
|
+
* Use --mode flag to switch: bgl dev --mode <env_name>
|
|
223
|
+
*/
|
|
224
|
+
const configs: Record<WorkspaceEnvironment, WorkspaceConfig> = {
|
|
225
|
+
localhost: {
|
|
226
|
+
host: 'http://localhost:8000',
|
|
227
|
+
proxy: '/api', // Optional: remove to skip proxy setup
|
|
228
|
+
openapi_url: 'http://localhost:8000/openapi.json',
|
|
229
|
+
},
|
|
230
|
+
development: {
|
|
231
|
+
host: '${productionHost}',
|
|
232
|
+
proxy: '/api',
|
|
233
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
234
|
+
},
|
|
235
|
+
production: {
|
|
236
|
+
host: '${productionHost}',
|
|
237
|
+
proxy: '/api',
|
|
238
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
239
|
+
},
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export default defineWorkspace(configs)
|
|
243
|
+
`;
|
|
244
|
+
const configPath = node_path.resolve(root, configFile);
|
|
245
|
+
node_fs.writeFileSync(configPath, configContent, "utf-8");
|
|
246
|
+
console.log(`
|
|
247
|
+
\u2705 Created ${configFile}`);
|
|
248
|
+
console.log(` Production host: ${productionHost}`);
|
|
249
|
+
console.log(` Local dev host: http://localhost:8000
|
|
250
|
+
`);
|
|
251
|
+
const setupResponse = await prompts__default([
|
|
252
|
+
{
|
|
253
|
+
type: "confirm",
|
|
254
|
+
name: "updatePackageJson",
|
|
255
|
+
message: "Add/update dev scripts in package.json?",
|
|
256
|
+
initial: true
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
type: "confirm",
|
|
260
|
+
name: "updateViteConfig",
|
|
261
|
+
message: "Create/update vite.config.ts?",
|
|
262
|
+
initial: true
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
type: "confirm",
|
|
266
|
+
name: "createTsConfig",
|
|
267
|
+
message: "Create tsconfig.app.json with path aliases?",
|
|
268
|
+
initial: true
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
type: "confirm",
|
|
272
|
+
name: "generateNetlify",
|
|
273
|
+
message: "Generate netlify.toml for deployment?",
|
|
274
|
+
initial: true
|
|
275
|
+
}
|
|
276
|
+
]);
|
|
277
|
+
if (setupResponse.updatePackageJson) {
|
|
278
|
+
updatePackageJsonScripts(root);
|
|
279
|
+
}
|
|
280
|
+
if (setupResponse.updateViteConfig) {
|
|
281
|
+
updateViteConfig(root);
|
|
282
|
+
}
|
|
283
|
+
if (setupResponse.createTsConfig) {
|
|
284
|
+
createTsConfig(root);
|
|
285
|
+
}
|
|
286
|
+
if (setupResponse.generateNetlify) {
|
|
287
|
+
const prodConfig = {
|
|
288
|
+
host: productionHost,
|
|
289
|
+
proxy: "/api"
|
|
290
|
+
};
|
|
291
|
+
netlify.writeNetlifyConfig(prodConfig, node_path.resolve(root, "netlify.toml"));
|
|
292
|
+
}
|
|
293
|
+
console.log("\n\u{1F4A1} You can edit these files to customize your configuration.\n");
|
|
294
|
+
}
|
|
295
|
+
function updatePackageJsonScripts(root) {
|
|
296
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
297
|
+
if (!node_fs.existsSync(packageJsonPath)) {
|
|
298
|
+
console.log("\u26A0\uFE0F No package.json found, skipping script update");
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
|
|
303
|
+
if (!packageJson.scripts) {
|
|
304
|
+
packageJson.scripts = {};
|
|
305
|
+
}
|
|
306
|
+
const scriptsToAdd = {
|
|
307
|
+
"dev": "vite",
|
|
308
|
+
"dev:local": "vite --mode localhost",
|
|
309
|
+
"build": "vite build",
|
|
310
|
+
"preview": "vite preview"
|
|
311
|
+
};
|
|
312
|
+
let modified = false;
|
|
313
|
+
for (const [key, value] of Object.entries(scriptsToAdd)) {
|
|
314
|
+
if (key === "dev" || key === "dev:local") {
|
|
315
|
+
if (packageJson.scripts[key] !== value) {
|
|
316
|
+
packageJson.scripts[key] = value;
|
|
317
|
+
modified = true;
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
if (!packageJson.scripts[key]) {
|
|
321
|
+
packageJson.scripts[key] = value;
|
|
322
|
+
modified = true;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (modified) {
|
|
327
|
+
node_fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
328
|
+
`, "utf-8");
|
|
329
|
+
console.log("\u2705 Updated package.json with dev scripts");
|
|
330
|
+
} else {
|
|
331
|
+
console.log("\u2139\uFE0F Scripts already up to date in package.json");
|
|
332
|
+
}
|
|
333
|
+
} catch (error) {
|
|
334
|
+
console.error("\u274C Failed to update package.json:", error);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function createTsConfig(root) {
|
|
338
|
+
const tsConfigPath = node_path.resolve(root, "tsconfig.app.json");
|
|
339
|
+
const tsConfigExists = node_fs.existsSync(tsConfigPath);
|
|
340
|
+
if (tsConfigExists) {
|
|
341
|
+
console.log("\u26A0\uFE0F tsconfig.app.json already exists, skipping");
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const tsConfigContent = `{
|
|
345
|
+
"extends": "../tsconfig.json",
|
|
346
|
+
"compilerOptions": {
|
|
347
|
+
"composite": true,
|
|
348
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
349
|
+
"baseUrl": ".",
|
|
350
|
+
"paths": {
|
|
351
|
+
"@/*": ["./src/*"],
|
|
352
|
+
"@shared/*": ["../shared/*"]
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
"include": ["src/**/*", "src/**/*.vue"],
|
|
356
|
+
"exclude": ["node_modules"]
|
|
357
|
+
}
|
|
358
|
+
`;
|
|
359
|
+
node_fs.writeFileSync(tsConfigPath, tsConfigContent, "utf-8");
|
|
360
|
+
console.log("\u2705 Created tsconfig.app.json");
|
|
361
|
+
}
|
|
362
|
+
function updateViteConfig(root) {
|
|
363
|
+
const viteConfigPath = node_path.resolve(root, "vite.config.ts");
|
|
364
|
+
const viteConfigExists = node_fs.existsSync(viteConfigPath);
|
|
365
|
+
if (viteConfigExists) {
|
|
366
|
+
const existingConfig = node_fs.readFileSync(viteConfigPath, "utf-8");
|
|
367
|
+
if (existingConfig.includes("@bagelink/workspace")) {
|
|
368
|
+
console.log("\u2139\uFE0F vite.config.ts already configured");
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
console.log("\u26A0\uFE0F vite.config.ts exists. Please manually add the bagelink plugin:");
|
|
372
|
+
console.log("");
|
|
373
|
+
console.log(" import { bagelink } from '@bagelink/workspace/vite'");
|
|
374
|
+
console.log(" import workspace from './bgl.config'");
|
|
375
|
+
console.log("");
|
|
376
|
+
console.log(" plugins: [");
|
|
377
|
+
console.log(" vue(),");
|
|
378
|
+
console.log(" bagelink({ workspace }),");
|
|
379
|
+
console.log(" ]");
|
|
380
|
+
console.log("");
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const viteConfigContent = `import { defineConfig } from 'vite'
|
|
384
|
+
import vue from '@vitejs/plugin-vue'
|
|
385
|
+
import { bagelink } from '@bagelink/workspace/vite'
|
|
386
|
+
import workspace from './bgl.config'
|
|
387
|
+
|
|
388
|
+
// https://vitejs.dev/config/
|
|
389
|
+
export default defineConfig({
|
|
390
|
+
plugins: [
|
|
391
|
+
vue(),
|
|
392
|
+
bagelink({ workspace }),
|
|
393
|
+
],
|
|
394
|
+
})
|
|
395
|
+
`;
|
|
396
|
+
node_fs.writeFileSync(viteConfigPath, viteConfigContent, "utf-8");
|
|
397
|
+
console.log("\u2705 Created vite.config.ts");
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const REDUNDANT_FILES = [
|
|
401
|
+
// Old ESLint configs
|
|
402
|
+
".eslintrc",
|
|
403
|
+
".eslintrc.json",
|
|
404
|
+
".eslintrc.js",
|
|
405
|
+
".eslintrc.cjs",
|
|
406
|
+
".eslintrc.yaml",
|
|
407
|
+
".eslintrc.yml",
|
|
408
|
+
// Oxlint
|
|
409
|
+
"oxlint.json",
|
|
410
|
+
// Old Prettier configs (we create .prettierrc)
|
|
411
|
+
"prettier.config.js",
|
|
412
|
+
"prettier.config.cjs",
|
|
413
|
+
"prettier.config.mjs",
|
|
414
|
+
".prettierrc.json",
|
|
415
|
+
".prettierrc.yaml",
|
|
416
|
+
".prettierrc.yml",
|
|
417
|
+
".prettierrc.js",
|
|
418
|
+
".prettierrc.cjs",
|
|
419
|
+
".prettierrc.mjs",
|
|
420
|
+
".prettierrc.toml"
|
|
421
|
+
];
|
|
422
|
+
async function setupLint(root = process__default.cwd(), isWorkspace = false) {
|
|
423
|
+
console.log("\n\u{1F50D} Setting up linting...\n");
|
|
424
|
+
const response = await prompts__default([
|
|
425
|
+
{
|
|
426
|
+
type: "multiselect",
|
|
427
|
+
name: "configs",
|
|
428
|
+
message: "Select configurations to set up:",
|
|
429
|
+
choices: [
|
|
430
|
+
{ title: "ESLint", value: "eslint", selected: true },
|
|
431
|
+
{ title: "Prettier", value: "prettier", selected: true },
|
|
432
|
+
{ title: "EditorConfig", value: "editorconfig", selected: true },
|
|
433
|
+
{ title: "Git Hooks", value: "githooks", selected: false }
|
|
434
|
+
]
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
type: "confirm",
|
|
438
|
+
name: "cleanRedundant",
|
|
439
|
+
message: "Clean up redundant lint config files?",
|
|
440
|
+
initial: true
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
type: "confirm",
|
|
444
|
+
name: "installDeps",
|
|
445
|
+
message: "Install dependencies?",
|
|
446
|
+
initial: true
|
|
447
|
+
}
|
|
448
|
+
]);
|
|
449
|
+
if (!response || !response.configs) {
|
|
450
|
+
console.log("\n\u274C Setup cancelled.\n");
|
|
451
|
+
process__default.exit(1);
|
|
452
|
+
}
|
|
453
|
+
const { configs, cleanRedundant, installDeps } = response;
|
|
454
|
+
if (cleanRedundant) {
|
|
455
|
+
await cleanRedundantFiles(root);
|
|
456
|
+
}
|
|
457
|
+
if (configs.includes("eslint")) {
|
|
458
|
+
createEslintConfig(root, isWorkspace);
|
|
459
|
+
}
|
|
460
|
+
if (configs.includes("prettier")) {
|
|
461
|
+
createPrettierConfig(root);
|
|
462
|
+
}
|
|
463
|
+
if (configs.includes("editorconfig")) {
|
|
464
|
+
createEditorConfig(root);
|
|
465
|
+
}
|
|
466
|
+
if (configs.includes("githooks")) {
|
|
467
|
+
createGitHooks(root);
|
|
468
|
+
}
|
|
469
|
+
updatePackageJsonLint(root, configs);
|
|
470
|
+
if (installDeps) {
|
|
471
|
+
console.log("\n\u{1F4E6} Installing dependencies...");
|
|
472
|
+
console.log("Run: bun add -D @bagelink/lint-config eslint prettier typescript");
|
|
473
|
+
}
|
|
474
|
+
console.log("\n\u2705 Linting setup complete!");
|
|
475
|
+
console.log("\nAvailable commands:");
|
|
476
|
+
console.log(" bun run lint - Run linter");
|
|
477
|
+
console.log(" bun run lint:fix - Fix linting issues");
|
|
478
|
+
console.log(" bun run format - Format code with Prettier");
|
|
479
|
+
console.log("");
|
|
480
|
+
}
|
|
481
|
+
function createEslintConfig(root, isWorkspace) {
|
|
482
|
+
const configPath = node_path.resolve(root, "eslint.config.js");
|
|
483
|
+
const config = isWorkspace ? `import { defineConfig } from '@bagelink/lint-config/eslint'
|
|
484
|
+
|
|
485
|
+
export default defineConfig({
|
|
486
|
+
// Workspace-level ESLint config
|
|
487
|
+
ignores: ['**/dist/**', '**/node_modules/**', '**/.bun-cache/**'],
|
|
488
|
+
})
|
|
489
|
+
` : `import vue3Config from '@bagelink/lint-config/eslint/vue3'
|
|
490
|
+
|
|
491
|
+
export default vue3Config
|
|
492
|
+
`;
|
|
493
|
+
node_fs.writeFileSync(configPath, config);
|
|
494
|
+
console.log("\u2705 Created eslint.config.js");
|
|
495
|
+
}
|
|
496
|
+
function createPrettierConfig(root) {
|
|
497
|
+
const configPath = node_path.resolve(root, ".prettierrc");
|
|
498
|
+
const config = {
|
|
499
|
+
semi: false,
|
|
500
|
+
singleQuote: true,
|
|
501
|
+
tabWidth: 2,
|
|
502
|
+
useTabs: true,
|
|
503
|
+
trailingComma: "all",
|
|
504
|
+
printWidth: 100,
|
|
505
|
+
arrowParens: "avoid"
|
|
506
|
+
};
|
|
507
|
+
node_fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
508
|
+
`);
|
|
509
|
+
console.log("\u2705 Created .prettierrc");
|
|
510
|
+
const ignorePath = node_path.resolve(root, ".prettierignore");
|
|
511
|
+
const ignore = `dist
|
|
512
|
+
node_modules
|
|
513
|
+
.bun-cache
|
|
514
|
+
*.min.js
|
|
515
|
+
*.min.css
|
|
516
|
+
`;
|
|
517
|
+
node_fs.writeFileSync(ignorePath, ignore);
|
|
518
|
+
console.log("\u2705 Created .prettierignore");
|
|
519
|
+
}
|
|
520
|
+
function createEditorConfig(root) {
|
|
521
|
+
const configPath = node_path.resolve(root, ".editorconfig");
|
|
522
|
+
const config = `root = true
|
|
523
|
+
|
|
524
|
+
[*]
|
|
525
|
+
charset = utf-8
|
|
526
|
+
indent_style = tab
|
|
527
|
+
indent_size = 2
|
|
528
|
+
end_of_line = lf
|
|
529
|
+
insert_final_newline = true
|
|
530
|
+
trim_trailing_whitespace = true
|
|
531
|
+
|
|
532
|
+
[*.md]
|
|
533
|
+
trim_trailing_whitespace = false
|
|
534
|
+
|
|
535
|
+
[*.{json,yml,yaml}]
|
|
536
|
+
indent_style = space
|
|
537
|
+
indent_size = 2
|
|
538
|
+
`;
|
|
539
|
+
node_fs.writeFileSync(configPath, config);
|
|
540
|
+
console.log("\u2705 Created .editorconfig");
|
|
541
|
+
}
|
|
542
|
+
function createGitHooks(root) {
|
|
543
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
544
|
+
if (!node_fs.existsSync(packageJsonPath)) {
|
|
545
|
+
console.warn("\u26A0\uFE0F No package.json found, skipping git hooks");
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
const lintStagedConfig = {
|
|
549
|
+
"*.{js,jsx,ts,tsx,vue}": ["eslint --fix"],
|
|
550
|
+
"*.{json,md,yml,yaml}": ["prettier --write"]
|
|
551
|
+
};
|
|
552
|
+
node_fs.writeFileSync(
|
|
553
|
+
node_path.resolve(root, ".lintstagedrc"),
|
|
554
|
+
`${JSON.stringify(lintStagedConfig, null, 2)}
|
|
555
|
+
`
|
|
556
|
+
);
|
|
557
|
+
console.log("\u2705 Created .lintstagedrc");
|
|
558
|
+
console.log("\u2139\uFE0F Add simple-git-hooks and lint-staged to devDependencies");
|
|
559
|
+
console.log(" Then run: npx simple-git-hooks");
|
|
560
|
+
}
|
|
561
|
+
async function cleanRedundantFiles(root) {
|
|
562
|
+
const foundFiles = [];
|
|
563
|
+
for (const file of REDUNDANT_FILES) {
|
|
564
|
+
const filePath = node_path.resolve(root, file);
|
|
565
|
+
if (node_fs.existsSync(filePath)) {
|
|
566
|
+
foundFiles.push(file);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
if (foundFiles.length === 0) {
|
|
570
|
+
console.log("\u2728 No redundant files found");
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
console.log("\n\u{1F4CB} Found redundant files:");
|
|
574
|
+
foundFiles.forEach((file) => {
|
|
575
|
+
console.log(` - ${file}`);
|
|
576
|
+
});
|
|
577
|
+
const confirmResponse = await prompts__default({
|
|
578
|
+
type: "confirm",
|
|
579
|
+
name: "confirm",
|
|
580
|
+
message: `Delete ${foundFiles.length} redundant file${foundFiles.length > 1 ? "s" : ""}?`,
|
|
581
|
+
initial: true
|
|
582
|
+
});
|
|
583
|
+
if (!confirmResponse.confirm) {
|
|
584
|
+
console.log("\u23ED\uFE0F Skipped cleaning redundant files");
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
let deleted = 0;
|
|
588
|
+
for (const file of foundFiles) {
|
|
589
|
+
try {
|
|
590
|
+
node_fs.unlinkSync(node_path.resolve(root, file));
|
|
591
|
+
console.log(`\u{1F5D1}\uFE0F Deleted ${file}`);
|
|
592
|
+
deleted++;
|
|
593
|
+
} catch (error) {
|
|
594
|
+
console.error(`\u274C Failed to delete ${file}:`, error);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
console.log(`\u2705 Cleaned up ${deleted} file${deleted > 1 ? "s" : ""}`);
|
|
598
|
+
}
|
|
599
|
+
function updatePackageJsonLint(root, configs) {
|
|
600
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
601
|
+
if (!node_fs.existsSync(packageJsonPath)) {
|
|
602
|
+
console.warn("\u26A0\uFE0F No package.json found");
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
try {
|
|
606
|
+
const packageJson = JSON.parse(
|
|
607
|
+
node_fs.readFileSync(packageJsonPath, "utf-8")
|
|
608
|
+
);
|
|
609
|
+
if (!packageJson.scripts) {
|
|
610
|
+
packageJson.scripts = {};
|
|
611
|
+
}
|
|
612
|
+
if (configs.includes("eslint")) {
|
|
613
|
+
if (!packageJson.scripts.lint) {
|
|
614
|
+
packageJson.scripts.lint = "eslint .";
|
|
615
|
+
}
|
|
616
|
+
if (!packageJson.scripts["lint:fix"]) {
|
|
617
|
+
packageJson.scripts["lint:fix"] = "eslint . --fix";
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if (configs.includes("prettier")) {
|
|
621
|
+
if (!packageJson.scripts.format) {
|
|
622
|
+
packageJson.scripts.format = "prettier --write .";
|
|
623
|
+
}
|
|
624
|
+
if (!packageJson.scripts["format:check"]) {
|
|
625
|
+
packageJson.scripts["format:check"] = "prettier --check .";
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
node_fs.writeFileSync(
|
|
629
|
+
packageJsonPath,
|
|
630
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
631
|
+
`
|
|
632
|
+
);
|
|
633
|
+
console.log("\u2705 Updated package.json with lint scripts");
|
|
634
|
+
} catch (error) {
|
|
635
|
+
console.error("\u274C Failed to update package.json:", error);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
async function generateSDK(root = process__default.cwd()) {
|
|
640
|
+
console.log("\n\u{1F527} Generating SDK from OpenAPI...\n");
|
|
641
|
+
let config = null;
|
|
642
|
+
let openApiUrl;
|
|
643
|
+
try {
|
|
644
|
+
const configPath = node_path.resolve(root, "bgl.config.ts");
|
|
645
|
+
if (node_fs.existsSync(configPath)) {
|
|
646
|
+
const module = await import(`file://${configPath}`);
|
|
647
|
+
const workspace = module.default;
|
|
648
|
+
if (typeof workspace === "function") {
|
|
649
|
+
config = workspace("development");
|
|
650
|
+
if (config?.openapi_url) {
|
|
651
|
+
openApiUrl = config.openapi_url;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
} catch {
|
|
656
|
+
}
|
|
657
|
+
const response = await prompts__default([
|
|
658
|
+
{
|
|
659
|
+
type: openApiUrl !== void 0 ? null : "text",
|
|
660
|
+
name: "openApiUrl",
|
|
661
|
+
message: "OpenAPI spec URL:",
|
|
662
|
+
initial: openApiUrl ?? "http://localhost:8000/openapi.json"
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
type: "text",
|
|
666
|
+
name: "outputDir",
|
|
667
|
+
message: "Output directory:",
|
|
668
|
+
initial: "./src/api"
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
type: "confirm",
|
|
672
|
+
name: "splitFiles",
|
|
673
|
+
message: "Split into organized files?",
|
|
674
|
+
initial: true
|
|
675
|
+
}
|
|
676
|
+
]);
|
|
677
|
+
if (!response) {
|
|
678
|
+
console.log("\n\u274C SDK generation cancelled.\n");
|
|
679
|
+
process__default.exit(1);
|
|
680
|
+
}
|
|
681
|
+
const finalUrl = openApiUrl ?? response.openApiUrl;
|
|
682
|
+
const { outputDir, splitFiles } = response;
|
|
683
|
+
console.log(`
|
|
684
|
+
\u{1F4E1} Fetching OpenAPI spec from: ${finalUrl}`);
|
|
685
|
+
console.log(`\u{1F4C1} Output directory: ${outputDir}
|
|
686
|
+
`);
|
|
687
|
+
try {
|
|
688
|
+
const { openAPI } = await import('@bagelink/sdk');
|
|
689
|
+
const { readFileSync } = await import('node:fs');
|
|
690
|
+
const { dirname, join } = await import('node:path');
|
|
691
|
+
const { fileURLToPath } = await import('node:url');
|
|
692
|
+
const { types, code } = await openAPI(finalUrl, "/api");
|
|
693
|
+
const outputPath = node_path.resolve(root, outputDir);
|
|
694
|
+
if (!node_fs.existsSync(outputPath)) {
|
|
695
|
+
node_fs.mkdirSync(outputPath, { recursive: true });
|
|
696
|
+
}
|
|
697
|
+
const typesPath = node_path.resolve(outputPath, "types.d.ts");
|
|
698
|
+
node_fs.writeFileSync(typesPath, types);
|
|
699
|
+
console.log("\u2705 Generated types.d.ts");
|
|
700
|
+
const apiPath = node_path.resolve(outputPath, "api.ts");
|
|
701
|
+
node_fs.writeFileSync(apiPath, code);
|
|
702
|
+
console.log("\u2705 Generated api.ts");
|
|
703
|
+
console.log("\u2139\uFE0F Stream utilities are imported from @bagelink/sdk");
|
|
704
|
+
if (splitFiles) {
|
|
705
|
+
console.log("\n\u{1F500} Splitting into organized files...");
|
|
706
|
+
console.log("\u2139\uFE0F File splitting requires @bagelink/sdk bin scripts");
|
|
707
|
+
console.log(" Keeping monolithic structure for now");
|
|
708
|
+
}
|
|
709
|
+
console.log("\n\u2705 SDK generated successfully!");
|
|
710
|
+
console.log(`
|
|
711
|
+
Import directly in your code:`);
|
|
712
|
+
console.log(` import { agents } from '${outputDir.replace("./src/", "./")}/api'`);
|
|
713
|
+
console.log(` import type { SendMessageRequest } from '${outputDir.replace("./src/", "./")}/types.d'`);
|
|
714
|
+
console.log("");
|
|
715
|
+
} catch (error) {
|
|
716
|
+
console.error("\n\u274C Failed to generate SDK:");
|
|
717
|
+
if (error instanceof Error) {
|
|
718
|
+
console.error(error.message);
|
|
719
|
+
} else {
|
|
720
|
+
console.error(error);
|
|
721
|
+
}
|
|
722
|
+
console.log("\nMake sure:");
|
|
723
|
+
console.log(" 1. @bagelink/sdk is installed: bun add -D @bagelink/sdk");
|
|
724
|
+
console.log(" 2. OpenAPI URL is accessible");
|
|
725
|
+
console.log(" 3. API server is running (if using localhost)");
|
|
726
|
+
process__default.exit(1);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
async function generateSDKForWorkspace(root = process__default.cwd()) {
|
|
730
|
+
console.log("\n\u{1F3E2} Generating SDK for workspace...\n");
|
|
731
|
+
let config = null;
|
|
732
|
+
let openApiUrl;
|
|
733
|
+
try {
|
|
734
|
+
const configPath = node_path.resolve(root, "bgl.config.ts");
|
|
735
|
+
if (node_fs.existsSync(configPath)) {
|
|
736
|
+
const module = await import(`file://${configPath}`);
|
|
737
|
+
const workspace = module.default;
|
|
738
|
+
if (typeof workspace === "function") {
|
|
739
|
+
config = workspace("development");
|
|
740
|
+
if (config?.openapi_url) {
|
|
741
|
+
openApiUrl = config.openapi_url;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
} catch {
|
|
746
|
+
}
|
|
747
|
+
const response = await prompts__default({
|
|
748
|
+
type: openApiUrl !== void 0 ? null : "text",
|
|
749
|
+
name: "openApiUrl",
|
|
750
|
+
message: "OpenAPI spec URL:",
|
|
751
|
+
initial: openApiUrl ?? "http://localhost:8000/openapi.json"
|
|
752
|
+
});
|
|
753
|
+
if (response === void 0 || openApiUrl === void 0 && !response.openApiUrl) {
|
|
754
|
+
console.log("\n\u274C SDK generation cancelled.\n");
|
|
755
|
+
process__default.exit(1);
|
|
756
|
+
}
|
|
757
|
+
const finalUrl = openApiUrl ?? response.openApiUrl;
|
|
758
|
+
const outputDir = "./shared";
|
|
759
|
+
console.log(`
|
|
760
|
+
\u{1F4E1} Fetching OpenAPI spec from: ${finalUrl}`);
|
|
761
|
+
console.log(`\u{1F4C1} Output directory: ${outputDir}
|
|
762
|
+
`);
|
|
763
|
+
try {
|
|
764
|
+
const { openAPI } = await import('@bagelink/sdk');
|
|
765
|
+
const { types, code } = await openAPI(finalUrl, "/api");
|
|
766
|
+
const outputPath = node_path.resolve(root, outputDir);
|
|
767
|
+
if (!node_fs.existsSync(outputPath)) {
|
|
768
|
+
node_fs.mkdirSync(outputPath, { recursive: true });
|
|
769
|
+
}
|
|
770
|
+
const typesPath = node_path.resolve(outputPath, "types.d.ts");
|
|
771
|
+
node_fs.writeFileSync(typesPath, types);
|
|
772
|
+
console.log("\u2705 Generated types.d.ts");
|
|
773
|
+
const apiPath = node_path.resolve(outputPath, "api.ts");
|
|
774
|
+
node_fs.writeFileSync(apiPath, code);
|
|
775
|
+
console.log("\u2705 Generated api.ts");
|
|
776
|
+
console.log("\n\u2705 SDK generated successfully in shared folder!");
|
|
777
|
+
console.log(`
|
|
778
|
+
Import from shared in your projects:`);
|
|
779
|
+
console.log(` import { agents } from '../shared/api'`);
|
|
780
|
+
console.log(` import type { SendMessageRequest } from '../shared/types'`);
|
|
781
|
+
console.log("");
|
|
782
|
+
} catch (error) {
|
|
783
|
+
console.error("\n\u274C Failed to generate SDK:");
|
|
784
|
+
if (error instanceof Error) {
|
|
785
|
+
console.error(error.message);
|
|
786
|
+
} else {
|
|
787
|
+
console.error(error);
|
|
788
|
+
}
|
|
789
|
+
console.log("\nMake sure:");
|
|
790
|
+
console.log(" 1. @bagelink/sdk is installed: bun add -D @bagelink/sdk");
|
|
791
|
+
console.log(" 2. OpenAPI URL is accessible");
|
|
792
|
+
console.log(" 3. API server is running (if using localhost)");
|
|
793
|
+
process__default.exit(1);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
13
796
|
|
|
14
797
|
const [, , command, subcommand, ...args] = process__default.argv;
|
|
15
798
|
async function main() {
|
|
16
799
|
if (command === "init") {
|
|
17
800
|
const createWorkspace = subcommand === "--workspace" || subcommand === "-w" || args.includes("--workspace") || args.includes("-w");
|
|
801
|
+
let targetPath = process__default.cwd();
|
|
802
|
+
if (subcommand && !subcommand.startsWith("-")) {
|
|
803
|
+
targetPath = subcommand === "." ? process__default.cwd() : node_path.resolve(process__default.cwd(), subcommand);
|
|
804
|
+
}
|
|
18
805
|
if (createWorkspace) {
|
|
19
|
-
await
|
|
806
|
+
await netlify.initWorkspace();
|
|
20
807
|
} else {
|
|
21
|
-
await
|
|
808
|
+
await generateWorkspaceConfig(targetPath);
|
|
22
809
|
}
|
|
23
810
|
} else if (command === "add") {
|
|
24
811
|
const projectName = subcommand;
|
|
@@ -27,9 +814,9 @@ async function main() {
|
|
|
27
814
|
console.log("Usage: bgl add <project-name>");
|
|
28
815
|
process__default.exit(1);
|
|
29
816
|
}
|
|
30
|
-
await
|
|
817
|
+
await netlify.addProject(projectName);
|
|
31
818
|
} else if (command === "list") {
|
|
32
|
-
const projects =
|
|
819
|
+
const projects = netlify.listProjects();
|
|
33
820
|
if (projects.length === 0) {
|
|
34
821
|
console.log("No projects found");
|
|
35
822
|
} else {
|
|
@@ -43,13 +830,13 @@ async function main() {
|
|
|
43
830
|
if (subcommand === "init") {
|
|
44
831
|
const forceWorkspace = args.includes("--workspace") || args.includes("-w");
|
|
45
832
|
const forceProject = args.includes("--project") || args.includes("-p");
|
|
46
|
-
let workspaceMode =
|
|
833
|
+
let workspaceMode = isWorkspace(process__default.cwd());
|
|
47
834
|
if (forceWorkspace) workspaceMode = true;
|
|
48
835
|
if (forceProject) workspaceMode = false;
|
|
49
836
|
if (workspaceMode) {
|
|
50
837
|
console.log("\u2713 Detected workspace mode");
|
|
51
838
|
}
|
|
52
|
-
await
|
|
839
|
+
await setupLint(process__default.cwd(), workspaceMode);
|
|
53
840
|
} else {
|
|
54
841
|
console.log(`
|
|
55
842
|
Lint Commands:
|
|
@@ -63,14 +850,14 @@ Lint Commands:
|
|
|
63
850
|
if (subcommand === "generate") {
|
|
64
851
|
const forceWorkspace = args.includes("--workspace") || args.includes("-w");
|
|
65
852
|
const forceProject = args.includes("--project") || args.includes("-p");
|
|
66
|
-
let workspaceMode =
|
|
853
|
+
let workspaceMode = isWorkspace(process__default.cwd());
|
|
67
854
|
if (forceWorkspace) workspaceMode = true;
|
|
68
855
|
if (forceProject) workspaceMode = false;
|
|
69
856
|
if (workspaceMode) {
|
|
70
857
|
console.log("\u2713 Detected workspace mode - will generate for multiple projects");
|
|
71
|
-
await
|
|
858
|
+
await generateSDKForWorkspace();
|
|
72
859
|
} else {
|
|
73
|
-
await
|
|
860
|
+
await generateSDK(process__default.cwd());
|
|
74
861
|
}
|
|
75
862
|
} else {
|
|
76
863
|
console.log(`
|
|
@@ -81,21 +868,46 @@ SDK Commands:
|
|
|
81
868
|
`);
|
|
82
869
|
process__default.exit(1);
|
|
83
870
|
}
|
|
871
|
+
} else if (command === "dev") {
|
|
872
|
+
const { filter, additionalArgs } = parseFilterArgs(
|
|
873
|
+
void 0,
|
|
874
|
+
subcommand,
|
|
875
|
+
args
|
|
876
|
+
);
|
|
877
|
+
const exitCode = await runDev(filter, additionalArgs);
|
|
878
|
+
process__default.exit(exitCode);
|
|
879
|
+
} else if (command === "build") {
|
|
880
|
+
const { filter, additionalArgs } = parseFilterArgs(
|
|
881
|
+
void 0,
|
|
882
|
+
subcommand,
|
|
883
|
+
args
|
|
884
|
+
);
|
|
885
|
+
const exitCode = await runBuild(filter, additionalArgs);
|
|
886
|
+
process__default.exit(exitCode);
|
|
84
887
|
} else {
|
|
85
888
|
console.log(`
|
|
86
889
|
Bagel Workspace CLI
|
|
87
890
|
|
|
88
891
|
Usage:
|
|
89
|
-
bgl init
|
|
892
|
+
bgl init [path] Generate bgl.config.ts for single project
|
|
893
|
+
Examples: bgl init, bgl init ., bgl init ./my-app
|
|
90
894
|
bgl init --workspace Create a new workspace with multiple projects
|
|
91
895
|
bgl add <name> Add a new project to workspace
|
|
92
896
|
bgl list List all projects in workspace
|
|
897
|
+
bgl dev [filter] [...args] Run dev servers with clean output (default: './!shared*')
|
|
898
|
+
Examples:
|
|
899
|
+
bgl dev --mode localhost
|
|
900
|
+
bgl dev --mode staging
|
|
901
|
+
bgl dev admin --mode production
|
|
902
|
+
bgl build [project] [...args] Build project by directory (default: all projects)
|
|
903
|
+
Example: bgl build --mode production
|
|
93
904
|
bgl lint init Set up linting (auto-detects workspace)
|
|
94
905
|
bgl sdk generate Generate SDK (auto-detects workspace)
|
|
95
906
|
|
|
96
907
|
Options:
|
|
97
908
|
--workspace, -w Force workspace mode
|
|
98
909
|
--project, -p Force single project mode
|
|
910
|
+
--mode <env> Set environment (matches bgl.config.ts keys)
|
|
99
911
|
--help, -h Show this help message
|
|
100
912
|
|
|
101
913
|
Note: Commands auto-detect workspace mode based on directory structure
|
|
@@ -103,6 +915,34 @@ Note: Commands auto-detect workspace mode based on directory structure
|
|
|
103
915
|
process__default.exit(command === "--help" || command === "-h" ? 0 : 1);
|
|
104
916
|
}
|
|
105
917
|
}
|
|
918
|
+
function normalizeFilter(input) {
|
|
919
|
+
if (input.startsWith(".") || input.includes("*") || input.includes("[")) {
|
|
920
|
+
return input;
|
|
921
|
+
}
|
|
922
|
+
return `./${input}`;
|
|
923
|
+
}
|
|
924
|
+
function parseFilterArgs(defaultFilter, subcommandArg, argsList = []) {
|
|
925
|
+
const tokens = [subcommandArg, ...argsList].filter(Boolean);
|
|
926
|
+
const flagsWithValues = /* @__PURE__ */ new Set(["--mode", "--host", "--port"]);
|
|
927
|
+
const nonFlagIndexes = [];
|
|
928
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
929
|
+
const token = tokens[i];
|
|
930
|
+
if (token.startsWith("-")) {
|
|
931
|
+
if (flagsWithValues.has(token)) {
|
|
932
|
+
i++;
|
|
933
|
+
}
|
|
934
|
+
} else {
|
|
935
|
+
const prevToken = i > 0 ? tokens[i - 1] : null;
|
|
936
|
+
if (!prevToken || !flagsWithValues.has(prevToken)) {
|
|
937
|
+
nonFlagIndexes.push(i);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
const filterIndex = nonFlagIndexes.length > 0 ? nonFlagIndexes[nonFlagIndexes.length - 1] : -1;
|
|
942
|
+
const filter = filterIndex >= 0 ? normalizeFilter(tokens[filterIndex]) : defaultFilter;
|
|
943
|
+
const additionalArgs = filterIndex >= 0 ? tokens.filter((_, index) => index !== filterIndex) : tokens;
|
|
944
|
+
return { filter, additionalArgs };
|
|
945
|
+
}
|
|
106
946
|
main().catch((error) => {
|
|
107
947
|
console.error("Error:", error);
|
|
108
948
|
process__default.exit(1);
|