@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/dist/scaffold.js DELETED
@@ -1,448 +0,0 @@
1
- /** @license MIT
2
- * Copyright (c) 2026 vobsjs
3
- * @vobs/cli
4
- */
5
- import { existsSync, mkdirSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
6
- import * as path from 'node:path';
7
- import { enterpriseFiles } from './enterprise-template.js';
8
- export function createScaffold(type, name, options = {}, cwd = process.cwd()) {
9
- const template = resolveScaffoldTemplate(type, options);
10
- const projectName = readProjectName(name);
11
- const packageName = projectName;
12
- const targetDir = path.resolve(cwd, projectName);
13
- if (existsSync(targetDir)) {
14
- if (!options.force) {
15
- throw new Error(`Directory already exists: ${projectName}. Use --force to overwrite.`);
16
- }
17
- assertSafeTarget(cwd, targetDir);
18
- rmSync(targetDir, { recursive: true, force: true });
19
- }
20
- const context = {
21
- projectName,
22
- packageName,
23
- description: `A vobs ${isAppTemplate(template) ? 'application' : 'library'}.`,
24
- };
25
- for (const file of filesForTemplate(template)) {
26
- const filePath = path.join(targetDir, file.path);
27
- mkdirSync(path.dirname(filePath), { recursive: true });
28
- writeFileSync(filePath, renderTemplate(file.content, context));
29
- }
30
- return { name: projectName, targetDir, template };
31
- }
32
- export function resolveScaffoldTemplate(type, options = {}) {
33
- const candidate = options.template ?? normalizeTemplateShortcut(type, options.withDi === true);
34
- if (candidate !== undefined)
35
- return candidate;
36
- throw new Error('vobs new requires a template type and project name.');
37
- }
38
- export function isScaffoldTemplate(value) {
39
- return (value === 'app' ||
40
- value === 'app-di' ||
41
- value === 'enterprise' ||
42
- value === 'lib' ||
43
- value === 'lib-di');
44
- }
45
- export function scaffoldSuccessText(result) {
46
- const command = isAppTemplate(result.template) ? 'pnpm run dev' : 'pnpm run build';
47
- const diLine = result.template === 'app-di' || result.template === 'enterprise' || result.template === 'lib-di'
48
- ? '\nDI integration included.\n'
49
- : '\n';
50
- return [
51
- `Created ${result.name}`,
52
- '',
53
- ` cd ${result.name}`,
54
- ' pnpm install',
55
- ` ${command}`,
56
- diLine,
57
- ].join('\n');
58
- }
59
- function normalizeTemplateShortcut(type, withDi) {
60
- if (type === undefined)
61
- return undefined;
62
- if (type === 'app')
63
- return withDi ? 'app-di' : 'app';
64
- if (type === 'lib')
65
- return withDi ? 'lib-di' : 'lib';
66
- if (isScaffoldTemplate(type))
67
- return type;
68
- throw new Error(`Unknown template: ${type}`);
69
- }
70
- function readProjectName(name) {
71
- if (name === undefined)
72
- throw new Error('vobs new requires a project name.');
73
- if (!/^[a-z0-9][a-z0-9-]*$/u.test(name)) {
74
- throw new Error('Project name must use lowercase letters, numbers, and hyphens.');
75
- }
76
- return name;
77
- }
78
- function assertSafeTarget(cwd, targetDir) {
79
- const relative = path.relative(cwd, targetDir);
80
- if (relative === '' || relative.startsWith('..') || path.isAbsolute(relative)) {
81
- throw new Error(`Refusing to overwrite outside the current directory: ${targetDir}`);
82
- }
83
- const entries = readdirSync(targetDir);
84
- if (entries.some((entry) => {
85
- const entryPath = path.join(targetDir, entry);
86
- return statSync(entryPath).isDirectory() && entry === '.git';
87
- })) {
88
- throw new Error(`Refusing to overwrite a Git repository: ${targetDir}`);
89
- }
90
- }
91
- function renderTemplate(content, context) {
92
- return content
93
- .replaceAll('{{projectName}}', context.projectName)
94
- .replaceAll('{{packageName}}', context.packageName)
95
- .replaceAll('{{description}}', context.description);
96
- }
97
- function filesForTemplate(template) {
98
- switch (template) {
99
- case 'app':
100
- return appFiles(false);
101
- case 'app-di':
102
- return appFiles(true);
103
- case 'enterprise':
104
- return enterpriseFiles;
105
- case 'lib':
106
- return libFiles(false);
107
- case 'lib-di':
108
- return libFiles(true);
109
- }
110
- }
111
- function isAppTemplate(template) {
112
- return template === 'app' || template === 'app-di' || template === 'enterprise';
113
- }
114
- function appFiles(withDi) {
115
- return [
116
- { path: 'package.json', content: appPackageJson(withDi) },
117
- { path: 'tsconfig.json', content: appTsconfig },
118
- { path: 'vite.config.ts', content: viteConfig },
119
- { path: 'index.html', content: indexHtml },
120
- { path: 'src/env.d.ts', content: envDts },
121
- { path: 'src/app.ts', content: withDi ? appModuleWithDi : appModule },
122
- { path: 'src/main.ts', content: appMain },
123
- ...(withDi ? appDiFiles : []),
124
- { path: 'src/pages/index.ts', content: withDi ? indexPageWithDi : indexPage },
125
- { path: 'src/pages/index.html', content: indexPageHtml },
126
- { path: 'src/styles/global.css', content: globalCss },
127
- ];
128
- }
129
- function libFiles(withDi) {
130
- return [
131
- { path: 'package.json', content: libPackageJson(withDi) },
132
- { path: 'tsconfig.json', content: libTsconfig },
133
- { path: 'src/index.ts', content: withDi ? libIndexWithDi : libIndex },
134
- ...(withDi ? [{ path: 'src/keys.ts', content: libKeysWithDi }] : []),
135
- { path: 'src/types.ts', content: withDi ? libTypesWithDi : libTypes },
136
- { path: 'README.md', content: withDi ? libReadmeWithDi : libReadme },
137
- ];
138
- }
139
- function appPackageJson(_withDi) {
140
- return `{
141
- "name": "{{packageName}}",
142
- "version": "0.1.0",
143
- "private": true,
144
- "type": "module",
145
- "engines": {
146
- "node": ">=22.12.0"
147
- },
148
- "scripts": {
149
- "dev": "vite",
150
- "build": "tsc --noEmit && vite build",
151
- "preview": "vite preview",
152
- "typecheck": "tsc --noEmit"
153
- },
154
- "dependencies": {
155
- "@vobs/vobs": "0.2.0"
156
- },
157
- "devDependencies": {
158
- "@vobs/vite-plugin": "0.1.0",
159
- "typescript": "^5.7.0",
160
- "vite": "^8.0.0"
161
- }
162
- }
163
- `;
164
- }
165
- const appTsconfig = `{
166
- "compilerOptions": {
167
- "target": "ES2022",
168
- "module": "ESNext",
169
- "moduleResolution": "Bundler",
170
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
171
- "strict": true,
172
- "skipLibCheck": true,
173
- "isolatedModules": true,
174
- "verbatimModuleSyntax": true,
175
- "types": ["@vobs/vite-plugin/client"]
176
- },
177
- "include": ["src/**/*.ts", "vite.config.ts"]
178
- }
179
- `;
180
- const viteConfig = `import { defineConfig } from 'vite';
181
- import { vobs } from '@vobs/vite-plugin';
182
-
183
- export default defineConfig({
184
- plugins: [vobs()],
185
- });
186
- `;
187
- const indexHtml = `<div id="app"></div>
188
- <script type="module" src="/src/main.ts"></script>
189
- `;
190
- const envDts = `/// <reference types="@vobs/vite-plugin/client" />
191
- `;
192
- const appMain = `import { app } from './app.js';
193
- import './styles/global.css';
194
-
195
- await app.mount('#app');
196
- `;
197
- const appModule = `import { createVobsApp } from '@vobs/vobs';
198
- import router from 'vobs:routes';
199
-
200
- const reportAppError = (error: unknown): void => {
201
- queueMicrotask(() => {
202
- throw error;
203
- });
204
- };
205
-
206
- const app = createVobsApp({
207
- router,
208
- onAppError(error) {
209
- reportAppError(error);
210
- },
211
- });
212
-
213
- export { app };
214
- `;
215
- const appModuleWithDi = `import { createInjectionScope, createVobsApp } from '@vobs/vobs';
216
- import router from 'vobs:routes';
217
- import { registerServices } from './app/di.js';
218
-
219
- const injections = createInjectionScope();
220
- registerServices(injections);
221
-
222
- const reportAppError = (error: unknown): void => {
223
- queueMicrotask(() => {
224
- throw error;
225
- });
226
- };
227
-
228
- const app = createVobsApp({
229
- router,
230
- ui: { injections },
231
- onAppError(error) {
232
- reportAppError(error);
233
- },
234
- });
235
-
236
- export { app };
237
- `;
238
- const appDiFiles = [
239
- {
240
- path: 'src/app/di.ts',
241
- content: `import type { InjectionScope } from '@vobs/vobs';
242
- import { createToastService, ToastServiceKey } from '../services/toast.js';
243
-
244
- export function registerServices(scope: InjectionScope): void {
245
- scope.provide(
246
- ToastServiceKey,
247
- createToastService({
248
- prefix: '{{projectName}}',
249
- }),
250
- );
251
- }
252
- `,
253
- },
254
- {
255
- path: 'src/services/toast.ts',
256
- content: `import { createInjectionKey, inject } from '@vobs/vobs';
257
-
258
- export interface ToastService {
259
- success(message: string): void;
260
- }
261
-
262
- export const ToastServiceKey = createInjectionKey<ToastService>('app.toast');
263
-
264
- export function createToastService(options: { readonly prefix: string }): ToastService {
265
- return {
266
- success(message) {
267
- console.info(\`[\${options.prefix}] \${message}\`);
268
- },
269
- };
270
- }
271
-
272
- export function useToast(): ToastService {
273
- return inject(ToastServiceKey);
274
- }
275
- `,
276
- },
277
- ];
278
- const indexPage = `import { definePage, signal } from '@vobs/vobs';
279
- import template from './index.html';
280
-
281
- export default definePage({
282
- template,
283
- setup() {
284
- const count = signal(0);
285
-
286
- function increment() {
287
- count.value += 1;
288
- }
289
-
290
- return { count, increment };
291
- },
292
- });
293
- `;
294
- const indexPageWithDi = `import { definePage, signal } from '@vobs/vobs';
295
- import { useToast } from '../services/toast.js';
296
- import template from './index.html';
297
-
298
- export default definePage({
299
- template,
300
- setup() {
301
- const toast = useToast();
302
- const count = signal(0);
303
-
304
- function increment() {
305
- count.value += 1;
306
- toast.success(\`Count is now \${count.value}\`);
307
- }
308
-
309
- return { count, increment };
310
- },
311
- });
312
- `;
313
- const indexPageHtml = `<main>
314
- <h1>{{projectName}}</h1>
315
- <p>{{description}}</p>
316
- <button type="button" @click="increment()">Count: {{ count }}</button>
317
- </main>
318
- `;
319
- const globalCss = `:root {
320
- color-scheme: light;
321
- font-family:
322
- Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
323
- }
324
-
325
- body {
326
- margin: 0;
327
- }
328
-
329
- main {
330
- padding: 32px;
331
- }
332
- `;
333
- function libPackageJson(withDi) {
334
- return `{
335
- "name": "{{packageName}}",
336
- "version": "0.1.0",
337
- "type": "module",
338
- "main": "dist/index.js",
339
- "types": "dist/index.d.ts",
340
- "exports": {
341
- ".": {
342
- "types": "./dist/index.d.ts",
343
- "import": "./dist/index.js"
344
- }
345
- },
346
- "scripts": {
347
- "build": "tsc",
348
- "typecheck": "tsc --noEmit"
349
- },
350
- ${withDi ? ' "peerDependencies": {\n "@vobs/di": "^0.1.0"\n },\n' : ''} "files": ["dist"],
351
- "devDependencies": {
352
- ${withDi ? ' "@vobs/di": "0.1.0",\n' : ''} "typescript": "^5.7.0"
353
- }
354
- }
355
- `;
356
- }
357
- const libTsconfig = `{
358
- "compilerOptions": {
359
- "target": "ES2022",
360
- "module": "ESNext",
361
- "moduleResolution": "Bundler",
362
- "lib": ["ES2022", "DOM"],
363
- "strict": true,
364
- "declaration": true,
365
- "outDir": "dist",
366
- "rootDir": "src",
367
- "skipLibCheck": true,
368
- "isolatedModules": true,
369
- "verbatimModuleSyntax": true
370
- },
371
- "include": ["src/**/*.ts"]
372
- }
373
- `;
374
- const libIndex = `export function hello(name: string): string {
375
- return \`Hello, \${name}!\`;
376
- }
377
-
378
- export type { ExampleConfig, ExampleUser } from './types.js';
379
- `;
380
- const libTypes = `export interface ExampleUser {
381
- readonly id: string;
382
- readonly name: string;
383
- }
384
-
385
- export interface ExampleConfig {
386
- readonly apiUrl: string;
387
- readonly timeout: number;
388
- }
389
- `;
390
- const libIndexWithDi = `import { inject, provide } from '@vobs/di';
391
- import { ExampleServiceKey } from './keys.js';
392
- import type { ExampleConfig, ExampleService } from './types.js';
393
-
394
- export function createExampleService(config: ExampleConfig): ExampleService {
395
- return {
396
- async run(input) {
397
- return \`\${config.prefix}: \${input}\`;
398
- },
399
- };
400
- }
401
-
402
- export function provideExampleService(service: ExampleService): () => void {
403
- return provide(ExampleServiceKey, service);
404
- }
405
-
406
- export function useExampleService(): ExampleService {
407
- return inject(ExampleServiceKey);
408
- }
409
-
410
- export type { ExampleConfig, ExampleService } from './types.js';
411
- export { ExampleServiceKey } from './keys.js';
412
- `;
413
- const libKeysWithDi = `import { createInjectionKey } from '@vobs/di';
414
- import type { ExampleService } from './types.js';
415
-
416
- export const ExampleServiceKey = createInjectionKey<ExampleService>('{{packageName}}.example');
417
- `;
418
- const libTypesWithDi = `export interface ExampleService {
419
- run(input: string): Promise<string>;
420
- }
421
-
422
- export interface ExampleConfig {
423
- readonly prefix: string;
424
- }
425
- `;
426
- const libReadme = `# {{packageName}}
427
-
428
- {{description}}
429
- `;
430
- const libReadmeWithDi = `# {{packageName}}
431
-
432
- {{description}}
433
-
434
- ## Usage
435
-
436
- \`\`\`ts
437
- import { createInjectionScope, runWithInjectionScope } from '@vobs/di';
438
- import { createExampleService, provideExampleService, useExampleService } from '{{packageName}}';
439
-
440
- const injections = createInjectionScope();
441
-
442
- runWithInjectionScope(injections, () => {
443
- provideExampleService(createExampleService({ prefix: 'demo' }));
444
- const service = useExampleService();
445
- void service.run('hello');
446
- });
447
- \`\`\`
448
- `;