@bagelink/workspace 1.9.0 → 1.10.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/README.md +95 -3
- package/bin/bgl.ts +59 -12
- package/dist/bin/bgl.cjs +55 -18
- package/dist/bin/bgl.mjs +51 -14
- package/dist/index.cjs +18 -14
- package/dist/index.d.cts +25 -3
- package/dist/index.d.mts +25 -3
- package/dist/index.d.ts +25 -3
- package/dist/index.mjs +2 -2
- package/dist/shared/{workspace.cX7U2RUq.mjs → workspace.B6LGs4Ed.mjs} +361 -175
- package/dist/shared/{workspace.CCUm_5GG.cjs → workspace.Ndvn7T1u.cjs} +353 -163
- package/package.json +6 -1
- package/src/detect.ts +91 -0
- package/src/index.ts +3 -1
- package/src/sdk.ts +186 -0
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
const node_fs = require('node:fs');
|
|
4
4
|
const node_path = require('node:path');
|
|
5
|
-
const process = require('node:process');
|
|
5
|
+
const process$1 = require('node:process');
|
|
6
6
|
const prompts = require('prompts');
|
|
7
7
|
|
|
8
8
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
9
9
|
|
|
10
|
-
const process__default = /*#__PURE__*/_interopDefaultCompat(process);
|
|
10
|
+
const process__default = /*#__PURE__*/_interopDefaultCompat(process$1);
|
|
11
11
|
const prompts__default = /*#__PURE__*/_interopDefaultCompat(prompts);
|
|
12
12
|
|
|
13
13
|
function generateNetlifyRedirect(config) {
|
|
@@ -238,6 +238,312 @@ export default defineConfig(({ mode }) => {
|
|
|
238
238
|
console.log("\u2705 Created vite.config.ts");
|
|
239
239
|
}
|
|
240
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
|
+
require("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(), projectName) {
|
|
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
|
+
openApiUrl = config.openapi_url;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
} catch (error) {
|
|
426
|
+
console.warn("\u26A0\uFE0F Could not load bgl.config.ts");
|
|
427
|
+
}
|
|
428
|
+
const response = await prompts__default([
|
|
429
|
+
{
|
|
430
|
+
type: openApiUrl ? null : "text",
|
|
431
|
+
name: "openApiUrl",
|
|
432
|
+
message: "OpenAPI spec URL:",
|
|
433
|
+
initial: openApiUrl || "http://localhost:8000/openapi.json"
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
type: "text",
|
|
437
|
+
name: "outputDir",
|
|
438
|
+
message: "Output directory:",
|
|
439
|
+
initial: "./src/api"
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
type: "confirm",
|
|
443
|
+
name: "splitFiles",
|
|
444
|
+
message: "Split into organized files?",
|
|
445
|
+
initial: true
|
|
446
|
+
}
|
|
447
|
+
]);
|
|
448
|
+
if (!response) {
|
|
449
|
+
console.log("\n\u274C SDK generation cancelled.\n");
|
|
450
|
+
process__default.exit(1);
|
|
451
|
+
}
|
|
452
|
+
const finalUrl = openApiUrl || response.openApiUrl;
|
|
453
|
+
const { outputDir, splitFiles } = response;
|
|
454
|
+
console.log(`
|
|
455
|
+
\u{1F4E1} Fetching OpenAPI spec from: ${finalUrl}`);
|
|
456
|
+
console.log(`\u{1F4C1} Output directory: ${outputDir}
|
|
457
|
+
`);
|
|
458
|
+
try {
|
|
459
|
+
const { default: openAPI } = await import('@bagelink/sdk');
|
|
460
|
+
const { types, code } = await openAPI(finalUrl, "/api");
|
|
461
|
+
const outputPath = node_path.resolve(root, outputDir);
|
|
462
|
+
if (!node_fs.existsSync(outputPath)) {
|
|
463
|
+
node_fs.mkdirSync(outputPath, { recursive: true });
|
|
464
|
+
}
|
|
465
|
+
const typesPath = node_path.resolve(outputPath, "types.d.ts");
|
|
466
|
+
node_fs.writeFileSync(typesPath, types);
|
|
467
|
+
console.log("\u2705 Generated types.d.ts");
|
|
468
|
+
const apiPath = node_path.resolve(outputPath, "api.ts");
|
|
469
|
+
node_fs.writeFileSync(apiPath, code);
|
|
470
|
+
console.log("\u2705 Generated api.ts");
|
|
471
|
+
const indexPath = node_path.resolve(outputPath, "index.ts");
|
|
472
|
+
node_fs.writeFileSync(
|
|
473
|
+
indexPath,
|
|
474
|
+
"export * from './api'\nexport * from './types.d'\n"
|
|
475
|
+
);
|
|
476
|
+
console.log("\u2705 Generated index.ts");
|
|
477
|
+
if (splitFiles) {
|
|
478
|
+
console.log("\n\u{1F500} Splitting into organized files...");
|
|
479
|
+
try {
|
|
480
|
+
const { splitClientCode } = await import('@bagelink/sdk/bin/splitClientGen');
|
|
481
|
+
await splitClientCode({
|
|
482
|
+
bagelinkDir: outputPath,
|
|
483
|
+
useDirectories: true
|
|
484
|
+
});
|
|
485
|
+
const fs = await import('node:fs');
|
|
486
|
+
fs.rmSync(apiPath, { force: true });
|
|
487
|
+
fs.rmSync(typesPath, { force: true });
|
|
488
|
+
fs.rmSync(indexPath, { force: true });
|
|
489
|
+
console.log("\u2705 Files organized into directories");
|
|
490
|
+
} catch (error) {
|
|
491
|
+
console.warn("\u26A0\uFE0F Could not split files, keeping monolithic structure");
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
console.log("\n\u2705 SDK generated successfully!");
|
|
495
|
+
console.log(`
|
|
496
|
+
Import it in your code:`);
|
|
497
|
+
console.log(` import { api } from '${outputDir.replace("./src/", "./")}'`);
|
|
498
|
+
console.log("");
|
|
499
|
+
} catch (error) {
|
|
500
|
+
console.error("\n\u274C Failed to generate SDK:");
|
|
501
|
+
if (error instanceof Error) {
|
|
502
|
+
console.error(error.message);
|
|
503
|
+
} else {
|
|
504
|
+
console.error(error);
|
|
505
|
+
}
|
|
506
|
+
console.log("\nMake sure:");
|
|
507
|
+
console.log(" 1. @bagelink/sdk is installed: bun add -D @bagelink/sdk");
|
|
508
|
+
console.log(" 2. OpenAPI URL is accessible");
|
|
509
|
+
console.log(" 3. API server is running (if using localhost)");
|
|
510
|
+
process__default.exit(1);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
async function generateSDKForWorkspace(root = process__default.cwd()) {
|
|
514
|
+
console.log("\n\u{1F3E2} Generating SDK for workspace projects...\n");
|
|
515
|
+
const fs = await import('node:fs');
|
|
516
|
+
const items = fs.readdirSync(root, { withFileTypes: true });
|
|
517
|
+
const projects = items.filter(
|
|
518
|
+
(item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".")
|
|
519
|
+
).map((item) => item.name);
|
|
520
|
+
if (projects.length === 0) {
|
|
521
|
+
console.log("No projects found in workspace");
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
const response = await prompts__default({
|
|
525
|
+
type: "multiselect",
|
|
526
|
+
name: "selectedProjects",
|
|
527
|
+
message: "Select projects to generate SDK for:",
|
|
528
|
+
choices: projects.map((p) => ({ title: p, value: p, selected: true }))
|
|
529
|
+
});
|
|
530
|
+
if (!response || !response.selectedProjects || response.selectedProjects.length === 0) {
|
|
531
|
+
console.log("\n\u274C No projects selected.\n");
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
for (const project of response.selectedProjects) {
|
|
535
|
+
console.log(`
|
|
536
|
+
\u{1F4E6} Generating SDK for: ${project}`);
|
|
537
|
+
const projectPath = node_path.resolve(root, project);
|
|
538
|
+
try {
|
|
539
|
+
await generateSDK(projectPath);
|
|
540
|
+
} catch (error) {
|
|
541
|
+
console.error(`Failed to generate SDK for ${project}:`, error);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
console.log("\n\u2705 All SDKs generated!");
|
|
545
|
+
}
|
|
546
|
+
|
|
241
547
|
async function initWorkspace(root = process__default.cwd()) {
|
|
242
548
|
console.log("\n\u{1F680} Creating Bagel workspace...\n");
|
|
243
549
|
const response = await prompts__default([
|
|
@@ -564,182 +870,66 @@ function listProjects(root = process__default.cwd()) {
|
|
|
564
870
|
}
|
|
565
871
|
}
|
|
566
872
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
{
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
{ title: "Prettier", value: "prettier", selected: true },
|
|
577
|
-
{ title: "EditorConfig", value: "editorconfig", selected: true },
|
|
578
|
-
{ title: "Git Hooks", value: "githooks", selected: false }
|
|
579
|
-
]
|
|
580
|
-
},
|
|
581
|
-
{
|
|
582
|
-
type: "confirm",
|
|
583
|
-
name: "installDeps",
|
|
584
|
-
message: "Install dependencies?",
|
|
585
|
-
initial: true
|
|
873
|
+
function isWorkspace(root = process.cwd()) {
|
|
874
|
+
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
875
|
+
if (node_fs.existsSync(packageJsonPath)) {
|
|
876
|
+
try {
|
|
877
|
+
const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
|
|
878
|
+
if (packageJson.workspaces) {
|
|
879
|
+
return true;
|
|
880
|
+
}
|
|
881
|
+
} catch {
|
|
586
882
|
}
|
|
587
|
-
]);
|
|
588
|
-
if (!response || !response.configs) {
|
|
589
|
-
console.log("\n\u274C Setup cancelled.\n");
|
|
590
|
-
process__default.exit(1);
|
|
591
|
-
}
|
|
592
|
-
const { configs, installDeps } = response;
|
|
593
|
-
if (configs.includes("eslint")) {
|
|
594
|
-
createEslintConfig(root, isWorkspace);
|
|
595
|
-
}
|
|
596
|
-
if (configs.includes("prettier")) {
|
|
597
|
-
createPrettierConfig(root);
|
|
598
|
-
}
|
|
599
|
-
if (configs.includes("editorconfig")) {
|
|
600
|
-
createEditorConfig(root);
|
|
601
|
-
}
|
|
602
|
-
if (configs.includes("githooks")) {
|
|
603
|
-
createGitHooks(root);
|
|
604
|
-
}
|
|
605
|
-
updatePackageJsonLint(root, configs);
|
|
606
|
-
if (installDeps) {
|
|
607
|
-
console.log("\n\u{1F4E6} Installing dependencies...");
|
|
608
|
-
console.log("Run: bun add -D @bagelink/lint-config eslint prettier typescript");
|
|
609
883
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
const configPath = node_path.resolve(root, "eslint.config.js");
|
|
619
|
-
const config = isWorkspace ? `import { defineConfig } from '@bagelink/lint-config/eslint'
|
|
620
|
-
|
|
621
|
-
export default defineConfig({
|
|
622
|
-
// Workspace-level ESLint config
|
|
623
|
-
ignores: ['**/dist/**', '**/node_modules/**', '**/.bun-cache/**'],
|
|
624
|
-
})
|
|
625
|
-
` : `import vue3Config from '@bagelink/lint-config/eslint/vue3'
|
|
626
|
-
|
|
627
|
-
export default vue3Config
|
|
628
|
-
`;
|
|
629
|
-
node_fs.writeFileSync(configPath, config);
|
|
630
|
-
console.log("\u2705 Created eslint.config.js");
|
|
631
|
-
}
|
|
632
|
-
function createPrettierConfig(root) {
|
|
633
|
-
const configPath = node_path.resolve(root, ".prettierrc");
|
|
634
|
-
const config = {
|
|
635
|
-
semi: false,
|
|
636
|
-
singleQuote: true,
|
|
637
|
-
tabWidth: 2,
|
|
638
|
-
useTabs: true,
|
|
639
|
-
trailingComma: "all",
|
|
640
|
-
printWidth: 100,
|
|
641
|
-
arrowParens: "avoid"
|
|
642
|
-
};
|
|
643
|
-
node_fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
644
|
-
`);
|
|
645
|
-
console.log("\u2705 Created .prettierrc");
|
|
646
|
-
const ignorePath = node_path.resolve(root, ".prettierignore");
|
|
647
|
-
const ignore = `dist
|
|
648
|
-
node_modules
|
|
649
|
-
.bun-cache
|
|
650
|
-
*.min.js
|
|
651
|
-
*.min.css
|
|
652
|
-
`;
|
|
653
|
-
node_fs.writeFileSync(ignorePath, ignore);
|
|
654
|
-
console.log("\u2705 Created .prettierignore");
|
|
655
|
-
}
|
|
656
|
-
function createEditorConfig(root) {
|
|
657
|
-
const configPath = node_path.resolve(root, ".editorconfig");
|
|
658
|
-
const config = `root = true
|
|
659
|
-
|
|
660
|
-
[*]
|
|
661
|
-
charset = utf-8
|
|
662
|
-
indent_style = tab
|
|
663
|
-
indent_size = 2
|
|
664
|
-
end_of_line = lf
|
|
665
|
-
insert_final_newline = true
|
|
666
|
-
trim_trailing_whitespace = true
|
|
667
|
-
|
|
668
|
-
[*.md]
|
|
669
|
-
trim_trailing_whitespace = false
|
|
670
|
-
|
|
671
|
-
[*.{json,yml,yaml}]
|
|
672
|
-
indent_style = space
|
|
673
|
-
indent_size = 2
|
|
674
|
-
`;
|
|
675
|
-
node_fs.writeFileSync(configPath, config);
|
|
676
|
-
console.log("\u2705 Created .editorconfig");
|
|
677
|
-
}
|
|
678
|
-
function createGitHooks(root) {
|
|
679
|
-
const packageJsonPath = node_path.resolve(root, "package.json");
|
|
680
|
-
if (!node_fs.existsSync(packageJsonPath)) {
|
|
681
|
-
console.warn("\u26A0\uFE0F No package.json found, skipping git hooks");
|
|
682
|
-
return;
|
|
884
|
+
try {
|
|
885
|
+
const items = node_fs.readdirSync(root, { withFileTypes: true });
|
|
886
|
+
const projectDirs = items.filter(
|
|
887
|
+
(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"))
|
|
888
|
+
);
|
|
889
|
+
return projectDirs.length >= 2;
|
|
890
|
+
} catch {
|
|
891
|
+
return false;
|
|
683
892
|
}
|
|
684
|
-
const lintStagedConfig = {
|
|
685
|
-
"*.{js,jsx,ts,tsx,vue}": ["eslint --fix"],
|
|
686
|
-
"*.{json,md,yml,yaml}": ["prettier --write"]
|
|
687
|
-
};
|
|
688
|
-
node_fs.writeFileSync(
|
|
689
|
-
node_path.resolve(root, ".lintstagedrc"),
|
|
690
|
-
`${JSON.stringify(lintStagedConfig, null, 2)}
|
|
691
|
-
`
|
|
692
|
-
);
|
|
693
|
-
console.log("\u2705 Created .lintstagedrc");
|
|
694
|
-
console.log("\u2139\uFE0F Add simple-git-hooks and lint-staged to devDependencies");
|
|
695
|
-
console.log(" Then run: npx simple-git-hooks");
|
|
696
893
|
}
|
|
697
|
-
function
|
|
698
|
-
const
|
|
699
|
-
if (!
|
|
700
|
-
|
|
701
|
-
|
|
894
|
+
function getWorkspaceInfo(root = process.cwd()) {
|
|
895
|
+
const workspace = isWorkspace(root);
|
|
896
|
+
if (!workspace) {
|
|
897
|
+
return {
|
|
898
|
+
isWorkspace: false,
|
|
899
|
+
projects: [],
|
|
900
|
+
hasShared: false
|
|
901
|
+
};
|
|
702
902
|
}
|
|
703
903
|
try {
|
|
704
|
-
const
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
packageJson.scripts.format = "prettier --write .";
|
|
721
|
-
}
|
|
722
|
-
if (!packageJson.scripts["format:check"]) {
|
|
723
|
-
packageJson.scripts["format:check"] = "prettier --check .";
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
node_fs.writeFileSync(
|
|
727
|
-
packageJsonPath,
|
|
728
|
-
`${JSON.stringify(packageJson, null, 2)}
|
|
729
|
-
`
|
|
730
|
-
);
|
|
731
|
-
console.log("\u2705 Updated package.json with lint scripts");
|
|
732
|
-
} catch (error) {
|
|
733
|
-
console.error("\u274C Failed to update package.json:", error);
|
|
904
|
+
const items = node_fs.readdirSync(root, { withFileTypes: true });
|
|
905
|
+
const projects = items.filter(
|
|
906
|
+
(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"))
|
|
907
|
+
).map((item) => item.name);
|
|
908
|
+
const hasShared = node_fs.existsSync(node_path.resolve(root, "shared"));
|
|
909
|
+
return {
|
|
910
|
+
isWorkspace: true,
|
|
911
|
+
projects,
|
|
912
|
+
hasShared
|
|
913
|
+
};
|
|
914
|
+
} catch {
|
|
915
|
+
return {
|
|
916
|
+
isWorkspace: false,
|
|
917
|
+
projects: [],
|
|
918
|
+
hasShared: false
|
|
919
|
+
};
|
|
734
920
|
}
|
|
735
921
|
}
|
|
736
922
|
|
|
737
923
|
exports.addProject = addProject;
|
|
738
924
|
exports.generateNetlifyConfig = generateNetlifyConfig;
|
|
739
925
|
exports.generateNetlifyRedirect = generateNetlifyRedirect;
|
|
926
|
+
exports.generateSDK = generateSDK;
|
|
927
|
+
exports.generateSDKForWorkspace = generateSDKForWorkspace;
|
|
740
928
|
exports.generateWorkspaceConfig = generateWorkspaceConfig;
|
|
741
929
|
exports.generateWorkspaceConfigSync = generateWorkspaceConfigSync;
|
|
930
|
+
exports.getWorkspaceInfo = getWorkspaceInfo;
|
|
742
931
|
exports.initWorkspace = initWorkspace;
|
|
932
|
+
exports.isWorkspace = isWorkspace;
|
|
743
933
|
exports.listProjects = listProjects;
|
|
744
934
|
exports.setBuildEnvVars = setBuildEnvVars;
|
|
745
935
|
exports.setupLint = setupLint;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bagelink/workspace",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.10.1",
|
|
5
5
|
"description": "Monorepo workspace tooling for Bagel projects with proxy and config management",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Bagel Studio",
|
|
@@ -53,11 +53,16 @@
|
|
|
53
53
|
"prompts": "^2.4.2"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
+
"@bagelink/lint-config": ">=1.0.0",
|
|
57
|
+
"@bagelink/sdk": ">=1.0.0",
|
|
56
58
|
"vite": ">=5.0.0"
|
|
57
59
|
},
|
|
58
60
|
"peerDependenciesMeta": {
|
|
59
61
|
"@bagelink/lint-config": {
|
|
60
62
|
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"@bagelink/sdk": {
|
|
65
|
+
"optional": true
|
|
61
66
|
}
|
|
62
67
|
},
|
|
63
68
|
"devDependencies": {
|
package/src/detect.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { resolve } from 'node:path'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Detect if current directory is a workspace root
|
|
6
|
+
*/
|
|
7
|
+
export function isWorkspace(root: string = process.cwd()): boolean {
|
|
8
|
+
// Check if package.json has workspaces field
|
|
9
|
+
const packageJsonPath = resolve(root, 'package.json')
|
|
10
|
+
if (existsSync(packageJsonPath)) {
|
|
11
|
+
try {
|
|
12
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))
|
|
13
|
+
if (packageJson.workspaces) {
|
|
14
|
+
return true
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// Ignore parse errors
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Check if there are multiple project directories
|
|
23
|
+
// (directories with their own package.json, excluding shared, node_modules, etc.)
|
|
24
|
+
try {
|
|
25
|
+
const items = readdirSync(root, { withFileTypes: true })
|
|
26
|
+
const projectDirs = items.filter(
|
|
27
|
+
item =>
|
|
28
|
+
item.isDirectory()
|
|
29
|
+
&& item.name !== 'node_modules'
|
|
30
|
+
&& item.name !== 'shared'
|
|
31
|
+
&& item.name !== '.git'
|
|
32
|
+
&& !item.name.startsWith('.')
|
|
33
|
+
&& existsSync(resolve(root, item.name, 'package.json')),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
// If we have 2+ project directories, it's likely a workspace
|
|
37
|
+
return projectDirs.length >= 2
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get workspace info
|
|
46
|
+
*/
|
|
47
|
+
export function getWorkspaceInfo(root: string = process.cwd()): {
|
|
48
|
+
isWorkspace: boolean
|
|
49
|
+
projects: string[]
|
|
50
|
+
hasShared: boolean
|
|
51
|
+
} {
|
|
52
|
+
const workspace = isWorkspace(root)
|
|
53
|
+
|
|
54
|
+
if (!workspace) {
|
|
55
|
+
return {
|
|
56
|
+
isWorkspace: false,
|
|
57
|
+
projects: [],
|
|
58
|
+
hasShared: false,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const items = readdirSync(root, { withFileTypes: true })
|
|
64
|
+
const projects = items
|
|
65
|
+
.filter(
|
|
66
|
+
item =>
|
|
67
|
+
item.isDirectory()
|
|
68
|
+
&& item.name !== 'node_modules'
|
|
69
|
+
&& item.name !== 'shared'
|
|
70
|
+
&& item.name !== '.git'
|
|
71
|
+
&& !item.name.startsWith('.')
|
|
72
|
+
&& existsSync(resolve(root, item.name, 'package.json')),
|
|
73
|
+
)
|
|
74
|
+
.map(item => item.name)
|
|
75
|
+
|
|
76
|
+
const hasShared = existsSync(resolve(root, 'shared'))
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
isWorkspace: true,
|
|
80
|
+
projects,
|
|
81
|
+
hasShared,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return {
|
|
86
|
+
isWorkspace: false,
|
|
87
|
+
projects: [],
|
|
88
|
+
hasShared: false,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -34,8 +34,10 @@ export {
|
|
|
34
34
|
writeNetlifyConfig,
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export { addProject, initWorkspace, listProjects } from './workspace'
|
|
38
37
|
export { setupLint } from './lint'
|
|
38
|
+
export { generateSDK, generateSDKForWorkspace } from './sdk'
|
|
39
|
+
export { addProject, initWorkspace, listProjects } from './workspace'
|
|
40
|
+
export { getWorkspaceInfo, isWorkspace } from './detect'
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
* Define workspace configuration
|