forgestack-os-cli 0.3.0 → 0.3.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.
- package/README.md +78 -0
- package/dist/commands/create.js +52 -55
- package/dist/commands/create.js.map +1 -1
- package/dist/generators/api.d.ts +1 -1
- package/dist/generators/api.js +29 -36
- package/dist/generators/api.js.map +1 -1
- package/dist/generators/auth.d.ts +1 -1
- package/dist/generators/auth.js +37 -43
- package/dist/generators/auth.js.map +1 -1
- package/dist/generators/backend.d.ts +1 -1
- package/dist/generators/backend.js +64 -70
- package/dist/generators/backend.js.map +1 -1
- package/dist/generators/common.d.ts +1 -1
- package/dist/generators/common.js +48 -13
- package/dist/generators/common.js.map +1 -1
- package/dist/generators/database.d.ts +1 -1
- package/dist/generators/database.js +18 -24
- package/dist/generators/database.js.map +1 -1
- package/dist/generators/docker.d.ts +1 -1
- package/dist/generators/docker.js +10 -16
- package/dist/generators/docker.js.map +1 -1
- package/dist/generators/frontend.d.ts +1 -1
- package/dist/generators/frontend.js +43 -49
- package/dist/generators/frontend.js.map +1 -1
- package/dist/generators/index.d.ts +1 -1
- package/dist/generators/index.js +40 -46
- package/dist/generators/index.js.map +1 -1
- package/dist/index.js +10 -7
- package/dist/index.js.map +1 -1
- package/dist/types.js +1 -2
- package/dist/utils/logger.js +9 -15
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/prompts.d.ts +16 -2
- package/dist/utils/prompts.js +108 -32
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/security.js +3 -9
- package/dist/utils/security.js.map +1 -1
- package/dist/utils/validators.d.ts +1 -1
- package/dist/utils/validators.js +7 -9
- package/dist/utils/validators.js.map +1 -1
- package/package.json +25 -3
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# ForgeStack OS CLI
|
|
2
|
+
|
|
3
|
+
Generate production-ready full-stack SaaS projects with one command.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Recommended: npx (no install)
|
|
9
|
+
npx forgestack-os-cli create my-app
|
|
10
|
+
|
|
11
|
+
# Or install globally
|
|
12
|
+
npm install -g forgestack-os-cli
|
|
13
|
+
# then
|
|
14
|
+
forgestack create my-app
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
forgestack create <project-name> [options]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Common flags**
|
|
24
|
+
|
|
25
|
+
- `--frontend <framework>`: react-vite | nextjs
|
|
26
|
+
- `--backend <framework>`: express | fastify | nestjs | bun-elysia | go-fiber
|
|
27
|
+
- `--auth <provider>`: jwt | clerk | supabase | authjs | firebase
|
|
28
|
+
- `--database <db>`: postgresql | mongodb | mysql | sqlite | supabase-db
|
|
29
|
+
- `--api <style>`: rest | graphql | trpc
|
|
30
|
+
- `--preset <name>`: use a predefined stack (e.g., next-nest-clerk-pg)
|
|
31
|
+
- `--stack <json>`: provide full stack config as JSON
|
|
32
|
+
- `--docker` / `--no-docker`: include or skip Docker config
|
|
33
|
+
- `--multi-tenant`: enable multi-tenancy scaffolding
|
|
34
|
+
- `--skip-install`: skip dependency installation
|
|
35
|
+
- `--skip-git`: skip git init
|
|
36
|
+
|
|
37
|
+
### Examples
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Interactive
|
|
41
|
+
forgestack create my-saas
|
|
42
|
+
|
|
43
|
+
# Preset
|
|
44
|
+
forgestack create my-enterprise --preset next-nest-clerk-pg
|
|
45
|
+
|
|
46
|
+
# Full JSON config
|
|
47
|
+
forgestack create my-app --stack '{"frontend":"nextjs","backend":"fastify","auth":"supabase","database":"supabase-db","apiStyle":"trpc","docker":true,"multiTenant":true}'
|
|
48
|
+
|
|
49
|
+
# Minimal flags
|
|
50
|
+
forgestack create api-only --frontend=react-vite --backend=express --auth=jwt --database=postgresql --api=rest --no-docker
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- 150+ stack combinations across frontend, backend, auth, database, and API styles
|
|
56
|
+
- Multi-tenancy ready scaffolds
|
|
57
|
+
- Docker Compose and env templates
|
|
58
|
+
- API docs (Swagger) for REST backends
|
|
59
|
+
- TypeScript-first across generated code
|
|
60
|
+
|
|
61
|
+
## Generated Project
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
my-app/
|
|
65
|
+
├─ frontend/ # Next.js or React+Vite
|
|
66
|
+
├─ backend/ # Express, Fastify, NestJS, Bun+Elysia, or Go+Fiber
|
|
67
|
+
├─ .env.example
|
|
68
|
+
├─ package.json (workspaces)
|
|
69
|
+
└─ README.md (per-project runbook)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Author
|
|
73
|
+
|
|
74
|
+
Built and maintained by **Sumit Chauhan** ([halloffame12](https://github.com/halloffame12)).
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT
|
package/dist/commands/create.js
CHANGED
|
@@ -1,88 +1,85 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const validators_1 = require("../utils/validators");
|
|
13
|
-
const generators_1 = require("../generators");
|
|
14
|
-
async function createCommand(projectName, options) {
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
import { promptForStack } from '../utils/prompts.js';
|
|
7
|
+
import { validateStackConfig } from '../utils/validators.js';
|
|
8
|
+
import { generateProject } from '../generators/index.js';
|
|
9
|
+
const pkgRequire = createRequire(import.meta.url);
|
|
10
|
+
const { version: CLI_VERSION } = pkgRequire('../../package.json');
|
|
11
|
+
export async function createCommand(projectName, options) {
|
|
15
12
|
try {
|
|
16
13
|
// Display welcome banner
|
|
17
|
-
console.log(
|
|
18
|
-
console.log(
|
|
19
|
-
console.log(
|
|
20
|
-
console.log(
|
|
21
|
-
console.log(
|
|
22
|
-
console.log(
|
|
23
|
-
console.log(
|
|
14
|
+
console.log(chalk.bold.cyan('\n╔═══════════════════════════════════════╗'));
|
|
15
|
+
console.log(chalk.bold.cyan('║ ║'));
|
|
16
|
+
console.log(chalk.bold.cyan(`║ 🚀 ForgeStack OS v${CLI_VERSION} ║`));
|
|
17
|
+
console.log(chalk.bold.cyan('║ ║'));
|
|
18
|
+
console.log(chalk.bold.cyan('║ One platform. Any stack. Production. ║'));
|
|
19
|
+
console.log(chalk.bold.cyan('║ ║'));
|
|
20
|
+
console.log(chalk.bold.cyan('╚═══════════════════════════════════════╝\n'));
|
|
24
21
|
// Check if directory already exists
|
|
25
|
-
const targetDir =
|
|
26
|
-
const actualProjectName =
|
|
27
|
-
if (await
|
|
28
|
-
|
|
22
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
23
|
+
const actualProjectName = path.basename(targetDir);
|
|
24
|
+
if (await fs.pathExists(targetDir)) {
|
|
25
|
+
logger.error(`Directory "${projectName}" already exists!`);
|
|
29
26
|
process.exit(1);
|
|
30
27
|
}
|
|
31
28
|
// Test write permissions
|
|
32
29
|
try {
|
|
33
|
-
await
|
|
34
|
-
await
|
|
30
|
+
await fs.ensureDir(targetDir);
|
|
31
|
+
await fs.remove(targetDir);
|
|
35
32
|
}
|
|
36
33
|
catch {
|
|
37
|
-
|
|
34
|
+
logger.error(`Permission denied! Cannot create directory at "${targetDir}".`);
|
|
38
35
|
process.exit(1);
|
|
39
36
|
}
|
|
40
37
|
// Prompt for stack configuration
|
|
41
|
-
|
|
42
|
-
const config = await
|
|
38
|
+
logger.title('📋 Configure Your Stack');
|
|
39
|
+
const config = await promptForStack(actualProjectName, options);
|
|
43
40
|
// Validate configuration
|
|
44
|
-
const validation =
|
|
41
|
+
const validation = validateStackConfig(config);
|
|
45
42
|
if (validation.warnings.length > 0) {
|
|
46
43
|
console.log('');
|
|
47
|
-
validation.warnings.forEach(warning =>
|
|
44
|
+
validation.warnings.forEach((warning) => logger.warning(warning));
|
|
48
45
|
}
|
|
49
46
|
if (!validation.valid) {
|
|
50
47
|
console.log('');
|
|
51
|
-
validation.errors.forEach(error =>
|
|
48
|
+
validation.errors.forEach((error) => logger.error(error));
|
|
52
49
|
process.exit(1);
|
|
53
50
|
}
|
|
54
51
|
// Display selected stack
|
|
55
52
|
console.log('');
|
|
56
|
-
|
|
57
|
-
console.log(
|
|
58
|
-
console.log(`${
|
|
59
|
-
console.log(`${
|
|
60
|
-
console.log(`${
|
|
61
|
-
console.log(`${
|
|
62
|
-
console.log(`${
|
|
63
|
-
console.log(`${
|
|
64
|
-
console.log(`${
|
|
65
|
-
console.log(`${
|
|
66
|
-
console.log(
|
|
53
|
+
logger.title('✨ Your Stack Configuration');
|
|
54
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
55
|
+
console.log(`${chalk.bold('Project:')} ${chalk.cyan(config.projectName)}`);
|
|
56
|
+
console.log(`${chalk.bold('Frontend:')} ${chalk.cyan(config.frontend)}`);
|
|
57
|
+
console.log(`${chalk.bold('Backend:')} ${chalk.cyan(config.backend)}`);
|
|
58
|
+
console.log(`${chalk.bold('Auth:')} ${chalk.cyan(config.auth)}`);
|
|
59
|
+
console.log(`${chalk.bold('Database:')} ${chalk.cyan(config.database)}`);
|
|
60
|
+
console.log(`${chalk.bold('API Style:')} ${chalk.cyan(config.apiStyle)}`);
|
|
61
|
+
console.log(`${chalk.bold('Docker:')} ${chalk.cyan(config.docker ? 'Yes' : 'No')}`);
|
|
62
|
+
console.log(`${chalk.bold('Multi-Tenant:')} ${chalk.cyan(config.multiTenant ? 'Yes' : 'No')}`);
|
|
63
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
67
64
|
console.log('');
|
|
68
65
|
// Generate project
|
|
69
|
-
await
|
|
66
|
+
await generateProject(config, targetDir);
|
|
70
67
|
// Success message
|
|
71
68
|
console.log('');
|
|
72
|
-
|
|
73
|
-
console.log(
|
|
74
|
-
console.log(
|
|
69
|
+
logger.success(chalk.bold('🎉 Project created successfully!\n'));
|
|
70
|
+
console.log(chalk.bold('Next steps:\n'));
|
|
71
|
+
console.log(chalk.cyan(` cd ${projectName}`));
|
|
75
72
|
if (config.skipInstall) {
|
|
76
|
-
console.log(
|
|
73
|
+
console.log(chalk.cyan(' npm install'));
|
|
77
74
|
}
|
|
78
|
-
console.log(
|
|
79
|
-
console.log(
|
|
80
|
-
console.log(
|
|
81
|
-
console.log(
|
|
82
|
-
console.log(
|
|
75
|
+
console.log(chalk.cyan(' npm run dev\n'));
|
|
76
|
+
console.log(chalk.gray('For more information, check out the README.md in your project.\n'));
|
|
77
|
+
console.log(chalk.bold('Built by Sumit Chauhan'));
|
|
78
|
+
console.log(chalk.gray('GitHub: https://github.com/halloffame12'));
|
|
79
|
+
console.log(chalk.gray('LinkedIn: https://www.linkedin.com/in/sumit-chauhan-a4ba98325/\n'));
|
|
83
80
|
}
|
|
84
81
|
catch (error) {
|
|
85
|
-
|
|
82
|
+
logger.error('Failed to create project');
|
|
86
83
|
console.error(error);
|
|
87
84
|
process.exit(1);
|
|
88
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,UAAU,CAAC,oBAAoB,CAAwB,CAAC;AAEzF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,OAAgC;IACrF,IAAI,CAAC;QACD,yBAAyB;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,8BAA8B,WAAW,UAAU,CAAC,CAAC,CAAC;QAClF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;QAE5E,oCAAoC;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;QAC3D,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAEnD,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,KAAK,CAAC,cAAc,WAAW,mBAAmB,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC;YACD,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YAC9B,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACL,MAAM,CAAC,KAAK,CAAC,kDAAkD,SAAS,IAAI,CAAC,CAAC;YAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAED,iCAAiC;QACjC,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;QAEhE,yBAAyB;QACzB,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAE/C,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9E,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAED,yBAAyB;QACzB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1F,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,mBAAmB;QACnB,MAAM,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAEzC,kBAAkB;QAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC;QAEjE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,WAAW,EAAE,CAAC,CAAC,CAAC;QAC/C,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAE3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC,CAAC;QAC5F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC,CAAC;IAEhG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACzC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC"}
|
package/dist/generators/api.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { StackConfig } from '../types';
|
|
1
|
+
import { StackConfig } from '../types.js';
|
|
2
2
|
export declare function generateGraphQL(config: StackConfig, backendDir: string): Promise<void>;
|
|
3
3
|
export declare function generateTRPC(config: StackConfig, backendDir: string, frontendDir: string): Promise<void>;
|
package/dist/generators/api.js
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateGraphQL = generateGraphQL;
|
|
7
|
-
exports.generateTRPC = generateTRPC;
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
-
async function generateGraphQL(config, backendDir) {
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
export async function generateGraphQL(config, backendDir) {
|
|
11
4
|
if (config.backend === 'express') {
|
|
12
5
|
await generateExpressGraphQL(config, backendDir);
|
|
13
6
|
}
|
|
@@ -17,16 +10,16 @@ async function generateGraphQL(config, backendDir) {
|
|
|
17
10
|
}
|
|
18
11
|
async function generateExpressGraphQL(config, backendDir) {
|
|
19
12
|
// Update package.json
|
|
20
|
-
const packageJson = await
|
|
13
|
+
const packageJson = await fs.readJSON(path.join(backendDir, 'package.json'));
|
|
21
14
|
packageJson.dependencies['graphql'] = '^16.8.1';
|
|
22
15
|
packageJson.dependencies['@apollo/server'] = '^4.10.0';
|
|
23
16
|
packageJson.dependencies['@graphql-tools/schema'] = '^10.0.2';
|
|
24
|
-
await
|
|
17
|
+
await fs.writeJSON(path.join(backendDir, 'package.json'), packageJson, { spaces: 2 });
|
|
25
18
|
// Create GraphQL directory
|
|
26
|
-
const graphqlDir =
|
|
27
|
-
await
|
|
28
|
-
await
|
|
29
|
-
await
|
|
19
|
+
const graphqlDir = path.join(backendDir, 'src', 'graphql');
|
|
20
|
+
await fs.ensureDir(graphqlDir);
|
|
21
|
+
await fs.ensureDir(path.join(graphqlDir, 'resolvers'));
|
|
22
|
+
await fs.ensureDir(path.join(graphqlDir, 'types'));
|
|
30
23
|
// Schema
|
|
31
24
|
const schema = `import { gql } from 'graphql-tag';
|
|
32
25
|
|
|
@@ -54,7 +47,7 @@ export const typeDefs = gql\`
|
|
|
54
47
|
}
|
|
55
48
|
\`;
|
|
56
49
|
`;
|
|
57
|
-
await
|
|
50
|
+
await fs.writeFile(path.join(graphqlDir, 'schema.ts'), schema);
|
|
58
51
|
// Resolvers
|
|
59
52
|
const resolvers = `import bcrypt from 'bcrypt';
|
|
60
53
|
import jwt from 'jsonwebtoken';
|
|
@@ -136,7 +129,7 @@ export const resolvers = {
|
|
|
136
129
|
},
|
|
137
130
|
};
|
|
138
131
|
`;
|
|
139
|
-
await
|
|
132
|
+
await fs.writeFile(path.join(graphqlDir, 'resolvers', 'index.ts'), resolvers);
|
|
140
133
|
// Apollo Server setup
|
|
141
134
|
const apolloSetup = `import { ApolloServer } from '@apollo/server';
|
|
142
135
|
import { expressMiddleware } from '@apollo/server/express4';
|
|
@@ -170,16 +163,16 @@ export async function createApolloServer() {
|
|
|
170
163
|
});
|
|
171
164
|
}
|
|
172
165
|
`;
|
|
173
|
-
await
|
|
166
|
+
await fs.writeFile(path.join(graphqlDir, 'server.ts'), apolloSetup);
|
|
174
167
|
}
|
|
175
168
|
async function generateNestJSGraphQL(config, backendDir) {
|
|
176
169
|
// Update package.json
|
|
177
|
-
const packageJson = await
|
|
170
|
+
const packageJson = await fs.readJSON(path.join(backendDir, 'package.json'));
|
|
178
171
|
packageJson.dependencies['@nestjs/graphql'] = '^12.0.11';
|
|
179
172
|
packageJson.dependencies['@nestjs/apollo'] = '^12.0.11';
|
|
180
173
|
packageJson.dependencies['@apollo/server'] = '^4.10.0';
|
|
181
174
|
packageJson.dependencies['graphql'] = '^16.8.1';
|
|
182
|
-
await
|
|
175
|
+
await fs.writeJSON(path.join(backendDir, 'package.json'), packageJson, { spaces: 2 });
|
|
183
176
|
// GraphQL module
|
|
184
177
|
const graphqlModule = `import { Module } from '@nestjs/common';
|
|
185
178
|
import { GraphQLModule } from '@nestjs/graphql';
|
|
@@ -199,7 +192,7 @@ import { join } from 'path';
|
|
|
199
192
|
})
|
|
200
193
|
export class GraphqlModule {}
|
|
201
194
|
`;
|
|
202
|
-
await
|
|
195
|
+
await fs.writeFile(path.join(backendDir, 'src', 'graphql.module.ts'), graphqlModule);
|
|
203
196
|
// User resolver
|
|
204
197
|
const userResolver = `import { Resolver, Query, Mutation, Args } from '@nestjs/graphql';
|
|
205
198
|
import { UseGuards } from '@nestjs/common';
|
|
@@ -238,11 +231,11 @@ export class UserResolver {
|
|
|
238
231
|
}
|
|
239
232
|
}
|
|
240
233
|
`;
|
|
241
|
-
await
|
|
234
|
+
await fs.writeFile(path.join(backendDir, 'src', 'users', 'users.resolver.ts'), userResolver);
|
|
242
235
|
}
|
|
243
|
-
async function generateTRPC(config, backendDir, frontendDir) {
|
|
236
|
+
export async function generateTRPC(config, backendDir, frontendDir) {
|
|
244
237
|
// Backend setup
|
|
245
|
-
const packageJson = await
|
|
238
|
+
const packageJson = await fs.readJSON(path.join(backendDir, 'package.json'));
|
|
246
239
|
packageJson.dependencies['@trpc/server'] = '^10.45.0';
|
|
247
240
|
packageJson.dependencies['zod'] = '^3.22.4';
|
|
248
241
|
// Add auth dependencies - tRPC auth router always uses bcryptjs/jwt
|
|
@@ -252,11 +245,11 @@ async function generateTRPC(config, backendDir, frontendDir) {
|
|
|
252
245
|
packageJson.devDependencies = {};
|
|
253
246
|
packageJson.devDependencies['@types/bcryptjs'] = '^2.4.6';
|
|
254
247
|
packageJson.devDependencies['@types/jsonwebtoken'] = '^9.0.7';
|
|
255
|
-
await
|
|
248
|
+
await fs.writeJSON(path.join(backendDir, 'package.json'), packageJson, { spaces: 2 });
|
|
256
249
|
// tRPC router
|
|
257
|
-
const trpcDir =
|
|
258
|
-
await
|
|
259
|
-
await
|
|
250
|
+
const trpcDir = path.join(backendDir, 'src', 'trpc');
|
|
251
|
+
await fs.ensureDir(trpcDir);
|
|
252
|
+
await fs.ensureDir(path.join(trpcDir, 'routers'));
|
|
260
253
|
const trpcSetup = `import { initTRPC } from '@trpc/server';
|
|
261
254
|
import { z } from 'zod';
|
|
262
255
|
|
|
@@ -265,7 +258,7 @@ const t = initTRPC.create();
|
|
|
265
258
|
export const router = t.router;
|
|
266
259
|
export const publicProcedure = t.procedure;
|
|
267
260
|
`;
|
|
268
|
-
await
|
|
261
|
+
await fs.writeFile(path.join(trpcDir, 'trpc.ts'), trpcSetup);
|
|
269
262
|
const authRouter = `import { router, publicProcedure } from '../trpc.js';
|
|
270
263
|
import { z } from 'zod';
|
|
271
264
|
import bcrypt from 'bcryptjs';
|
|
@@ -336,22 +329,22 @@ export const authRouter = router({
|
|
|
336
329
|
}),
|
|
337
330
|
});
|
|
338
331
|
`;
|
|
339
|
-
await
|
|
332
|
+
await fs.writeFile(path.join(trpcDir, 'routers', 'auth.ts'), authRouter);
|
|
340
333
|
// Frontend tRPC client
|
|
341
|
-
const frontendPackageJson = await
|
|
334
|
+
const frontendPackageJson = await fs.readJSON(path.join(frontendDir, 'package.json'));
|
|
342
335
|
frontendPackageJson.dependencies['@trpc/client'] = '^10.45.0';
|
|
343
336
|
frontendPackageJson.dependencies['@trpc/react-query'] = '^10.45.0';
|
|
344
337
|
frontendPackageJson.dependencies['@tanstack/react-query'] = '^4.36.1';
|
|
345
|
-
await
|
|
338
|
+
await fs.writeJSON(path.join(frontendDir, 'package.json'), frontendPackageJson, { spaces: 2 });
|
|
346
339
|
const isNext = config.frontend === 'nextjs';
|
|
347
|
-
const frontendLibDir =
|
|
348
|
-
await
|
|
340
|
+
const frontendLibDir = path.join(frontendDir, isNext ? 'lib' : 'src/lib');
|
|
341
|
+
await fs.ensureDir(frontendLibDir);
|
|
349
342
|
const relativePath = isNext ? '../../backend/src/trpc/routers' : '../../../backend/src/trpc/routers';
|
|
350
343
|
const trpcClient = `import { createTRPCReact } from '@trpc/react-query';
|
|
351
344
|
import type { AppRouter } from '${relativePath}';
|
|
352
345
|
|
|
353
346
|
export const trpc = createTRPCReact<AppRouter>();
|
|
354
347
|
`;
|
|
355
|
-
await
|
|
348
|
+
await fs.writeFile(path.join(frontendLibDir, 'trpc.ts'), trpcClient);
|
|
356
349
|
}
|
|
357
350
|
//# sourceMappingURL=api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/generators/api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/generators/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { StackConfig } from '../types';
|
|
1
|
+
import { StackConfig } from '../types.js';
|
|
2
2
|
export declare function generateAuth(config: StackConfig, frontendDir: string, backendDir: string): Promise<void>;
|
package/dist/generators/auth.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateAuth = generateAuth;
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
-
async function generateAuth(config, frontendDir, backendDir) {
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
export async function generateAuth(config, frontendDir, backendDir) {
|
|
10
4
|
switch (config.auth) {
|
|
11
5
|
case 'jwt':
|
|
12
6
|
await generateJWTAuth(config, frontendDir, backendDir);
|
|
@@ -32,14 +26,14 @@ async function generateAuth(config, frontendDir, backendDir) {
|
|
|
32
26
|
async function generateJWTAuth(config, _frontendDir, backendDir) {
|
|
33
27
|
// Backend: Auth logic
|
|
34
28
|
if (config.backend === 'express') {
|
|
35
|
-
const routesDir =
|
|
36
|
-
await
|
|
37
|
-
await
|
|
29
|
+
const routesDir = path.join(backendDir, 'src', 'routes');
|
|
30
|
+
await fs.ensureDir(routesDir);
|
|
31
|
+
await fs.writeFile(path.join(routesDir, 'auth.ts'), getExpressAuthRoutes(config));
|
|
38
32
|
}
|
|
39
33
|
else if (config.backend === 'fastify') {
|
|
40
|
-
const routesDir =
|
|
41
|
-
await
|
|
42
|
-
await
|
|
34
|
+
const routesDir = path.join(backendDir, 'src', 'routes');
|
|
35
|
+
await fs.ensureDir(routesDir);
|
|
36
|
+
await fs.writeFile(path.join(routesDir, 'auth.ts'), getFastifyAuthRoutes(config));
|
|
43
37
|
}
|
|
44
38
|
else if (config.backend === 'nestjs') {
|
|
45
39
|
await generateNestJSAuth(config, backendDir);
|
|
@@ -50,33 +44,33 @@ async function generateJWTAuth(config, _frontendDir, backendDir) {
|
|
|
50
44
|
extends: ["eslint:recommended"],
|
|
51
45
|
env: { node: true, es2021: true }
|
|
52
46
|
};
|
|
53
|
-
await
|
|
47
|
+
await fs.writeJSON(path.join(backendDir, '.eslintrc.json'), eslintConfig, { spaces: 2 });
|
|
54
48
|
}
|
|
55
49
|
async function generateFrontendAuthPages(config, frontendDir) {
|
|
56
50
|
const isNext = config.frontend === 'nextjs';
|
|
57
|
-
const frontendLibDir =
|
|
58
|
-
await
|
|
51
|
+
const frontendLibDir = path.join(frontendDir, isNext ? 'app/lib' : 'src/lib');
|
|
52
|
+
await fs.ensureDir(frontendLibDir);
|
|
59
53
|
// Always generate auth context file for JWT-based auth
|
|
60
|
-
await
|
|
54
|
+
await fs.writeFile(path.join(frontendLibDir, 'auth.tsx'), getAuthContextCode());
|
|
61
55
|
if (isNext) {
|
|
62
56
|
const nextEslint = {
|
|
63
57
|
root: true,
|
|
64
58
|
extends: ["next/core-web-vitals"]
|
|
65
59
|
};
|
|
66
|
-
await
|
|
67
|
-
const authAppDir =
|
|
68
|
-
await
|
|
69
|
-
await
|
|
70
|
-
await
|
|
71
|
-
await
|
|
72
|
-
await
|
|
60
|
+
await fs.writeJSON(path.join(frontendDir, '.eslintrc.json'), nextEslint, { spaces: 2 });
|
|
61
|
+
const authAppDir = path.join(frontendDir, 'app');
|
|
62
|
+
await fs.ensureDir(path.join(authAppDir, 'login'));
|
|
63
|
+
await fs.ensureDir(path.join(authAppDir, 'dashboard'));
|
|
64
|
+
await fs.writeFile(path.join(authAppDir, 'login', 'page.tsx'), getLoginPageCode(config));
|
|
65
|
+
await fs.writeFile(path.join(authAppDir, 'dashboard', 'page.tsx'), getDashboardPageCode(config));
|
|
66
|
+
await fs.writeFile(path.join(authAppDir, 'page.tsx'), getHomePageCode(config));
|
|
73
67
|
}
|
|
74
68
|
else {
|
|
75
|
-
const pagesDir =
|
|
76
|
-
await
|
|
77
|
-
await
|
|
78
|
-
await
|
|
79
|
-
await
|
|
69
|
+
const pagesDir = path.join(frontendDir, 'src', 'pages');
|
|
70
|
+
await fs.ensureDir(pagesDir);
|
|
71
|
+
await fs.writeFile(path.join(pagesDir, 'LoginPage.tsx'), getLoginPageCode(config));
|
|
72
|
+
await fs.writeFile(path.join(pagesDir, 'HomePage.tsx'), getHomePageCode(config));
|
|
73
|
+
await fs.writeFile(path.join(pagesDir, 'DashboardPage.tsx'), getDashboardPageCode(config));
|
|
80
74
|
}
|
|
81
75
|
}
|
|
82
76
|
function getExpressAuthRoutes(config) {
|
|
@@ -117,7 +111,7 @@ router.post('/login', async (req, res, next) => {
|
|
|
117
111
|
export default router;
|
|
118
112
|
`;
|
|
119
113
|
}
|
|
120
|
-
function getFastifyAuthRoutes(
|
|
114
|
+
function getFastifyAuthRoutes(_config) {
|
|
121
115
|
return `import { FastifyInstance } from 'fastify';
|
|
122
116
|
import bcrypt from 'bcrypt';
|
|
123
117
|
|
|
@@ -131,10 +125,10 @@ export default async function authRoutes(fastify: FastifyInstance) {
|
|
|
131
125
|
}
|
|
132
126
|
`;
|
|
133
127
|
}
|
|
134
|
-
async function generateNestJSAuth(
|
|
135
|
-
const authDir =
|
|
136
|
-
await
|
|
137
|
-
await
|
|
128
|
+
async function generateNestJSAuth(_config, backendDir) {
|
|
129
|
+
const authDir = path.join(backendDir, 'src', 'auth');
|
|
130
|
+
await fs.ensureDir(authDir);
|
|
131
|
+
await fs.ensureDir(path.join(authDir, 'dto'));
|
|
138
132
|
const controller = `import { Controller, Post, Body } from '@nestjs/common';
|
|
139
133
|
import { AuthService } from './auth.service';
|
|
140
134
|
import { RegisterDto, LoginDto } from './dto/auth.dto';
|
|
@@ -148,7 +142,7 @@ export class AuthController {
|
|
|
148
142
|
async login(@Body() dto: LoginDto) { return this.authService.login(dto); }
|
|
149
143
|
}
|
|
150
144
|
`;
|
|
151
|
-
await
|
|
145
|
+
await fs.writeFile(path.join(authDir, 'auth.controller.ts'), controller);
|
|
152
146
|
const dto = `import { IsEmail, IsString, MinLength } from 'class-validator';
|
|
153
147
|
export class RegisterDto {
|
|
154
148
|
@IsEmail()
|
|
@@ -166,7 +160,7 @@ export class LoginDto {
|
|
|
166
160
|
password!: string;
|
|
167
161
|
}
|
|
168
162
|
`;
|
|
169
|
-
await
|
|
163
|
+
await fs.writeFile(path.join(authDir, 'dto/auth.dto.ts'), dto);
|
|
170
164
|
const service = `import { Injectable } from '@nestjs/common';
|
|
171
165
|
import { JwtService } from '@nestjs/jwt';
|
|
172
166
|
|
|
@@ -177,7 +171,7 @@ export class AuthService {
|
|
|
177
171
|
async login(user: any) { return { token: this.jwtService.sign({ id: '1' }) }; }
|
|
178
172
|
}
|
|
179
173
|
`;
|
|
180
|
-
await
|
|
174
|
+
await fs.writeFile(path.join(authDir, 'auth.service.ts'), service);
|
|
181
175
|
}
|
|
182
176
|
function getAuthContextCode() {
|
|
183
177
|
return `'use client';
|
|
@@ -276,15 +270,15 @@ export default function DashboardPage() {
|
|
|
276
270
|
`;
|
|
277
271
|
}
|
|
278
272
|
async function generateClerkAuth(config, frontendDir, _backendDir) {
|
|
279
|
-
await
|
|
273
|
+
await fs.writeFile(path.join(frontendDir, 'CLERK_SETUP.md'), '# Clerk Setup');
|
|
280
274
|
}
|
|
281
275
|
async function generateSupabaseAuth(config, frontendDir, _backendDir) {
|
|
282
|
-
await
|
|
276
|
+
await fs.writeFile(path.join(frontendDir, 'SUPABASE_SETUP.md'), '# Supabase Setup');
|
|
283
277
|
}
|
|
284
278
|
async function generateAuthJS(config, frontendDir, _backendDir) {
|
|
285
|
-
await
|
|
279
|
+
await fs.writeFile(path.join(frontendDir, 'AUTHJS_SETUP.md'), '# Auth.js Setup');
|
|
286
280
|
}
|
|
287
281
|
async function generateFirebaseAuth(config, frontendDir, _backendDir) {
|
|
288
|
-
await
|
|
282
|
+
await fs.writeFile(path.join(frontendDir, 'FIREBASE_SETUP.md'), '# Firebase Setup');
|
|
289
283
|
}
|
|
290
284
|
//# sourceMappingURL=auth.js.map
|