@vobs/cli 0.3.0 → 1.2.0

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.
Files changed (143) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +116 -0
  3. package/bin/vobs.js +12 -0
  4. package/dist/banner.cjs +37 -0
  5. package/dist/banner.cjs.map +1 -0
  6. package/dist/banner.d.cts +18 -0
  7. package/dist/banner.d.ts +18 -0
  8. package/dist/banner.js +33 -0
  9. package/dist/banner.js.map +1 -0
  10. package/dist/cli.cjs +416 -0
  11. package/dist/cli.cjs.map +1 -0
  12. package/dist/cli.d.cts +5 -0
  13. package/dist/cli.d.ts +5 -0
  14. package/dist/cli.js +389 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/commands/add.cjs +113 -0
  17. package/dist/commands/add.cjs.map +1 -0
  18. package/dist/commands/add.d.cts +5 -0
  19. package/dist/commands/add.d.ts +5 -0
  20. package/dist/commands/add.js +88 -0
  21. package/dist/commands/add.js.map +1 -0
  22. package/dist/commands/build.cjs +55 -0
  23. package/dist/commands/build.cjs.map +1 -0
  24. package/dist/commands/build.d.cts +5 -0
  25. package/dist/commands/build.d.ts +5 -0
  26. package/dist/commands/build.js +49 -0
  27. package/dist/commands/build.js.map +1 -0
  28. package/dist/commands/dev.cjs +57 -0
  29. package/dist/commands/dev.cjs.map +1 -0
  30. package/dist/commands/dev.d.cts +5 -0
  31. package/dist/commands/dev.d.ts +5 -0
  32. package/dist/commands/dev.js +51 -0
  33. package/dist/commands/dev.js.map +1 -0
  34. package/dist/commands/generate.cjs +153 -0
  35. package/dist/commands/generate.cjs.map +1 -0
  36. package/dist/commands/generate.d.cts +5 -0
  37. package/dist/commands/generate.d.ts +5 -0
  38. package/dist/commands/generate.js +126 -0
  39. package/dist/commands/generate.js.map +1 -0
  40. package/dist/commands/index.cjs +331 -0
  41. package/dist/commands/index.cjs.map +1 -0
  42. package/dist/commands/index.d.cts +6 -0
  43. package/dist/commands/index.d.ts +6 -0
  44. package/dist/commands/index.js +300 -0
  45. package/dist/commands/index.js.map +1 -0
  46. package/dist/commands/init.cjs +187 -0
  47. package/dist/commands/init.cjs.map +1 -0
  48. package/dist/commands/init.d.cts +5 -0
  49. package/dist/commands/init.d.ts +5 -0
  50. package/dist/commands/init.js +160 -0
  51. package/dist/commands/init.js.map +1 -0
  52. package/dist/index.cjs +561 -0
  53. package/dist/index.cjs.map +1 -0
  54. package/dist/index.d.cts +14 -0
  55. package/dist/index.d.ts +14 -18
  56. package/dist/index.js +489 -486
  57. package/dist/index.js.map +1 -0
  58. package/dist/repl.cjs +436 -0
  59. package/dist/repl.cjs.map +1 -0
  60. package/dist/repl.d.cts +8 -0
  61. package/dist/repl.d.ts +8 -0
  62. package/dist/repl.js +409 -0
  63. package/dist/repl.js.map +1 -0
  64. package/dist/start.cjs +543 -0
  65. package/dist/start.cjs.map +1 -0
  66. package/dist/start.d.cts +4 -0
  67. package/dist/start.d.ts +4 -0
  68. package/dist/start.js +516 -0
  69. package/dist/start.js.map +1 -0
  70. package/dist/templates/basic/.gitignore.hbs +4 -0
  71. package/dist/templates/basic/index.html.hbs +12 -0
  72. package/dist/templates/basic/package.json.hbs +25 -0
  73. package/dist/templates/basic/src/App.tsx.hbs +8 -0
  74. package/dist/templates/basic/src/app.css.hbs +32 -0
  75. package/dist/templates/basic/src/main.ts.hbs +20 -0
  76. package/dist/templates/basic/tsconfig.json.hbs +19 -0
  77. package/dist/templates/basic/vite.config.ts.hbs +10 -0
  78. package/dist/templates/component.hbs +7 -0
  79. package/dist/templates/page.hbs +7 -0
  80. package/dist/types.cjs +4 -0
  81. package/dist/types.cjs.map +1 -0
  82. package/dist/types.d.cts +71 -0
  83. package/dist/types.d.ts +71 -0
  84. package/dist/types.js +3 -0
  85. package/dist/types.js.map +1 -0
  86. package/dist/utils/file.cjs +79 -0
  87. package/dist/utils/file.cjs.map +1 -0
  88. package/dist/utils/file.d.cts +14 -0
  89. package/dist/utils/file.d.ts +14 -0
  90. package/dist/utils/file.js +67 -0
  91. package/dist/utils/file.js.map +1 -0
  92. package/dist/utils/logger.cjs +45 -0
  93. package/dist/utils/logger.cjs.map +1 -0
  94. package/dist/utils/logger.d.cts +14 -0
  95. package/dist/utils/logger.d.ts +14 -0
  96. package/dist/utils/logger.js +34 -0
  97. package/dist/utils/logger.js.map +1 -0
  98. package/dist/utils/pm.cjs +38 -0
  99. package/dist/utils/pm.cjs.map +1 -0
  100. package/dist/utils/pm.d.cts +9 -0
  101. package/dist/utils/pm.d.ts +9 -0
  102. package/dist/utils/pm.js +34 -0
  103. package/dist/utils/pm.js.map +1 -0
  104. package/package.json +30 -40
  105. package/src/banner.ts +41 -0
  106. package/src/cli.ts +108 -0
  107. package/src/commands/add.ts +37 -0
  108. package/src/commands/build.ts +17 -0
  109. package/src/commands/dev.ts +19 -0
  110. package/src/commands/generate.ts +87 -0
  111. package/src/commands/index.ts +5 -0
  112. package/src/commands/init.ts +84 -0
  113. package/src/index.ts +13 -0
  114. package/src/repl.ts +140 -0
  115. package/src/start.ts +20 -0
  116. package/src/templates/basic/.gitignore.hbs +4 -0
  117. package/src/templates/basic/index.html.hbs +12 -0
  118. package/src/templates/basic/package.json.hbs +25 -0
  119. package/src/templates/basic/src/App.tsx.hbs +8 -0
  120. package/src/templates/basic/src/app.css.hbs +32 -0
  121. package/src/templates/basic/src/main.ts.hbs +20 -0
  122. package/src/templates/basic/tsconfig.json.hbs +19 -0
  123. package/src/templates/basic/vite.config.ts.hbs +10 -0
  124. package/src/templates/component.hbs +7 -0
  125. package/src/templates/page.hbs +7 -0
  126. package/src/types.ts +78 -0
  127. package/src/utils/file.ts +77 -0
  128. package/src/utils/logger.ts +27 -0
  129. package/src/utils/pm.ts +42 -0
  130. package/dist/ai-server.d.ts +0 -11
  131. package/dist/ai-server.js +0 -212
  132. package/dist/context.d.ts +0 -12
  133. package/dist/context.js +0 -301
  134. package/dist/diagnose.d.ts +0 -12
  135. package/dist/diagnose.js +0 -122
  136. package/dist/enterprise-template.d.ts +0 -83
  137. package/dist/enterprise-template.js +0 -638
  138. package/dist/inspect.d.ts +0 -11
  139. package/dist/inspect.js +0 -576
  140. package/dist/logo/cli-logo.d.ts +0 -5
  141. package/dist/logo/cli-logo.js +0 -16
  142. package/dist/scaffold.d.ts +0 -23
  143. package/dist/scaffold.js +0 -448
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 vobsjs
3
+ Copyright (c) 2026 vobs contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # @vobs/cli
2
+
3
+ Command-line interface for the vobs framework: project scaffolding, code generation, and dev/build tooling.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g @vobs/cli
9
+ # or
10
+ npx @vobs/cli
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```bash
16
+ # Create a new project
17
+ vobs init my-app
18
+
19
+ # Start the dev server
20
+ cd my-app
21
+ vobs dev
22
+
23
+ # Build for production
24
+ vobs build
25
+
26
+ # Generate a component
27
+ vobs g component Button
28
+
29
+ # Add a package
30
+ vobs add @vobs/ui
31
+ ```
32
+
33
+ ## Commands
34
+
35
+ | Command | Usage | Description |
36
+ | --- | --- | --- |
37
+ | `init` / `create` | `vobs init my-app` | Create a new vobs project with interactive prompts (project name, package manager, TypeScript, git). |
38
+ | `dev` | `vobs dev` | Start the Vite dev server. Accepts `--port`, `--open`, `--config`. |
39
+ | `build` | `vobs build` | Build for production via Vite. Accepts `--outDir`, `--mode`, `--config`. |
40
+ | `generate` / `g` | `vobs g component Button` | Generate a component or page from a Handlebars template. Accepts `--type`, `--dir`. |
41
+ | `add` | `vobs add @vobs/notification` | Install a package and save to dependencies. Accepts `-D` / `--dev`. |
42
+
43
+ ## Options
44
+
45
+ | Option | Description |
46
+ | --- | --- |
47
+ | `-h, --help` | Show help output |
48
+ | `-V, --version` | Show version number |
49
+
50
+ ### init options
51
+
52
+ | Option | Default | Description |
53
+ | --- | --- | --- |
54
+ | `--dir <dir>` | current directory | Target directory for the new project |
55
+ | `--pm <pm>` | detected | Package manager: `pnpm`, `npm`, or `yarn` |
56
+ | `--no-typescript` | TypeScript enabled | Skip TypeScript setup |
57
+ | `--no-git` | git init enabled | Skip git repository initialization |
58
+
59
+ ### dev options
60
+
61
+ | Option | Default | Description |
62
+ | --- | --- | --- |
63
+ | `--port <port>` | Vite default | Dev server port |
64
+ | `--open` | false | Open browser on start |
65
+ | `--config <path>` | `vite.config.ts` | Path to Vite config file |
66
+
67
+ ### build options
68
+
69
+ | Option | Default | Description |
70
+ | --- | --- | --- |
71
+ | `--outDir <dir>` | `dist` | Output directory |
72
+ | `--mode <mode>` | `production` | Build mode |
73
+ | `--config <path>` | `vite.config.ts` | Path to Vite config file |
74
+
75
+ ## Templates
76
+
77
+ The `init` command scaffolds a project from Handlebars templates:
78
+
79
+ ```
80
+ my-app/
81
+ ├── package.json # Project manifest with @vobs/* dependencies
82
+ ├── vite.config.ts # Vite config with vobsPlugin() and vobsTailwind()
83
+ ├── tsconfig.json # TypeScript config targeting ES2020
84
+ ├── index.html # Entry HTML with #app mount point
85
+ ├── .gitignore # Standard ignore rules
86
+ └── src/
87
+ ├── main.ts # Application entry with createVobs()
88
+ ├── App.tsx # Root component
89
+ └── app.css # Global styles
90
+ ```
91
+
92
+ ## Programmatic API
93
+
94
+ ```ts
95
+ import { createCLI } from '@vobs/cli'
96
+
97
+ // Parse and execute CLI commands programmatically
98
+ const cli = createCLI()
99
+ cli.parse(process.argv)
100
+ ```
101
+
102
+ ```ts
103
+ import { scaffoldProject } from '@vobs/cli'
104
+
105
+ // Scaffold a project without CLI interaction
106
+ await scaffoldProject('/path/to/target', {
107
+ name: 'my-app',
108
+ packageName: 'my-app',
109
+ typescript: true,
110
+ vobsVersion: '1.0.0'
111
+ })
112
+ ```
113
+
114
+ ## Types
115
+
116
+ InitOptions, GenerateOptions, DevOptions, BuildOptions, AddOptions, TemplateContext, ComponentTemplateContext, PageTemplateContext, CLIOptions, LoggerLevel, PackageManager
package/bin/vobs.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Register the TypeScript loader synchronously BEFORE importing any .ts
4
+ // module. tsx 4.23's programmatic API (tsx/esm/api) uses Node's registerHooks
5
+ // (Node >=22.13) and does not rely on the deprecated --loader worker path.
6
+ import { register } from 'tsx/esm/api'
7
+
8
+ register()
9
+
10
+ const { start } = await import('../src/start.ts')
11
+
12
+ await start(process.argv.slice(2))
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
5
+
6
+ // packages/cli/src/banner.ts
7
+ var BANNER_LINE1 = "\u{1D5E9}\u{1D5E2}\u{1D5D5}\u{1D5E6} \u{1D5D6}\u{1D5DF}\u{1D5DC} \u{1D603}\u{1D7ED}.\u{1D7EC}";
8
+ var BANNER_TAGLINE = "Signals First \xB7 Zero Re-renders \xB7 Ultra Lightweight";
9
+ var INDENT = " ";
10
+ var DIM = "\x1B[2m";
11
+ var RESET = "\x1B[0m";
12
+ function showLogo() {
13
+ console.log();
14
+ console.log();
15
+ console.log(`${INDENT}${BANNER_LINE1}`);
16
+ console.log();
17
+ console.log(`${INDENT}${DIM}${BANNER_TAGLINE}${RESET}`);
18
+ console.log();
19
+ console.log();
20
+ }
21
+ __name(showLogo, "showLogo");
22
+ function showBanner() {
23
+ console.log(`${INDENT}${BANNER_LINE1}`);
24
+ }
25
+ __name(showBanner, "showBanner");
26
+ function showDevBanner() {
27
+ console.log();
28
+ console.log(`${INDENT}${BANNER_LINE1}`);
29
+ console.log();
30
+ }
31
+ __name(showDevBanner, "showDevBanner");
32
+
33
+ exports.showBanner = showBanner;
34
+ exports.showDevBanner = showDevBanner;
35
+ exports.showLogo = showLogo;
36
+ //# sourceMappingURL=banner.cjs.map
37
+ //# sourceMappingURL=banner.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/banner.ts"],"names":[],"mappings":";;;;;;AAWA,IAAM,YAAA,GAAe,+FAAA;AACrB,IAAM,cAAA,GAAiB,2DAAA;AAGvB,IAAM,MAAA,GAAS,IAAA;AACf,IAAM,GAAA,GAAM,SAAA;AACZ,IAAM,KAAA,GAAQ,SAAA;AAGP,SAAS,QAAA,GAAiB;AAC/B,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA,EAAG,YAAY,CAAA,CAAE,CAAA;AACtC,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,MAAM,CAAA,EAAG,GAAG,CAAA,EAAG,cAAc,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA;AACtD,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,EAAI;AACd;AARgB,MAAA,CAAA,QAAA,EAAA,UAAA,CAAA;AAWT,SAAS,UAAA,GAAmB;AACjC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA,EAAG,YAAY,CAAA,CAAE,CAAA;AACxC;AAFgB,MAAA,CAAA,UAAA,EAAA,YAAA,CAAA;AAKT,SAAS,aAAA,GAAsB;AACpC,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA,EAAG,YAAY,CAAA,CAAE,CAAA;AACtC,EAAA,OAAA,CAAQ,GAAA,EAAI;AACd;AAJgB,MAAA,CAAA,aAAA,EAAA,eAAA,CAAA","file":"banner.cjs","sourcesContent":["/**\n * VOBS CLI Banner — Mathematical Bold Sans-Serif\n * 𝗩𝗢𝗕𝗦 𝗖𝗟𝗜 𝘃𝟭.𝟬\n * Signals First · Zero Re-renders · Ultra Lightweight\n *\n * The banner is left-aligned with a fixed indent rather than horizontally\n * centered. Centering depends on the terminal column width and per-glyph\n * render width, neither of which is reliably knowable, so it drifts as the\n * window resizes. Fixed indent is stable across any terminal size.\n */\n\nconst BANNER_LINE1 = '𝗩𝗢𝗕𝗦 𝗖𝗟𝗜 𝘃𝟭.𝟬'\nconst BANNER_TAGLINE = 'Signals First · Zero Re-renders · Ultra Lightweight'\n\n/** Fixed left indent applied to every banner line (2 spaces). */\nconst INDENT = ' '\nconst DIM = '\\x1b[2m'\nconst RESET = '\\x1b[0m'\n\n/** Show full banner (used for logo command, --help) */\nexport function showLogo(): void {\n console.log()\n console.log()\n console.log(`${INDENT}${BANNER_LINE1}`)\n console.log()\n console.log(`${INDENT}${DIM}${BANNER_TAGLINE}${RESET}`)\n console.log()\n console.log()\n}\n\n/** Show single-line version banner (used for --version) */\nexport function showBanner(): void {\n console.log(`${INDENT}${BANNER_LINE1}`)\n}\n\n/** Show the dev server start banner */\nexport function showDevBanner(): void {\n console.log()\n console.log(`${INDENT}${BANNER_LINE1}`)\n console.log()\n}"]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * VOBS CLI Banner — Mathematical Bold Sans-Serif
3
+ * 𝗩𝗢𝗕𝗦 𝗖𝗟𝗜 𝘃𝟭.𝟬
4
+ * Signals First · Zero Re-renders · Ultra Lightweight
5
+ *
6
+ * The banner is left-aligned with a fixed indent rather than horizontally
7
+ * centered. Centering depends on the terminal column width and per-glyph
8
+ * render width, neither of which is reliably knowable, so it drifts as the
9
+ * window resizes. Fixed indent is stable across any terminal size.
10
+ */
11
+ /** Show full banner (used for logo command, --help) */
12
+ declare function showLogo(): void;
13
+ /** Show single-line version banner (used for --version) */
14
+ declare function showBanner(): void;
15
+ /** Show the dev server start banner */
16
+ declare function showDevBanner(): void;
17
+
18
+ export { showBanner, showDevBanner, showLogo };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * VOBS CLI Banner — Mathematical Bold Sans-Serif
3
+ * 𝗩𝗢𝗕𝗦 𝗖𝗟𝗜 𝘃𝟭.𝟬
4
+ * Signals First · Zero Re-renders · Ultra Lightweight
5
+ *
6
+ * The banner is left-aligned with a fixed indent rather than horizontally
7
+ * centered. Centering depends on the terminal column width and per-glyph
8
+ * render width, neither of which is reliably knowable, so it drifts as the
9
+ * window resizes. Fixed indent is stable across any terminal size.
10
+ */
11
+ /** Show full banner (used for logo command, --help) */
12
+ declare function showLogo(): void;
13
+ /** Show single-line version banner (used for --version) */
14
+ declare function showBanner(): void;
15
+ /** Show the dev server start banner */
16
+ declare function showDevBanner(): void;
17
+
18
+ export { showBanner, showDevBanner, showLogo };
package/dist/banner.js ADDED
@@ -0,0 +1,33 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // packages/cli/src/banner.ts
5
+ var BANNER_LINE1 = "\u{1D5E9}\u{1D5E2}\u{1D5D5}\u{1D5E6} \u{1D5D6}\u{1D5DF}\u{1D5DC} \u{1D603}\u{1D7ED}.\u{1D7EC}";
6
+ var BANNER_TAGLINE = "Signals First \xB7 Zero Re-renders \xB7 Ultra Lightweight";
7
+ var INDENT = " ";
8
+ var DIM = "\x1B[2m";
9
+ var RESET = "\x1B[0m";
10
+ function showLogo() {
11
+ console.log();
12
+ console.log();
13
+ console.log(`${INDENT}${BANNER_LINE1}`);
14
+ console.log();
15
+ console.log(`${INDENT}${DIM}${BANNER_TAGLINE}${RESET}`);
16
+ console.log();
17
+ console.log();
18
+ }
19
+ __name(showLogo, "showLogo");
20
+ function showBanner() {
21
+ console.log(`${INDENT}${BANNER_LINE1}`);
22
+ }
23
+ __name(showBanner, "showBanner");
24
+ function showDevBanner() {
25
+ console.log();
26
+ console.log(`${INDENT}${BANNER_LINE1}`);
27
+ console.log();
28
+ }
29
+ __name(showDevBanner, "showDevBanner");
30
+
31
+ export { showBanner, showDevBanner, showLogo };
32
+ //# sourceMappingURL=banner.js.map
33
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/banner.ts"],"names":[],"mappings":";;;;AAWA,IAAM,YAAA,GAAe,+FAAA;AACrB,IAAM,cAAA,GAAiB,2DAAA;AAGvB,IAAM,MAAA,GAAS,IAAA;AACf,IAAM,GAAA,GAAM,SAAA;AACZ,IAAM,KAAA,GAAQ,SAAA;AAGP,SAAS,QAAA,GAAiB;AAC/B,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA,EAAG,YAAY,CAAA,CAAE,CAAA;AACtC,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,MAAM,CAAA,EAAG,GAAG,CAAA,EAAG,cAAc,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA;AACtD,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,EAAI;AACd;AARgB,MAAA,CAAA,QAAA,EAAA,UAAA,CAAA;AAWT,SAAS,UAAA,GAAmB;AACjC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA,EAAG,YAAY,CAAA,CAAE,CAAA;AACxC;AAFgB,MAAA,CAAA,UAAA,EAAA,YAAA,CAAA;AAKT,SAAS,aAAA,GAAsB;AACpC,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA,EAAG,YAAY,CAAA,CAAE,CAAA;AACtC,EAAA,OAAA,CAAQ,GAAA,EAAI;AACd;AAJgB,MAAA,CAAA,aAAA,EAAA,eAAA,CAAA","file":"banner.js","sourcesContent":["/**\n * VOBS CLI Banner — Mathematical Bold Sans-Serif\n * 𝗩𝗢𝗕𝗦 𝗖𝗟𝗜 𝘃𝟭.𝟬\n * Signals First · Zero Re-renders · Ultra Lightweight\n *\n * The banner is left-aligned with a fixed indent rather than horizontally\n * centered. Centering depends on the terminal column width and per-glyph\n * render width, neither of which is reliably knowable, so it drifts as the\n * window resizes. Fixed indent is stable across any terminal size.\n */\n\nconst BANNER_LINE1 = '𝗩𝗢𝗕𝗦 𝗖𝗟𝗜 𝘃𝟭.𝟬'\nconst BANNER_TAGLINE = 'Signals First · Zero Re-renders · Ultra Lightweight'\n\n/** Fixed left indent applied to every banner line (2 spaces). */\nconst INDENT = ' '\nconst DIM = '\\x1b[2m'\nconst RESET = '\\x1b[0m'\n\n/** Show full banner (used for logo command, --help) */\nexport function showLogo(): void {\n console.log()\n console.log()\n console.log(`${INDENT}${BANNER_LINE1}`)\n console.log()\n console.log(`${INDENT}${DIM}${BANNER_TAGLINE}${RESET}`)\n console.log()\n console.log()\n}\n\n/** Show single-line version banner (used for --version) */\nexport function showBanner(): void {\n console.log(`${INDENT}${BANNER_LINE1}`)\n}\n\n/** Show the dev server start banner */\nexport function showDevBanner(): void {\n console.log()\n console.log(`${INDENT}${BANNER_LINE1}`)\n console.log()\n}"]}
package/dist/cli.cjs ADDED
@@ -0,0 +1,416 @@
1
+ 'use strict';
2
+
3
+ var cac = require('cac');
4
+ var path = require('path');
5
+ var child_process = require('child_process');
6
+ var p = require('@clack/prompts');
7
+ var pc = require('picocolors');
8
+ var fs = require('fs');
9
+ var url = require('url');
10
+ var Handlebars = require('handlebars');
11
+ var vite = require('vite');
12
+
13
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
14
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
+
16
+ function _interopNamespace(e) {
17
+ if (e && e.__esModule) return e;
18
+ var n = Object.create(null);
19
+ if (e) {
20
+ Object.keys(e).forEach(function (k) {
21
+ if (k !== 'default') {
22
+ var d = Object.getOwnPropertyDescriptor(e, k);
23
+ Object.defineProperty(n, k, d.get ? d : {
24
+ enumerable: true,
25
+ get: function () { return e[k]; }
26
+ });
27
+ }
28
+ });
29
+ }
30
+ n.default = e;
31
+ return Object.freeze(n);
32
+ }
33
+
34
+ var p__namespace = /*#__PURE__*/_interopNamespace(p);
35
+ var pc__default = /*#__PURE__*/_interopDefault(pc);
36
+ var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
37
+
38
+ var __defProp = Object.defineProperty;
39
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
40
+ function timestamp() {
41
+ return pc__default.default.dim(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`);
42
+ }
43
+ __name(timestamp, "timestamp");
44
+ function info(msg) {
45
+ console.log(`${timestamp()} ${pc__default.default.cyan("\u2139")} ${msg}`);
46
+ }
47
+ __name(info, "info");
48
+ function success(msg) {
49
+ console.log(`${timestamp()} ${pc__default.default.green("\u2714")} ${msg}`);
50
+ }
51
+ __name(success, "success");
52
+ function warn(msg) {
53
+ console.log(`${timestamp()} ${pc__default.default.yellow("\u26A0")} ${msg}`);
54
+ }
55
+ __name(warn, "warn");
56
+ function error(msg) {
57
+ console.error(`${timestamp()} ${pc__default.default.red("\u2716")} ${msg}`);
58
+ }
59
+ __name(error, "error");
60
+ function step(msg) {
61
+ console.log(`
62
+ ${pc__default.default.bold(pc__default.default.cyan(msg))}`);
63
+ }
64
+ __name(step, "step");
65
+ var logger = { info, success, warn, error, step };
66
+ var __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href))));
67
+ var TEMPLATES_ROOT = path.resolve(__dirname$1, "..", "templates");
68
+ function getTemplatesDir() {
69
+ return TEMPLATES_ROOT;
70
+ }
71
+ __name(getTemplatesDir, "getTemplatesDir");
72
+ function renderTemplate(templatePath, context) {
73
+ const source = fs.readFileSync(templatePath, "utf-8");
74
+ const template = Handlebars__default.default.compile(source);
75
+ return template(context);
76
+ }
77
+ __name(renderTemplate, "renderTemplate");
78
+ function writeFile(dir, filename, content) {
79
+ const filePath = path.resolve(dir, filename);
80
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
81
+ fs.writeFileSync(filePath, content, "utf-8");
82
+ }
83
+ __name(writeFile, "writeFile");
84
+ function ensureDir(dir) {
85
+ if (!fs.existsSync(dir)) {
86
+ fs.mkdirSync(dir, { recursive: true });
87
+ }
88
+ }
89
+ __name(ensureDir, "ensureDir");
90
+ async function copyDirRecursive(srcDir, destDir, context) {
91
+ const { readdirSync } = await import('fs');
92
+ const { join } = await import('path');
93
+ const entries = readdirSync(srcDir, { withFileTypes: true });
94
+ for (const entry of entries) {
95
+ const srcPath = join(srcDir, entry.name);
96
+ const isHbs = entry.name.endsWith(".hbs");
97
+ const destName = isHbs ? entry.name.slice(0, -4) : entry.name;
98
+ const destPath = join(destDir, destName);
99
+ if (entry.isDirectory()) {
100
+ ensureDir(destPath);
101
+ await copyDirRecursive(srcPath, destPath, context);
102
+ } else if (isHbs) {
103
+ const content = renderTemplate(srcPath, context);
104
+ writeFile(destDir, destName, content);
105
+ } else {
106
+ const content = fs.readFileSync(srcPath, "utf-8");
107
+ writeFile(destDir, destName, content);
108
+ }
109
+ }
110
+ }
111
+ __name(copyDirRecursive, "copyDirRecursive");
112
+ async function scaffoldProject(targetDir, context) {
113
+ const templateDir = path.resolve(TEMPLATES_ROOT, "basic");
114
+ ensureDir(targetDir);
115
+ await copyDirRecursive(templateDir, targetDir, context);
116
+ }
117
+ __name(scaffoldProject, "scaffoldProject");
118
+ function detectPackageManager(targetDir) {
119
+ if (targetDir) {
120
+ if (fs.existsSync(path.resolve(targetDir, "pnpm-lock.yaml"))) return "pnpm";
121
+ if (fs.existsSync(path.resolve(targetDir, "yarn.lock"))) return "yarn";
122
+ if (fs.existsSync(path.resolve(targetDir, "package-lock.json"))) return "npm";
123
+ }
124
+ const userAgent = process.env.npm_config_user_agent || "";
125
+ if (userAgent.startsWith("pnpm")) return "pnpm";
126
+ if (userAgent.startsWith("yarn")) return "yarn";
127
+ if (userAgent.startsWith("npm")) return "npm";
128
+ return "pnpm";
129
+ }
130
+ __name(detectPackageManager, "detectPackageManager");
131
+ function installDependencies(targetDir, pm) {
132
+ const cmd = pm === "yarn" ? "yarn" : `${pm} install`;
133
+ child_process.execSync(cmd, { cwd: targetDir, stdio: "inherit" });
134
+ }
135
+ __name(installDependencies, "installDependencies");
136
+ function addPackage(targetDir, pm, pkg, dev) {
137
+ const installFlag = dev ? "-D" : "";
138
+ const cmd = pm === "npm" ? `npm install ${installFlag} ${pkg}` : pm === "yarn" ? `yarn add ${installFlag} ${pkg}` : `pnpm add ${installFlag} ${pkg}`;
139
+ child_process.execSync(cmd, { cwd: targetDir, stdio: "inherit" });
140
+ }
141
+ __name(addPackage, "addPackage");
142
+
143
+ // packages/cli/src/commands/init.ts
144
+ async function initCommand(options) {
145
+ const projectName = options.name || await p__namespace.text({
146
+ message: "Project name:",
147
+ placeholder: "my-vobs-app",
148
+ validate: /* @__PURE__ */ __name((v) => !v ? "Project name is required" : void 0, "validate")
149
+ });
150
+ if (p__namespace.isCancel(projectName)) {
151
+ p__namespace.cancel("Cancelled");
152
+ return;
153
+ }
154
+ const targetDir = options.targetDir || path.resolve(process.cwd(), projectName);
155
+ const packageManager = options.packageManager || await p__namespace.select({
156
+ message: "Package manager:",
157
+ options: [
158
+ { value: "pnpm", label: "pnpm" },
159
+ { value: "npm", label: "npm" },
160
+ { value: "yarn", label: "yarn" }
161
+ ]
162
+ });
163
+ if (p__namespace.isCancel(packageManager)) {
164
+ p__namespace.cancel("Cancelled");
165
+ return;
166
+ }
167
+ const useTypescript = options.typescript ?? await p__namespace.confirm({
168
+ message: "Use TypeScript?",
169
+ initialValue: true
170
+ });
171
+ if (p__namespace.isCancel(useTypescript)) {
172
+ p__namespace.cancel("Cancelled");
173
+ return;
174
+ }
175
+ const initGit = options.git ?? await p__namespace.confirm({
176
+ message: "Initialize a git repository?",
177
+ initialValue: true
178
+ });
179
+ if (p__namespace.isCancel(initGit)) {
180
+ p__namespace.cancel("Cancelled");
181
+ return;
182
+ }
183
+ logger.step(`Creating project ${projectName}...`);
184
+ await scaffoldProject(targetDir, {
185
+ name: projectName,
186
+ packageName: projectName.toLowerCase().replace(/\s+/g, "-"),
187
+ typescript: useTypescript,
188
+ vobsVersion: "1.0.0"
189
+ });
190
+ logger.success("Project scaffolded");
191
+ logger.step("Installing dependencies...");
192
+ installDependencies(targetDir, packageManager);
193
+ logger.success("Dependencies installed");
194
+ if (initGit) {
195
+ logger.step("Initializing git repository...");
196
+ try {
197
+ child_process.execSync("git init", { cwd: targetDir, stdio: "ignore" });
198
+ logger.success("Git repository initialized");
199
+ } catch {
200
+ logger.warn("Git not found, skipping git init");
201
+ }
202
+ }
203
+ logger.step("Done!");
204
+ console.log(`
205
+ ${packageManager === "pnpm" ? "pnpm" : packageManager === "yarn" ? "yarn" : "npm run"} dev
206
+ `);
207
+ }
208
+ __name(initCommand, "initCommand");
209
+ async function devCommand(options) {
210
+ logger.info("Starting dev server...");
211
+ const server = await vite.createServer({
212
+ configFile: options.config,
213
+ server: {
214
+ port: options.port,
215
+ open: options.open
216
+ }
217
+ });
218
+ await server.listen();
219
+ server.printUrls();
220
+ logger.success("Dev server is running");
221
+ }
222
+ __name(devCommand, "devCommand");
223
+ async function buildCommand(options) {
224
+ logger.info("Building for production...");
225
+ await vite.build({
226
+ configFile: options.config,
227
+ build: {
228
+ outDir: options.outDir
229
+ },
230
+ mode: options.mode || "production"
231
+ });
232
+ logger.success("Build complete");
233
+ }
234
+ __name(buildCommand, "buildCommand");
235
+ async function generateCommand(options) {
236
+ const type = options.type || await p__namespace.select({
237
+ message: "What to generate?",
238
+ options: [
239
+ { value: "component", label: "Component" },
240
+ { value: "page", label: "Page" }
241
+ ]
242
+ });
243
+ if (p__namespace.isCancel(type)) {
244
+ p__namespace.cancel("Cancelled");
245
+ return;
246
+ }
247
+ const name = options.name || await p__namespace.text({
248
+ message: "Name:",
249
+ placeholder: type === "component" ? "Button" : "AboutPage",
250
+ validate: /* @__PURE__ */ __name((v) => !v ? "Name is required" : void 0, "validate")
251
+ });
252
+ if (p__namespace.isCancel(name)) {
253
+ p__namespace.cancel("Cancelled");
254
+ return;
255
+ }
256
+ const templatesDir = getTemplatesDir();
257
+ if (type === "component") {
258
+ const targetDir = options.targetDir || path.resolve(process.cwd(), "src/components");
259
+ ensureDir(targetDir);
260
+ const context = {
261
+ name: toPascalCase(name),
262
+ kebabName: toKebabCase(name)
263
+ };
264
+ const content = renderTemplate(
265
+ path.resolve(templatesDir, "component.hbs"),
266
+ context
267
+ );
268
+ const filename = `${context.name}.tsx`;
269
+ writeFile(targetDir, filename, content);
270
+ logger.success(`Created ${type} at ${path.resolve(targetDir, filename)}`);
271
+ } else {
272
+ const targetDir = options.targetDir || path.resolve(process.cwd(), "src/pages");
273
+ ensureDir(targetDir);
274
+ const context = {
275
+ name: toPascalCase(name),
276
+ path: `/${toKebabCase(name)}`
277
+ };
278
+ const content = renderTemplate(
279
+ path.resolve(templatesDir, "page.hbs"),
280
+ context
281
+ );
282
+ const filename = `${context.name}.tsx`;
283
+ writeFile(targetDir, filename, content);
284
+ logger.success(`Created ${type} at ${path.resolve(targetDir, filename)}`);
285
+ }
286
+ }
287
+ __name(generateCommand, "generateCommand");
288
+ function toPascalCase(str) {
289
+ return str.replace(/[^a-zA-Z0-9]/g, " ").split(/\s+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
290
+ }
291
+ __name(toPascalCase, "toPascalCase");
292
+ function toKebabCase(str) {
293
+ return str.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "").replace(/[^a-z0-9-]/g, "-").replace(/--+/g, "-").replace(/^-|-$/g, "");
294
+ }
295
+ __name(toKebabCase, "toKebabCase");
296
+ async function addCommand(options) {
297
+ const pkg = options.package || await p__namespace.text({
298
+ message: "Package to add:",
299
+ placeholder: "@vobs/ui",
300
+ validate: /* @__PURE__ */ __name((v) => !v ? "Package name is required" : void 0, "validate")
301
+ });
302
+ if (p__namespace.isCancel(pkg)) {
303
+ p__namespace.cancel("Cancelled");
304
+ return;
305
+ }
306
+ const isDev = options.dev ?? await p__namespace.confirm({
307
+ message: "Save as dev dependency?",
308
+ initialValue: false
309
+ });
310
+ if (p__namespace.isCancel(isDev)) {
311
+ p__namespace.cancel("Cancelled");
312
+ return;
313
+ }
314
+ const pm = detectPackageManager(process.cwd());
315
+ logger.step(`Installing ${pkg}...`);
316
+ addPackage(process.cwd(), pm, pkg, isDev);
317
+ logger.success(`Installed ${pkg}`);
318
+ console.log(`
319
+ Import it in your code:
320
+ `);
321
+ console.log(` import { ... } from '${pkg}'`);
322
+ console.log();
323
+ }
324
+ __name(addCommand, "addCommand");
325
+
326
+ // packages/cli/src/banner.ts
327
+ var BANNER_LINE1 = "\u{1D5E9}\u{1D5E2}\u{1D5D5}\u{1D5E6} \u{1D5D6}\u{1D5DF}\u{1D5DC} \u{1D603}\u{1D7ED}.\u{1D7EC}";
328
+ var BANNER_TAGLINE = "Signals First \xB7 Zero Re-renders \xB7 Ultra Lightweight";
329
+ var INDENT = " ";
330
+ var DIM = "\x1B[2m";
331
+ var RESET = "\x1B[0m";
332
+ function showLogo() {
333
+ console.log();
334
+ console.log();
335
+ console.log(`${INDENT}${BANNER_LINE1}`);
336
+ console.log();
337
+ console.log(`${INDENT}${DIM}${BANNER_TAGLINE}${RESET}`);
338
+ console.log();
339
+ console.log();
340
+ }
341
+ __name(showLogo, "showLogo");
342
+ function showBanner() {
343
+ console.log(`${INDENT}${BANNER_LINE1}`);
344
+ }
345
+ __name(showBanner, "showBanner");
346
+ function showDevBanner() {
347
+ console.log();
348
+ console.log(`${INDENT}${BANNER_LINE1}`);
349
+ console.log();
350
+ }
351
+ __name(showDevBanner, "showDevBanner");
352
+
353
+ // packages/cli/src/cli.ts
354
+ function createCLI() {
355
+ const cli = cac.cac("vobs");
356
+ cli.command("init [name]", "Create a new vobs project").option("--dir <dir>", "Target directory").option("--pm <pm>", "Package manager (pnpm/npm/yarn)").option("--no-typescript", "Do not use TypeScript").option("--no-git", "Do not initialize git").action(async (name, options) => {
357
+ await initCommand({
358
+ name,
359
+ targetDir: options.dir,
360
+ packageManager: options.pm,
361
+ typescript: options.typescript !== false,
362
+ git: options.git !== false
363
+ });
364
+ });
365
+ cli.command("create [name]", "Alias for init").option("--dir <dir>", "Target directory").option("--pm <pm>", "Package manager (pnpm/npm/yarn)").option("--no-typescript", "Do not use TypeScript").option("--no-git", "Do not initialize git").action(async (name, options) => {
366
+ await initCommand({
367
+ name,
368
+ targetDir: options.dir,
369
+ packageManager: options.pm,
370
+ typescript: options.typescript !== false,
371
+ git: options.git !== false
372
+ });
373
+ });
374
+ cli.command("dev", "Start the dev server").option("--config <path>", "Vite config file").option("--port <port>", "Port to listen on").option("--open", "Open browser on start").action(async (options) => {
375
+ showDevBanner();
376
+ await devCommand({
377
+ config: options.config,
378
+ port: options.port,
379
+ open: options.open
380
+ });
381
+ });
382
+ cli.command("build", "Build for production").option("--config <path>", "Vite config file").option("--outDir <dir>", "Output directory").option("--mode <mode>", "Build mode").action(async (options) => {
383
+ await buildCommand({
384
+ config: options.config,
385
+ outDir: options.outDir,
386
+ mode: options.mode
387
+ });
388
+ });
389
+ cli.command("generate [name]", "Generate code (component/page)").alias("g").option("--type <type>", "Type: component or page").option("--dir <dir>", "Target directory").action(async (name, options) => {
390
+ await generateCommand({
391
+ name,
392
+ type: options.type || void 0,
393
+ targetDir: options.dir
394
+ });
395
+ });
396
+ cli.command("add [package]", "Add a package").option("-D, --dev", "Save as dev dependency").action(async (pkg, options) => {
397
+ await addCommand({
398
+ package: pkg,
399
+ dev: options.dev
400
+ });
401
+ });
402
+ cli.command("logo", "Show the vobs CLI logo and version info").action(() => {
403
+ showLogo();
404
+ });
405
+ cli.on("--help", () => {
406
+ showBanner();
407
+ });
408
+ cli.help();
409
+ cli.version("1.0.0");
410
+ return cli;
411
+ }
412
+ __name(createCLI, "createCLI");
413
+
414
+ exports.createCLI = createCLI;
415
+ //# sourceMappingURL=cli.cjs.map
416
+ //# sourceMappingURL=cli.cjs.map