@vertz/create-vertz-app 0.2.1 → 0.2.2

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.
@@ -1,8 +1,7 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
 
3
3
  import { Command } from 'commander';
4
- import { resolveOptions, scaffold } from '../src/index.js';
5
- import type { Runtime } from '../src/types.js';
4
+ import { resolveOptions, scaffold } from '../dist/index.js';
6
5
 
7
6
  const program = new Command();
8
7
 
@@ -11,55 +10,24 @@ program
11
10
  .description('Scaffold a new Vertz project')
12
11
  .version('0.1.0')
13
12
  .argument('[name]', 'Project name')
14
- .option('-r, --runtime <runtime>', 'Runtime to use (bun, node, deno)', 'bun')
15
- .option('-e, --example', 'Include example health module', undefined)
16
- .option('--no-example', 'Exclude example health module')
17
- .action(
18
- async (
19
- name: string | undefined,
20
- options: {
21
- runtime: string;
22
- example?: boolean;
23
- },
24
- ) => {
25
- try {
26
- // Convert runtime string to Runtime type
27
- const runtime = options.runtime.toLowerCase() as Runtime;
28
-
29
- // Handle --example / --no-example
30
- let includeExample: boolean | undefined;
31
- if (options.example === true) {
32
- includeExample = true;
33
- } else if (options.example === false) {
34
- includeExample = false;
35
- }
36
-
37
- const cliOptions = {
38
- projectName: name,
39
- runtime,
40
- includeExample,
41
- };
42
-
43
- const resolved = await resolveOptions(cliOptions);
44
-
45
- console.log(`Creating Vertz app: ${resolved.projectName}`);
46
- console.log(`Runtime: ${resolved.runtime}`);
47
- console.log(`Include example: ${resolved.includeExample ? 'Yes' : 'No'}`);
48
-
49
- // Create project in current directory
50
- const targetDir = process.cwd();
51
- await scaffold(targetDir, resolved);
52
-
53
- console.log(`\n✓ Created ${resolved.projectName}`);
54
- console.log(`\nNext steps:`);
55
- console.log(` cd ${resolved.projectName}`);
56
- console.log(` bun install`);
57
- console.log(` bun run dev`);
58
- } catch (error) {
59
- console.error('Error:', error instanceof Error ? error.message : error);
60
- process.exit(1);
61
- }
62
- },
63
- );
13
+ .action(async (name: string | undefined) => {
14
+ try {
15
+ const resolved = await resolveOptions({ projectName: name });
16
+
17
+ console.log(`Creating Vertz app: ${resolved.projectName}`);
18
+
19
+ const targetDir = process.cwd();
20
+ await scaffold(targetDir, resolved);
21
+
22
+ console.log(`\n✓ Created ${resolved.projectName}`);
23
+ console.log(`\nNext steps:`);
24
+ console.log(` cd ${resolved.projectName}`);
25
+ console.log(` bun install`);
26
+ console.log(` bun run dev`);
27
+ } catch (error) {
28
+ console.error('Error:', error instanceof Error ? error.message : error);
29
+ process.exit(1);
30
+ }
31
+ });
64
32
 
65
33
  program.parse();
package/dist/prompts.d.ts CHANGED
@@ -1,28 +1,14 @@
1
- import type { CliOptions, Runtime, ScaffoldOptions } from './types.js';
1
+ import type { CliOptions, ScaffoldOptions } from './types.js';
2
2
  /**
3
3
  * Error thrown in CI mode when project name is required but not provided
4
4
  */
5
5
  export declare class ProjectNameRequiredError extends Error {
6
6
  constructor();
7
7
  }
8
- /**
9
- * Error thrown when an invalid runtime is provided
10
- */
11
- export declare class InvalidRuntimeError extends Error {
12
- constructor(runtime: string);
13
- }
14
8
  /**
15
9
  * Prompts the user for project name
16
10
  */
17
11
  export declare function promptForProjectName(): Promise<string>;
18
- /**
19
- * Prompts the user for runtime selection
20
- */
21
- export declare function promptForRuntime(): Promise<Runtime>;
22
- /**
23
- * Prompts the user for example module inclusion
24
- */
25
- export declare function promptForExample(): Promise<boolean>;
26
12
  /**
27
13
  * Resolves CLI options into complete scaffold options
28
14
  * Handles both interactive and CI modes
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIvE;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;;CAKlD;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CAY5D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAiBzD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAkBzD;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CA0C9F"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;;CAKlD;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CAY5D;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAY9F"}
package/dist/prompts.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { createInterface } from 'node:readline';
2
- const VALID_RUNTIMES = ['bun', 'node', 'deno'];
3
2
  /**
4
3
  * Error thrown in CI mode when project name is required but not provided
5
4
  */
@@ -9,15 +8,6 @@ export class ProjectNameRequiredError extends Error {
9
8
  this.name = 'ProjectNameRequiredError';
10
9
  }
11
10
  }
12
- /**
13
- * Error thrown when an invalid runtime is provided
14
- */
15
- export class InvalidRuntimeError extends Error {
16
- constructor(runtime) {
17
- super(`Invalid runtime: ${runtime}. Valid options are: ${VALID_RUNTIMES.join(', ')}`);
18
- this.name = 'InvalidRuntimeError';
19
- }
20
- }
21
11
  /**
22
12
  * Prompts the user for project name
23
13
  */
@@ -33,60 +23,12 @@ export async function promptForProjectName() {
33
23
  });
34
24
  });
35
25
  }
36
- /**
37
- * Prompts the user for runtime selection
38
- */
39
- export async function promptForRuntime() {
40
- return new Promise((resolve) => {
41
- const rl = createInterface({
42
- input: process.stdin,
43
- output: process.stdout,
44
- });
45
- rl.question('Runtime (bun/node/deno) [bun]: ', (answer) => {
46
- rl.close();
47
- const trimmed = answer.trim().toLowerCase();
48
- if (VALID_RUNTIMES.includes(trimmed)) {
49
- resolve(trimmed);
50
- }
51
- else {
52
- resolve('bun');
53
- }
54
- });
55
- });
56
- }
57
- /**
58
- * Prompts the user for example module inclusion
59
- */
60
- export async function promptForExample() {
61
- return new Promise((resolve) => {
62
- const rl = createInterface({
63
- input: process.stdin,
64
- output: process.stdout,
65
- });
66
- rl.question('Include example health module? (Y/n): ', (answer) => {
67
- rl.close();
68
- const trimmed = answer.trim().toLowerCase();
69
- // Default to yes
70
- if (trimmed === 'n' || trimmed === 'no') {
71
- resolve(false);
72
- }
73
- else {
74
- resolve(true);
75
- }
76
- });
77
- });
78
- }
79
26
  /**
80
27
  * Resolves CLI options into complete scaffold options
81
28
  * Handles both interactive and CI modes
82
29
  */
83
30
  export async function resolveOptions(cliOptions) {
84
31
  const isCI = process.env.CI === 'true';
85
- // Validate runtime if provided
86
- if (cliOptions.runtime !== undefined && !VALID_RUNTIMES.includes(cliOptions.runtime)) {
87
- throw new InvalidRuntimeError(cliOptions.runtime);
88
- }
89
- // Handle project name
90
32
  let projectName = cliOptions.projectName;
91
33
  if (!projectName) {
92
34
  if (isCI) {
@@ -94,29 +36,5 @@ export async function resolveOptions(cliOptions) {
94
36
  }
95
37
  projectName = await promptForProjectName();
96
38
  }
97
- // Handle runtime
98
- let runtime = cliOptions.runtime;
99
- if (!runtime) {
100
- if (isCI) {
101
- runtime = 'bun'; // Default in CI mode
102
- }
103
- else {
104
- runtime = await promptForRuntime();
105
- }
106
- }
107
- // Handle example inclusion
108
- let includeExample = cliOptions.includeExample;
109
- if (includeExample === undefined) {
110
- if (isCI) {
111
- includeExample = true; // Default in CI mode
112
- }
113
- else {
114
- includeExample = await promptForExample();
115
- }
116
- }
117
- return {
118
- projectName,
119
- runtime,
120
- includeExample,
121
- };
39
+ return { projectName };
122
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,WAAW,EAAE,MAAM;CAIhC;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzF"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,WAAW,EAAE,MAAM;CAIhC;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDzF"}
package/dist/scaffold.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { promises as fs } from 'node:fs';
2
2
  import path from 'node:path';
3
- import { appTemplate, denoConfigTemplate, envExampleTemplate, envSrcTemplate, envTemplate, gitignoreTemplate, healthModuleDefTemplate, healthModuleTemplate, healthRouterTemplate, healthServiceTemplate, mainTemplate, packageJsonTemplate, tsconfigTemplate, vertzConfigTemplate, } from './templates/index.js';
3
+ import { appComponentTemplate, clientTemplate, dbTemplate, entryClientTemplate, envExampleTemplate, envTemplate, gitignoreTemplate, homePageTemplate, packageJsonTemplate, schemaTemplate, serverTemplate, tasksEntityTemplate, themeTemplate, tsconfigTemplate, vertzConfigTemplate, } from './templates/index.js';
4
4
  /**
5
5
  * Error thrown when the project directory already exists
6
6
  */
@@ -16,7 +16,7 @@ export class DirectoryExistsError extends Error {
16
16
  * @param options - Scaffold options
17
17
  */
18
18
  export async function scaffold(parentDir, options) {
19
- const { projectName, runtime, includeExample } = options;
19
+ const { projectName } = options;
20
20
  const projectDir = path.join(parentDir, projectName);
21
21
  // Check if directory already exists
22
22
  try {
@@ -29,35 +29,38 @@ export async function scaffold(parentDir, options) {
29
29
  }
30
30
  // Directory doesn't exist, which is what we want
31
31
  }
32
- // Create project directory
33
- await fs.mkdir(projectDir, { recursive: true });
34
- // Create subdirectories
32
+ // Create project directory and subdirectories
35
33
  const srcDir = path.join(projectDir, 'src');
36
- const modulesDir = path.join(srcDir, 'modules');
37
- await fs.mkdir(srcDir, { recursive: true });
38
- await fs.mkdir(modulesDir, { recursive: true });
39
- // Generate and write core config files
40
- await writeFile(projectDir, 'package.json', packageJsonTemplate({ projectName, runtime, includeExample }));
41
- await writeFile(projectDir, 'tsconfig.json', tsconfigTemplate(runtime));
42
- await writeFile(projectDir, 'vertz.config.ts', vertzConfigTemplate());
43
- await writeFile(projectDir, '.env', envTemplate());
44
- await writeFile(projectDir, '.env.example', envExampleTemplate());
45
- await writeFile(projectDir, '.gitignore', gitignoreTemplate());
46
- // Generate Deno-specific config if needed
47
- if (runtime === 'deno') {
48
- await writeFile(projectDir, 'deno.json', denoConfigTemplate());
49
- }
50
- // Generate source files
51
- await writeFile(srcDir, 'env.ts', envSrcTemplate());
52
- await writeFile(srcDir, 'app.ts', appTemplate(includeExample));
53
- await writeFile(srcDir, 'main.ts', mainTemplate());
54
- // Generate example health module if requested
55
- if (includeExample) {
56
- await writeFile(modulesDir, 'health.module-def.ts', healthModuleDefTemplate());
57
- await writeFile(modulesDir, 'health.service.ts', healthServiceTemplate());
58
- await writeFile(modulesDir, 'health.router.ts', healthRouterTemplate());
59
- await writeFile(modulesDir, 'health.module.ts', healthModuleTemplate());
60
- }
34
+ const apiDir = path.join(srcDir, 'api');
35
+ const entitiesDir = path.join(apiDir, 'entities');
36
+ const pagesDir = path.join(srcDir, 'pages');
37
+ const stylesDir = path.join(srcDir, 'styles');
38
+ await Promise.all([
39
+ fs.mkdir(entitiesDir, { recursive: true }),
40
+ fs.mkdir(pagesDir, { recursive: true }),
41
+ fs.mkdir(stylesDir, { recursive: true }),
42
+ ]);
43
+ // Write all files in parallel
44
+ await Promise.all([
45
+ // Config files
46
+ writeFile(projectDir, 'package.json', packageJsonTemplate(projectName)),
47
+ writeFile(projectDir, 'tsconfig.json', tsconfigTemplate()),
48
+ writeFile(projectDir, 'vertz.config.ts', vertzConfigTemplate()),
49
+ writeFile(projectDir, '.env', envTemplate()),
50
+ writeFile(projectDir, '.env.example', envExampleTemplate()),
51
+ writeFile(projectDir, '.gitignore', gitignoreTemplate()),
52
+ // API source files
53
+ writeFile(apiDir, 'server.ts', serverTemplate()),
54
+ writeFile(apiDir, 'schema.ts', schemaTemplate()),
55
+ writeFile(apiDir, 'db.ts', dbTemplate()),
56
+ writeFile(entitiesDir, 'tasks.entity.ts', tasksEntityTemplate()),
57
+ // UI source files
58
+ writeFile(srcDir, 'client.ts', clientTemplate()),
59
+ writeFile(srcDir, 'app.tsx', appComponentTemplate()),
60
+ writeFile(srcDir, 'entry-client.ts', entryClientTemplate()),
61
+ writeFile(pagesDir, 'home.tsx', homePageTemplate()),
62
+ writeFile(stylesDir, 'theme.ts', themeTemplate()),
63
+ ]);
61
64
  }
62
65
  /**
63
66
  * Helper to write a file with consistent formatting