@exanderal/stackcraft 0.3.2 → 0.4.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.
package/README.md CHANGED
@@ -22,8 +22,9 @@ your-project/
22
22
  │ └── mobile/ # Expo (optional)
23
23
  ├── packages/
24
24
  │ └── types/ # auto-generated types shared across all apps
25
- └── tools/
26
- └── generators/ # local Nx code generators
25
+ ├── tools/
26
+ └── generators/ # local Nx code generators
27
+ └── docker-compose.yml # local database
27
28
  ```
28
29
 
29
30
  ### Backend (`apps/backend`)
@@ -44,6 +45,7 @@ src/
44
45
  - UUID primary keys
45
46
  - REST: Swagger UI at `/api`, spec written to `swagger.json` on startup
46
47
  - GraphQL: schema auto-generated to `schema.gql` on startup (code-first)
48
+ - `.env` pre-configured with local database credentials
47
49
 
48
50
  ### Frontend (`apps/web`)
49
51
 
@@ -51,6 +53,7 @@ src/
51
53
  - Tailwind CSS v4
52
54
  - TypeScript
53
55
  - GraphQL projects: Apollo Client pre-configured, `ApolloProvider` already wired at the app root
56
+ - `.env` pre-configured with `VITE_API_URL` / `NEXT_PUBLIC_API_URL`
54
57
 
55
58
  ### Mobile (`apps/mobile`) — optional
56
59
 
@@ -66,16 +69,26 @@ Auto-generated TypeScript types shared across all apps — import from `@local/t
66
69
  - REST → generated from `swagger.json` via `@hey-api/openapi-ts`
67
70
  - GraphQL → generated from `schema.gql` + your `.graphql` operation files via `@graphql-codegen/cli`, outputs typed Apollo hooks
68
71
 
69
- ## Running the project
72
+ ## Quick start
73
+
74
+ ```sh
75
+ pnpm db:start # start the local database (Docker)
76
+ pnpm install
77
+ pnpm dev
78
+ ```
79
+
80
+ Environment variables are pre-configured in each app's `.env` — no manual setup needed to get started locally.
81
+
82
+ ## Scripts
70
83
 
71
84
  ```sh
72
85
  pnpm dev # start all apps in parallel
73
86
  pnpm build # build all apps
74
87
  pnpm test # run all tests
75
88
  pnpm lint # lint all apps
76
- ```
77
-
78
- ```sh
89
+ pnpm db:start # start the local database
90
+ pnpm db:stop # stop the local database
91
+ pnpm db:logs # tail database logs
79
92
  pnpm codegen # generate types once
80
93
  pnpm codegen:watch # watch for schema/spec changes and regenerate automatically
81
94
  ```
@@ -152,6 +165,7 @@ const { data, loading } = useGetTrainersQuery()
152
165
  | GraphQL client | Apollo Client |
153
166
  | REST types | @hey-api/openapi-ts |
154
167
  | GraphQL types + hooks | @graphql-codegen/cli |
168
+ | Local database | Docker Compose |
155
169
 
156
170
  ## Roadmap
157
171
 
@@ -165,6 +179,7 @@ const { data, loading } = useGetTrainersQuery()
165
179
  - [x] Expo mobile with Expo Router
166
180
  - [x] Interactive `generate:module` prompt
167
181
  - [x] Biome as an alternative to ESLint + Prettier
182
+ - [x] Docker Compose for local database + per-app `.env` files
168
183
  - [ ] `stackcraft add` addon system (auth, Supabase, etc.)
169
184
  - [ ] Presets and `--config` for non-interactive use
170
185
 
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAsB,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,iBAgClF"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAsB,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,iBAmClF"}
@@ -3,6 +3,7 @@ import { scaffoldNestjsGraphql } from './scaffolders/api-nestjs-graphql.js';
3
3
  import { scaffoldNestjsRest } from './scaffolders/api-nestjs-rest.js';
4
4
  import { scaffoldBase } from './scaffolders/base.js';
5
5
  import { scaffoldExpo } from './scaffolders/mobile-expo.js';
6
+ import { setupDocker } from './scaffolders/setup-docker.js';
6
7
  import { setupLinter } from './scaffolders/setup-linter.js';
7
8
  import { scaffoldNextjs } from './scaffolders/web-nextjs.js';
8
9
  import { scaffoldVite } from './scaffolders/web-vite.js';
@@ -31,6 +32,8 @@ export async function scaffold(config, onStep) {
31
32
  }
32
33
  onStep('Configuring linter...');
33
34
  await setupLinter(config);
35
+ onStep('Setting up Docker and environment...');
36
+ await setupDocker(config);
34
37
  onStep('Wiring client integration...');
35
38
  await wireClientIntegration(config);
36
39
  onStep('Installing dependencies...');
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAGpE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAqB,EAAE,MAA6B;IACjF,MAAM,CAAC,uBAAuB,CAAC,CAAA;IAC/B,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAE1B,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAC3B,IAAI,MAAM,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;QACxC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;SAAM,CAAC;QACN,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC/B,MAAM,CAAC,4BAA4B,CAAC,CAAA;QACpC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;SAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,CAAC,uBAAuB,CAAC,CAAA;QAC/B,MAAM,cAAc,CAAC,MAAM,CAAC,CAAA;IAC9B,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC7B,MAAM,CAAC,2BAA2B,CAAC,CAAA;QACnC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;IAED,MAAM,CAAC,uBAAuB,CAAC,CAAA;IAC/B,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;IAEzB,MAAM,CAAC,8BAA8B,CAAC,CAAA;IACtC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;IAEnC,MAAM,CAAC,4BAA4B,CAAC,CAAA;IACpC,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;AAC5E,CAAC"}
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAGpE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAqB,EAAE,MAA6B;IACjF,MAAM,CAAC,uBAAuB,CAAC,CAAA;IAC/B,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAE1B,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAC3B,IAAI,MAAM,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;QACxC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;SAAM,CAAC;QACN,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC/B,MAAM,CAAC,4BAA4B,CAAC,CAAA;QACpC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;SAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,CAAC,uBAAuB,CAAC,CAAA;QAC/B,MAAM,cAAc,CAAC,MAAM,CAAC,CAAA;IAC9B,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC7B,MAAM,CAAC,2BAA2B,CAAC,CAAA;QACnC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;IAED,MAAM,CAAC,uBAAuB,CAAC,CAAA;IAC/B,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;IAEzB,MAAM,CAAC,sCAAsC,CAAC,CAAA;IAC9C,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;IAEzB,MAAM,CAAC,8BAA8B,CAAC,CAAA;IACtC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;IAEnC,MAAM,CAAC,4BAA4B,CAAC,CAAA;IACpC,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;AAC5E,CAAC"}
@@ -34,6 +34,8 @@ async function setupGraphqlCodegen(targetDir) {
34
34
  await copyTemplate(join(TEMPLATES_DIR, 'types-graphql'), typesDir, {});
35
35
  const pkgPath = join(typesDir, 'package.json');
36
36
  const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));
37
+ pkg.dependencies['@apollo/client'] = '^3.13.0';
38
+ pkg.dependencies['graphql'] = '^16.0.0';
37
39
  pkg.devDependencies['@graphql-codegen/cli'] = '^5.0.0';
38
40
  pkg.devDependencies['@graphql-codegen/typescript'] = '^4.0.0';
39
41
  pkg.devDependencies['@graphql-codegen/typescript-operations'] = '^4.0.0';
@@ -1 +1 @@
1
- {"version":3,"file":"api-nestjs-graphql.js","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-graphql.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-nestjs-graphql.js","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-graphql.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProjectConfig } from '../types.js';
2
+ export declare function setupDocker(config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=setup-docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-docker.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/setup-docker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAuChD,wBAAsB,WAAW,CAAC,MAAM,EAAE,aAAa,iBAMtD"}
@@ -0,0 +1,116 @@
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ const DB_DOCKER = {
4
+ postgres: {
5
+ image: 'postgres:17-alpine',
6
+ port: 5432,
7
+ env: {
8
+ POSTGRES_USER: 'postgres',
9
+ POSTGRES_PASSWORD: 'postgres',
10
+ },
11
+ healthcheck: `test: ['CMD-SHELL', 'pg_isready -U postgres']\n interval: 5s\n timeout: 5s\n retries: 5`,
12
+ envVars: {
13
+ DB_USER: 'postgres',
14
+ DB_PASSWORD: 'postgres',
15
+ DB_PORT: '5432',
16
+ },
17
+ },
18
+ mysql: {
19
+ image: 'mysql:8-lts',
20
+ port: 3306,
21
+ env: {
22
+ MYSQL_ROOT_PASSWORD: 'root',
23
+ MYSQL_USER: 'mysql',
24
+ MYSQL_PASSWORD: 'mysql',
25
+ },
26
+ healthcheck: `test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost']\n interval: 5s\n timeout: 5s\n retries: 10`,
27
+ envVars: {
28
+ DB_USER: 'mysql',
29
+ DB_PASSWORD: 'mysql',
30
+ DB_PORT: '3306',
31
+ },
32
+ },
33
+ };
34
+ const FRONTEND_API_VAR = {
35
+ vite: 'VITE_API_URL',
36
+ nextjs: 'NEXT_PUBLIC_API_URL',
37
+ };
38
+ export async function setupDocker(config) {
39
+ await writeDockerCompose(config);
40
+ await writeBackendEnv(config);
41
+ await writeFrontendEnv(config);
42
+ await addDbScripts(config);
43
+ await updateGitignore(config);
44
+ }
45
+ async function writeDockerCompose(config) {
46
+ const db = DB_DOCKER[config.database];
47
+ const dbName = config.projectName.replace(/-/g, '_');
48
+ const envLines = Object.entries(db.env)
49
+ .map(([k, v]) => ` ${k}: ${v}`)
50
+ .join('\n');
51
+ const volumeName = config.database === 'postgres' ? 'pgdata' : 'mysqldata';
52
+ const content = `services:
53
+ db:
54
+ image: ${db.image}
55
+ environment:
56
+ ${envLines}
57
+ ${config.database === 'postgres' ? 'POSTGRES_DB' : 'MYSQL_DATABASE'}: ${dbName}
58
+ ports:
59
+ - "${db.port}:${db.port}"
60
+ volumes:
61
+ - ${volumeName}:/var/lib/${config.database === 'postgres' ? 'postgresql/data' : 'mysql'}
62
+ healthcheck:
63
+ ${db.healthcheck}
64
+
65
+ volumes:
66
+ ${volumeName}:
67
+ `;
68
+ await writeFile(join(config.targetDir, 'docker-compose.yml'), content, 'utf-8');
69
+ }
70
+ async function writeBackendEnv(config) {
71
+ const db = DB_DOCKER[config.database];
72
+ const dbName = config.projectName.replace(/-/g, '_');
73
+ const backendDir = join(config.targetDir, 'apps', 'backend');
74
+ const lines = [
75
+ '# Database',
76
+ `DB_HOST=localhost`,
77
+ `DB_PORT=${db.envVars.DB_PORT}`,
78
+ `DB_USER=${db.envVars.DB_USER}`,
79
+ `DB_PASSWORD=${db.envVars.DB_PASSWORD}`,
80
+ `DB_NAME=${dbName}`,
81
+ '',
82
+ '# App',
83
+ 'PORT=3000',
84
+ 'NODE_ENV=development',
85
+ '',
86
+ ].join('\n');
87
+ await writeFile(join(backendDir, '.env'), lines, 'utf-8');
88
+ await writeFile(join(backendDir, '.env.example'), lines, 'utf-8');
89
+ }
90
+ async function writeFrontendEnv(config) {
91
+ const webDir = join(config.targetDir, 'apps', 'web');
92
+ const apiVar = FRONTEND_API_VAR[config.frontend];
93
+ const lines = [
94
+ '# API',
95
+ `${apiVar}=http://localhost:3000`,
96
+ '',
97
+ ].join('\n');
98
+ await writeFile(join(webDir, '.env'), lines, 'utf-8');
99
+ await writeFile(join(webDir, '.env.example'), lines, 'utf-8');
100
+ }
101
+ async function addDbScripts(config) {
102
+ const pkgPath = join(config.targetDir, 'package.json');
103
+ const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));
104
+ pkg.scripts['db:start'] = 'docker compose up -d';
105
+ pkg.scripts['db:stop'] = 'docker compose down';
106
+ pkg.scripts['db:logs'] = 'docker compose logs -f db';
107
+ await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
108
+ }
109
+ async function updateGitignore(config) {
110
+ const gitignorePath = join(config.targetDir, '.gitignore');
111
+ const content = await readFile(gitignorePath, 'utf-8');
112
+ if (!content.includes('.env')) {
113
+ await writeFile(gitignorePath, content + '\n# environment\n**/.env\n', 'utf-8');
114
+ }
115
+ }
116
+ //# sourceMappingURL=setup-docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-docker.js","sourceRoot":"","sources":["../../../src/create/scaffolders/setup-docker.ts"],"names":[],"mappings":"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"}
@@ -18,7 +18,7 @@ async function substituteVars(dir, vars) {
18
18
  if (entry.isDirectory()) {
19
19
  await substituteVars(fullPath, vars);
20
20
  }
21
- else if (isTextFile(entry.name)) {
21
+ else if (entry.isFile() && isTextFile(entry.name)) {
22
22
  let content = await readFile(fullPath, 'utf-8');
23
23
  for (const [key, value] of Object.entries(vars)) {
24
24
  content = content.replaceAll(`{{${key}}}`, value);
@@ -1 +1 @@
1
- {"version":3,"file":"copy.js","sourceRoot":"","sources":["../../../../src/create/scaffolders/utils/copy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK;IAC/B,OAAO,EAAE,MAAM,EAAE,MAAM;IACvB,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM;CACjD,CAAC,CAAA;AAEF,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IACtC,MAAM,GAAG,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACzD,OAAO,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;AACzD,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,GAAW,EAAE,IAA4B;IACrE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;IAE3D,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACtC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QACtC,CAAC;aAAM,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,IAAI,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,CAAC,CAAA;YACnD,CAAC;YACD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC,CAAC,CACH,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,IAAY,EACZ,IAA4B;IAE5B,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAClC,CAAC"}
1
+ {"version":3,"file":"copy.js","sourceRoot":"","sources":["../../../../src/create/scaffolders/utils/copy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK;IAC/B,OAAO,EAAE,MAAM,EAAE,MAAM;IACvB,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM;CACjD,CAAC,CAAA;AAEF,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IACtC,MAAM,GAAG,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACzD,OAAO,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;AACzD,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,GAAW,EAAE,IAA4B;IACrE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;IAE3D,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACtC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QACtC,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACpD,IAAI,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,CAAC,CAAA;YACnD,CAAC;YACD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC,CAAC,CACH,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,IAAY,EACZ,IAA4B;IAE5B,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAClC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exanderal/stackcraft",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Opinionated full-stack project scaffolding CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,50 @@
1
+ # {{projectName}}
2
+
3
+ ## Quick start
4
+
5
+ **1. Start the database**
6
+
7
+ ```sh
8
+ pnpm db:start
9
+ ```
10
+
11
+ **2. Install dependencies and start**
12
+
13
+ ```sh
14
+ pnpm install
15
+ pnpm dev
16
+ ```
17
+
18
+ Environment variables are pre-configured in `apps/backend/.env` and `apps/web/.env` with defaults that match the local Docker setup — no changes needed to get started.
19
+
20
+ ## Scripts
21
+
22
+ | Script | Description |
23
+ | -------------------- | ---------------------------------------- |
24
+ | `pnpm dev` | Start all apps in watch mode |
25
+ | `pnpm build` | Build all apps |
26
+ | `pnpm test` | Run all tests |
27
+ | `pnpm lint` | Lint all apps |
28
+ | `pnpm db:start` | Start the local database (Docker) |
29
+ | `pnpm db:stop` | Stop the local database |
30
+ | `pnpm db:logs` | Tail database logs |
31
+ | `pnpm codegen` | Generate types from schema |
32
+ | `pnpm codegen:watch` | Watch and regenerate types automatically |
33
+
34
+ ## Code generators
35
+
36
+ ```sh
37
+ pnpm generate:module --name=booking # domain module (model, repository, service)
38
+ pnpm generate:controller --name=booking # REST controller
39
+ pnpm generate:resolver --name=booking # GraphQL resolver
40
+ ```
41
+
42
+ ## Deploy to Railway
43
+
44
+ [![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/new)
45
+
46
+ 1. Push this project to a GitHub repository
47
+ 2. Go to [railway.com](https://railway.com) and create a new project from your repo
48
+ 3. Add a PostgreSQL (or MySQL) database service
49
+ 4. Set the environment variables from `.env.example` in the Railway dashboard
50
+ 5. Railway will build and deploy automatically on every push to your target branch, typically `main` or `master`
@@ -6,5 +6,6 @@
6
6
  "./rest": "./src/rest/index.ts",
7
7
  "./graphql": "./src/graphql/index.ts"
8
8
  },
9
+ "dependencies": {},
9
10
  "devDependencies": {}
10
11
  }