@exanderal/stackcraft 0.2.0 → 0.2.1

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
@@ -19,87 +19,138 @@ your-project/
19
19
  ├── apps/
20
20
  │ ├── backend/ # NestJS REST or GraphQL API
21
21
  │ └── web/ # Vite + React or Next.js
22
- ├── packages/ # shared code
22
+ ├── packages/
23
+ │ └── types/ # auto-generated types shared across all apps
23
24
  └── tools/
24
25
  └── generators/ # local Nx code generators
25
26
  ```
26
27
 
27
28
  ### Backend (`apps/backend`)
28
29
 
29
- Choose between REST or GraphQL at setup time — both use the same underlying structure:
30
+ Choose between REST or GraphQL at setup — both share the same structure:
30
31
 
31
32
  ```
32
33
  src/
33
- ├── modules/ # domain layer — model, repository, service, module
34
- ├── api/ # REST controllers (REST only)
35
- ├── resolvers/ # GraphQL resolvers (GraphQL only)
36
- └── common/ # shared base classes
34
+ ├── modules/ # domain layer — model, repository, service, module
35
+ ├── api/ # REST controllers
36
+ ├── resolvers/ # GraphQL resolvers
37
+ └── common/ # shared base classes (EntityRepository, EntityService)
37
38
  ```
38
39
 
39
40
  - NestJS with TypeORM
40
41
  - PostgreSQL or MySQL
41
42
  - `EntityRepository` and `EntityService` base classes — extend them for each module
42
43
  - UUID primary keys
44
+ - REST: Swagger UI at `/api`, spec written to `swagger.json` on startup
45
+ - GraphQL: schema auto-generated to `schema.gql` on startup (code-first)
43
46
 
44
47
  ### Frontend (`apps/web`)
45
48
 
46
49
  - Vite + React or Next.js
47
50
  - Tailwind CSS v4
48
51
  - TypeScript
52
+ - GraphQL projects: Apollo Client pre-configured, `ApolloProvider` already wired at the app root
53
+
54
+ ### Types (`packages/types`)
55
+
56
+ Auto-generated TypeScript types shared across all apps — import from `@local/types/rest` or `@local/types/graphql`:
57
+
58
+ - REST → generated from `swagger.json` via `@hey-api/openapi-ts`
59
+ - GraphQL → generated from `schema.gql` + your `.graphql` operation files via `@graphql-codegen/cli`, outputs typed Apollo hooks
49
60
 
50
61
  ## Running the project
51
62
 
52
63
  ```sh
53
- pnpm dev # start all apps in parallel
54
- pnpm build # build all apps
55
- pnpm test # run all tests
56
- pnpm lint # lint all apps
64
+ pnpm dev # start all apps in parallel
65
+ pnpm build # build all apps
66
+ pnpm test # run all tests
67
+ pnpm lint # lint all apps
57
68
  ```
58
69
 
59
- Target a specific app:
70
+ ```sh
71
+ pnpm codegen # generate types once
72
+ pnpm codegen:watch # watch for schema/spec changes and regenerate automatically
73
+ ```
74
+
75
+ Typical dev workflow — run both in parallel:
60
76
 
61
77
  ```sh
62
- pnpm nx run backend:dev
63
- pnpm nx run web:dev
78
+ # terminal 1
79
+ pnpm dev
80
+
81
+ # terminal 2
82
+ pnpm codegen:watch
64
83
  ```
65
84
 
66
- ## Code generation
85
+ ## Code generators
67
86
 
68
- Generate a new domain module:
87
+ Generate a new domain module (model + repository + service):
69
88
 
70
89
  ```sh
71
90
  pnpm generate:module --name=trainer
72
- # add --graphql to include @ObjectType() on the model
73
- pnpm generate:module --name=trainer --graphql
91
+ pnpm generate:module --name=trainer --graphql # adds @ObjectType() to the model
74
92
  ```
75
93
 
76
- Generate a REST controller for an existing module:
94
+ Generate a REST controller:
77
95
 
78
96
  ```sh
79
97
  pnpm generate:controller --name=trainer
80
- # creates apps/backend/src/api/trainer/trainer.controller.ts
98
+ # apps/backend/src/api/trainer/trainer.controller.ts
81
99
  ```
82
100
 
83
- Generate a GraphQL resolver for an existing module:
101
+ Generate a GraphQL resolver:
84
102
 
85
103
  ```sh
86
104
  pnpm generate:resolver --name=trainer
87
- # creates apps/backend/src/resolvers/trainer/trainer.resolver.ts
105
+ # apps/backend/src/resolvers/trainer/trainer.resolver.ts
106
+ ```
107
+
108
+ ## Using generated types
109
+
110
+ **REST** — import types directly:
111
+
112
+ ```ts
113
+ import type { Trainer } from '@local/types/rest'
114
+ ```
115
+
116
+ **GraphQL** — write `.graphql` files in `apps/web/src/graphql/`, run `pnpm codegen`, then use the generated hooks:
117
+
118
+ ```ts
119
+ // apps/web/src/graphql/trainer.graphql
120
+ query GetTrainers {
121
+ trainers { id createdAt updatedAt }
122
+ }
123
+ ```
124
+
125
+ ```ts
126
+ import { useGetTrainersQuery } from '@local/types/graphql'
127
+
128
+ const { data, loading } = useGetTrainersQuery()
88
129
  ```
89
130
 
90
131
  ## Stack
91
132
 
92
- - **Monorepo** Nx
93
- - **Package manager** — pnpm or npm
94
- - **Backend** NestJS, TypeORM, PostgreSQL/MySQL
95
- - **Frontend** Vite + React or Next.js, Tailwind CSS v4
133
+ | Layer | Technology |
134
+ |---|---|
135
+ | Monorepo | Nx |
136
+ | Package manager | pnpm or npm |
137
+ | Backend | NestJS, TypeORM |
138
+ | Database | PostgreSQL or MySQL |
139
+ | Frontend | Vite + React or Next.js |
140
+ | Styles | Tailwind CSS v4 |
141
+ | GraphQL client | Apollo Client |
142
+ | REST types | @hey-api/openapi-ts |
143
+ | GraphQL types + hooks | @graphql-codegen/cli |
96
144
 
97
145
  ## Roadmap
98
146
 
99
- - [x] NestJS REST API
100
- - [x] NestJS GraphQL API
147
+ - [x] NestJS REST API with Swagger
148
+ - [x] NestJS GraphQL API (code-first)
101
149
  - [x] Module, controller, and resolver generators
102
- - [ ] GraphQL codegen pipeline
150
+ - [x] Auto-generated types in `packages/types`
151
+ - [x] `codegen:watch` for live type generation during dev
152
+ - [x] Apollo Client pre-configured in GraphQL projects
153
+ - [x] Typed Apollo hooks from `.graphql` operation files
103
154
  - [ ] Expo mobile
104
155
  - [ ] `stackcraft add` addon system (auth, Supabase, etc.)
105
156
  - [ ] Presets and `--config` for non-interactive use
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAMA,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,iBAqBlF"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAOA,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,iBAwBlF"}
@@ -4,6 +4,7 @@ import { scaffoldNestjsRest } from './scaffolders/api-nestjs-rest.js';
4
4
  import { scaffoldBase } from './scaffolders/base.js';
5
5
  import { scaffoldNextjs } from './scaffolders/web-nextjs.js';
6
6
  import { scaffoldVite } from './scaffolders/web-vite.js';
7
+ import { wireClientIntegration } from './scaffolders/wire-client.js';
7
8
  export async function scaffold(config, onStep) {
8
9
  onStep('Creating workspace...');
9
10
  await scaffoldBase(config);
@@ -22,6 +23,8 @@ export async function scaffold(config, onStep) {
22
23
  onStep('Adding Next.js app...');
23
24
  await scaffoldNextjs(config);
24
25
  }
26
+ onStep('Wiring client integration...');
27
+ await wireClientIntegration(config);
25
28
  onStep('Installing dependencies...');
26
29
  await execa(config.packageManager, ['install'], { cwd: config.targetDir });
27
30
  }
@@ -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,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAGxD,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,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,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,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 +1 @@
1
- {"version":3,"file":"api-nestjs-graphql.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-graphql.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAWhD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,aAAa,iBAahE"}
1
+ {"version":3,"file":"api-nestjs-graphql.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-graphql.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAWhD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,aAAa,iBAchE"}
@@ -18,6 +18,7 @@ export async function scaffoldNestjsGraphql(config) {
18
18
  dbPort: db.port,
19
19
  });
20
20
  await injectDbDriver(appDir, db);
21
+ await setupGraphqlCodegen(config.targetDir);
21
22
  }
22
23
  async function injectDbDriver(appDir, db) {
23
24
  const pkgPath = join(appDir, 'package.json');
@@ -28,4 +29,16 @@ async function injectDbDriver(appDir, db) {
28
29
  }
29
30
  await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
30
31
  }
32
+ async function setupGraphqlCodegen(targetDir) {
33
+ const typesDir = join(targetDir, 'packages', 'types');
34
+ await copyTemplate(join(TEMPLATES_DIR, 'types-graphql'), typesDir, {});
35
+ const pkgPath = join(typesDir, 'package.json');
36
+ const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));
37
+ pkg.devDependencies['@graphql-codegen/cli'] = '^5.0.0';
38
+ pkg.devDependencies['@graphql-codegen/typescript'] = '^4.0.0';
39
+ pkg.devDependencies['@graphql-codegen/typescript-operations'] = '^4.0.0';
40
+ pkg.devDependencies['@graphql-codegen/typescript-react-apollo'] = '^4.0.0';
41
+ pkg.devDependencies['@parcel/watcher'] = '^2.0.0';
42
+ await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
43
+ }
31
44
  //# sourceMappingURL=api-nestjs-graphql.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-nestjs-graphql.js","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;AAEpE,MAAM,SAAS,GAAG;IAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE;IACtI,KAAK,EAAK,EAAE,IAAI,EAAE,OAAO,EAAK,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE;CACvH,CAAA;AAEV,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAqB;IAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;IACxD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAExC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAErC,MAAM,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,EAAE,MAAM,EAAE;QACpE,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,MAAM,EAAE,EAAE,CAAC,IAAI;QACf,MAAM,EAAE,EAAE,CAAC,IAAI;KAChB,CAAC,CAAA;IAEF,MAAM,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AAClC,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,EAA4C;IACxF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAExD,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,CAAA;IAE9C,IAAI,EAAE,CAAC,YAAY,EAAE,CAAC;QACpB,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,YAAY,CAAA;IACxD,CAAC;IAED,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAA;AACxE,CAAC"}
1
+ {"version":3,"file":"api-nestjs-graphql.js","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;AAEpE,MAAM,SAAS,GAAG;IAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE;IACtI,KAAK,EAAK,EAAE,IAAI,EAAE,OAAO,EAAK,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE;CACvH,CAAA;AAEV,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAqB;IAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;IACxD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAExC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAErC,MAAM,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,EAAE,MAAM,EAAE;QACpE,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,MAAM,EAAE,EAAE,CAAC,IAAI;QACf,MAAM,EAAE,EAAE,CAAC,IAAI;KAChB,CAAC,CAAA;IAEF,MAAM,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAChC,MAAM,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;AAC7C,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,EAA4C;IACxF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAExD,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,CAAA;IAE9C,IAAI,EAAE,CAAC,YAAY,EAAE,CAAC;QACpB,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,YAAY,CAAA;IACxD,CAAC;IAED,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAA;AACxE,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,SAAiB;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IAErD,MAAM,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAA;IAEtE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAExD,GAAG,CAAC,eAAe,CAAC,sBAAsB,CAAC,GAAG,QAAQ,CAAA;IACtD,GAAG,CAAC,eAAe,CAAC,6BAA6B,CAAC,GAAG,QAAQ,CAAA;IAC7D,GAAG,CAAC,eAAe,CAAC,wCAAwC,CAAC,GAAG,QAAQ,CAAA;IACxE,GAAG,CAAC,eAAe,CAAC,0CAA0C,CAAC,GAAG,QAAQ,CAAA;IAC1E,GAAG,CAAC,eAAe,CAAC,iBAAiB,CAAC,GAAG,QAAQ,CAAA;IAEjD,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAA;AACxE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"api-nestjs-rest.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-rest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAWhD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,aAAa,iBAa7D"}
1
+ {"version":3,"file":"api-nestjs-rest.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-rest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAWhD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,aAAa,iBAc7D"}
@@ -1,4 +1,4 @@
1
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { copyTemplate } from './utils/copy.js';
@@ -18,6 +18,7 @@ export async function scaffoldNestjsRest(config) {
18
18
  dbPort: db.port,
19
19
  });
20
20
  await injectDbDriver(appDir, db);
21
+ await setupRestCodegen(config.targetDir);
21
22
  }
22
23
  async function injectDbDriver(appDir, db) {
23
24
  const pkgPath = join(appDir, 'package.json');
@@ -28,4 +29,13 @@ async function injectDbDriver(appDir, db) {
28
29
  }
29
30
  await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
30
31
  }
32
+ async function setupRestCodegen(targetDir) {
33
+ const typesDir = join(targetDir, 'packages', 'types');
34
+ await copyTemplate(join(TEMPLATES_DIR, 'types-rest'), typesDir, {});
35
+ const pkgPath = join(typesDir, 'package.json');
36
+ const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));
37
+ pkg.devDependencies['@hey-api/openapi-ts'] = '^0.64.0';
38
+ pkg.devDependencies['chokidar-cli'] = '^3.0.0';
39
+ await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
40
+ }
31
41
  //# sourceMappingURL=api-nestjs-rest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-nestjs-rest.js","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-rest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;AAEpE,MAAM,SAAS,GAAG;IAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE;IACtI,KAAK,EAAK,EAAE,IAAI,EAAE,OAAO,EAAK,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE;CACvH,CAAA;AAEV,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAqB;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;IACxD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAExC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAErC,MAAM,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,iBAAiB,CAAC,EAAE,MAAM,EAAE;QACjE,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,MAAM,EAAE,EAAE,CAAC,IAAI;QACf,MAAM,EAAE,EAAE,CAAC,IAAI;KAChB,CAAC,CAAA;IAEF,MAAM,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AAClC,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,EAA4C;IACxF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAExD,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,CAAA;IAE9C,IAAI,EAAE,CAAC,YAAY,EAAE,CAAC;QACpB,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,YAAY,CAAA;IACxD,CAAC;IAED,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAA;AACxE,CAAC"}
1
+ {"version":3,"file":"api-nestjs-rest.js","sourceRoot":"","sources":["../../../src/create/scaffolders/api-nestjs-rest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProjectConfig } from '../types.js';
2
+ export declare function wireClientIntegration(config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=wire-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-client.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/wire-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,aAAa,iBAehE"}
@@ -0,0 +1,77 @@
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ export async function wireClientIntegration(config) {
4
+ const webDir = join(config.targetDir, 'apps', 'web');
5
+ const webPkgPath = join(webDir, 'package.json');
6
+ const pkg = JSON.parse(await readFile(webPkgPath, 'utf-8'));
7
+ pkg.dependencies['@local/types'] = 'workspace:*';
8
+ if (config.backend === 'nestjs-graphql') {
9
+ pkg.dependencies['@apollo/client'] = '^3.13.0';
10
+ pkg.dependencies['graphql'] = '^16.0.0';
11
+ await writeFile(webPkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
12
+ await setupApolloClient(config, webDir);
13
+ }
14
+ else {
15
+ await writeFile(webPkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
16
+ }
17
+ }
18
+ async function setupApolloClient(config, webDir) {
19
+ await mkdir(join(webDir, 'src', 'lib'), { recursive: true });
20
+ await mkdir(join(webDir, 'src', 'graphql'), { recursive: true });
21
+ if (config.frontend === 'vite') {
22
+ await writeFile(join(webDir, 'src', 'lib', 'apollo.ts'), apolloViteClient(), 'utf-8');
23
+ await patchViteMain(webDir);
24
+ }
25
+ else if (config.frontend === 'nextjs') {
26
+ await writeFile(join(webDir, 'src', 'lib', 'apollo.ts'), apolloNextClient(), 'utf-8');
27
+ await writeFile(join(webDir, 'src', 'app', 'providers.tsx'), apolloNextProviders(), 'utf-8');
28
+ await patchNextLayout(webDir);
29
+ }
30
+ }
31
+ async function patchViteMain(webDir) {
32
+ const mainPath = join(webDir, 'src', 'main.tsx');
33
+ const content = await readFile(mainPath, 'utf-8');
34
+ const patched = content
35
+ .replace(`import { StrictMode } from 'react'`, `import { ApolloProvider } from '@apollo/client'\nimport { StrictMode } from 'react'\nimport { client } from './lib/apollo'`)
36
+ .replace(`<App />`, `<ApolloProvider client={client}>\n <App />\n </ApolloProvider>`);
37
+ await writeFile(mainPath, patched, 'utf-8');
38
+ }
39
+ async function patchNextLayout(webDir) {
40
+ const layoutPath = join(webDir, 'src', 'app', 'layout.tsx');
41
+ const content = await readFile(layoutPath, 'utf-8');
42
+ const patched = content
43
+ .replace(`import type { Metadata } from "next";`, `import type { Metadata } from "next";\nimport { Providers } from './providers';`)
44
+ .replace(`<body>`, `<body>\n <Providers>`)
45
+ .replace(`</body>`, `</Providers>\n </body>`);
46
+ await writeFile(layoutPath, patched, 'utf-8');
47
+ }
48
+ function apolloViteClient() {
49
+ return `import { ApolloClient, InMemoryCache } from '@apollo/client'
50
+
51
+ export const client = new ApolloClient({
52
+ uri: import.meta.env.VITE_API_URL ?? 'http://localhost:3000/graphql',
53
+ cache: new InMemoryCache(),
54
+ })
55
+ `;
56
+ }
57
+ function apolloNextClient() {
58
+ return `import { ApolloClient, InMemoryCache } from '@apollo/client'
59
+
60
+ export const client = new ApolloClient({
61
+ uri: process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:3000/graphql',
62
+ cache: new InMemoryCache(),
63
+ })
64
+ `;
65
+ }
66
+ function apolloNextProviders() {
67
+ return `'use client'
68
+
69
+ import { ApolloProvider } from '@apollo/client'
70
+ import { client } from '../lib/apollo'
71
+
72
+ export function Providers({ children }: { children: React.ReactNode }) {
73
+ return <ApolloProvider client={client}>{children}</ApolloProvider>
74
+ }
75
+ `;
76
+ }
77
+ //# sourceMappingURL=wire-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-client.js","sourceRoot":"","sources":["../../../src/create/scaffolders/wire-client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exanderal/stackcraft",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Opinionated full-stack project scaffolding CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,6 +25,7 @@
25
25
  "@nestjs/config": "^3.0.0",
26
26
  "@nestjs/core": "^11.0.1",
27
27
  "@nestjs/platform-express": "^11.0.1",
28
+ "@nestjs/swagger": "^11.0.0",
28
29
  "@nestjs/typeorm": "^10.0.0",
29
30
  "reflect-metadata": "^0.2.2",
30
31
  "rxjs": "^7.8.1",
@@ -1,8 +1,19 @@
1
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
1
2
  import { NestFactory } from '@nestjs/core';
3
+ import { writeFileSync } from 'node:fs';
2
4
  import { AppModule } from './app.module';
3
5
 
4
6
  async function bootstrap() {
5
7
  const app = await NestFactory.create(AppModule);
8
+
9
+ const config = new DocumentBuilder()
10
+ .setTitle('{{projectName}}')
11
+ .setVersion('1.0')
12
+ .build();
13
+ const document = SwaggerModule.createDocument(app, config);
14
+ SwaggerModule.setup('api', app, document);
15
+ writeFileSync('./swagger.json', JSON.stringify(document, null, 2));
16
+
6
17
  await app.listen(process.env.PORT ?? 3000);
7
18
  }
8
19
  bootstrap();
@@ -9,7 +9,9 @@
9
9
  "lint": "nx run-many -t lint",
10
10
  "generate:module": "nx g @local/generators:module",
11
11
  "generate:resolver": "nx g @local/generators:resolver",
12
- "generate:controller": "nx g @local/generators:controller"
12
+ "generate:controller": "nx g @local/generators:controller",
13
+ "codegen": "nx run types:codegen",
14
+ "codegen:watch": "nx run types:codegen:watch"
13
15
  },
14
16
  "devDependencies": {
15
17
  "@nx/devkit": "^20.0.0",
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "@local/types",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "exports": {
6
+ "./rest": "./src/rest/index.ts",
7
+ "./graphql": "./src/graphql/index.ts"
8
+ },
9
+ "devDependencies": {}
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "NodeNext",
4
+ "moduleResolution": "NodeNext",
5
+ "target": "ES2022",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true
9
+ }
10
+ }
@@ -0,0 +1,17 @@
1
+ import type { CodegenConfig } from '@graphql-codegen/cli';
2
+
3
+ const config: CodegenConfig = {
4
+ schema: '../../apps/backend/src/schema.gql',
5
+ documents: ['../../apps/web/src/**/*.graphql'],
6
+ generates: {
7
+ './src/graphql/index.ts': {
8
+ plugins: [
9
+ 'typescript',
10
+ 'typescript-operations',
11
+ 'typescript-react-apollo',
12
+ ],
13
+ },
14
+ },
15
+ };
16
+
17
+ export default config;
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "types",
3
+ "targets": {
4
+ "codegen": {
5
+ "executor": "nx:run-commands",
6
+ "options": {
7
+ "command": "graphql-codegen --config codegen.ts",
8
+ "cwd": "{projectRoot}"
9
+ }
10
+ },
11
+ "codegen:watch": {
12
+ "executor": "nx:run-commands",
13
+ "options": {
14
+ "command": "graphql-codegen --config codegen.ts --watch",
15
+ "cwd": "{projectRoot}"
16
+ }
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from '@hey-api/openapi-ts';
2
+
3
+ export default defineConfig({
4
+ input: '../../apps/backend/swagger.json',
5
+ output: {
6
+ path: './src/rest',
7
+ format: 'prettier',
8
+ },
9
+ plugins: ['@hey-api/typescript'],
10
+ });
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "types",
3
+ "targets": {
4
+ "codegen": {
5
+ "executor": "nx:run-commands",
6
+ "options": {
7
+ "command": "openapi-ts",
8
+ "cwd": "{projectRoot}"
9
+ }
10
+ },
11
+ "codegen:watch": {
12
+ "executor": "nx:run-commands",
13
+ "options": {
14
+ "command": "chokidar '../../apps/backend/swagger.json' --initial -c 'openapi-ts'",
15
+ "cwd": "{projectRoot}"
16
+ }
17
+ }
18
+ }
19
+ }