@codemcp/ade-core 0.0.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/.prettierignore +1 -0
- package/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-format.log +6 -0
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-test.log +21 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/LICENSE +21 -0
- package/dist/catalog/facets/architecture.d.ts +2 -0
- package/dist/catalog/facets/architecture.js +424 -0
- package/dist/catalog/facets/backpressure.d.ts +2 -0
- package/dist/catalog/facets/backpressure.js +123 -0
- package/dist/catalog/facets/practices.d.ts +2 -0
- package/dist/catalog/facets/practices.js +163 -0
- package/dist/catalog/facets/process.d.ts +2 -0
- package/dist/catalog/facets/process.js +47 -0
- package/dist/catalog/index.d.ts +14 -0
- package/dist/catalog/index.js +71 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +29 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +6 -0
- package/dist/registry.d.ts +7 -0
- package/dist/registry.js +41 -0
- package/dist/resolver.d.ts +7 -0
- package/dist/resolver.js +142 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.js +2 -0
- package/dist/writers/git-hooks.d.ts +2 -0
- package/dist/writers/git-hooks.js +7 -0
- package/dist/writers/instruction.d.ts +2 -0
- package/dist/writers/instruction.js +6 -0
- package/dist/writers/knowledge.d.ts +2 -0
- package/dist/writers/knowledge.js +9 -0
- package/dist/writers/setup-note.d.ts +2 -0
- package/dist/writers/setup-note.js +7 -0
- package/dist/writers/skills.d.ts +2 -0
- package/dist/writers/skills.js +7 -0
- package/dist/writers/workflows.d.ts +2 -0
- package/dist/writers/workflows.js +16 -0
- package/eslint.config.mjs +40 -0
- package/nodemon.json +7 -0
- package/package.json +34 -0
- package/src/catalog/catalog.spec.ts +531 -0
- package/src/catalog/facets/architecture.ts +438 -0
- package/src/catalog/facets/backpressure.ts +143 -0
- package/src/catalog/facets/practices.ts +173 -0
- package/src/catalog/facets/process.ts +50 -0
- package/src/catalog/index.ts +86 -0
- package/src/config.spec.ts +165 -0
- package/src/config.ts +39 -0
- package/src/index.ts +49 -0
- package/src/registry.spec.ts +144 -0
- package/src/registry.ts +68 -0
- package/src/resolver.spec.ts +581 -0
- package/src/resolver.ts +170 -0
- package/src/types.ts +151 -0
- package/src/writers/git-hooks.ts +9 -0
- package/src/writers/instruction.spec.ts +42 -0
- package/src/writers/instruction.ts +8 -0
- package/src/writers/knowledge.spec.ts +26 -0
- package/src/writers/knowledge.ts +15 -0
- package/src/writers/setup-note.ts +9 -0
- package/src/writers/skills.spec.ts +109 -0
- package/src/writers/skills.ts +9 -0
- package/src/writers/workflows.spec.ts +72 -0
- package/src/writers/workflows.ts +26 -0
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +7 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsconfig.vitest.json +7 -0
- package/vitest.config.ts +5 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import type { Facet } from "../../types.js";
|
|
2
|
+
|
|
3
|
+
export const architectureFacet: Facet = {
|
|
4
|
+
id: "architecture",
|
|
5
|
+
label: "Architecture",
|
|
6
|
+
description:
|
|
7
|
+
"Stack and framework conventions that shape your project structure",
|
|
8
|
+
required: false,
|
|
9
|
+
multiSelect: false,
|
|
10
|
+
options: [
|
|
11
|
+
{
|
|
12
|
+
id: "tanstack",
|
|
13
|
+
label: "TanStack",
|
|
14
|
+
description:
|
|
15
|
+
"Full-stack conventions for TanStack (Router, Query, Form, Table)",
|
|
16
|
+
recipe: [
|
|
17
|
+
{
|
|
18
|
+
writer: "skills",
|
|
19
|
+
config: {
|
|
20
|
+
skills: [
|
|
21
|
+
{
|
|
22
|
+
name: "tanstack-architecture",
|
|
23
|
+
description:
|
|
24
|
+
"Architecture conventions for TanStack applications",
|
|
25
|
+
body: [
|
|
26
|
+
"# TanStack Architecture Conventions",
|
|
27
|
+
"",
|
|
28
|
+
"## Project Structure",
|
|
29
|
+
"- Use file-based routing with TanStack Router (`routes/` directory)",
|
|
30
|
+
"- Colocate route components with their loaders and actions",
|
|
31
|
+
"- Organize by feature, not by type (e.g. `features/auth/`, not `components/auth/`)",
|
|
32
|
+
"",
|
|
33
|
+
"## Data Flow",
|
|
34
|
+
"- Use TanStack Query for all server state management",
|
|
35
|
+
"- Use TanStack Router loaders for route-level data requirements",
|
|
36
|
+
"- Keep client state minimal — prefer server state via Query",
|
|
37
|
+
"- Use `queryOptions()` factory pattern for reusable query definitions",
|
|
38
|
+
"",
|
|
39
|
+
"## Module Boundaries",
|
|
40
|
+
"- Each feature exports a public API via `index.ts`",
|
|
41
|
+
"- Features must not import from other features' internals",
|
|
42
|
+
"- Shared code goes in `lib/` or `shared/`"
|
|
43
|
+
].join("\n")
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "tanstack-design",
|
|
47
|
+
description: "Design patterns for TanStack applications",
|
|
48
|
+
body: [
|
|
49
|
+
"# TanStack Design Patterns",
|
|
50
|
+
"",
|
|
51
|
+
"## Query Patterns",
|
|
52
|
+
"- Define query options as standalone functions: `export const userQueryOptions = (id: string) => queryOptions({ queryKey: ['user', id], queryFn: () => fetchUser(id) })`",
|
|
53
|
+
"- Use `useSuspenseQuery` in route components paired with `loader` for prefetching",
|
|
54
|
+
"- Use `useMutation` with `onSettled` for cache invalidation",
|
|
55
|
+
"",
|
|
56
|
+
"## Router Patterns",
|
|
57
|
+
"- Define routes using `createFileRoute` for type-safe file-based routing",
|
|
58
|
+
"- Use `beforeLoad` for auth guards and redirects",
|
|
59
|
+
"- Use search params validation with `zodSearchValidator` for type-safe URL state",
|
|
60
|
+
"",
|
|
61
|
+
"## Form Patterns",
|
|
62
|
+
"- Use TanStack Form with Zod validators for form state and validation",
|
|
63
|
+
"- Prefer field-level validation over form-level where possible",
|
|
64
|
+
"- Connect form submission to `useMutation` for server sync"
|
|
65
|
+
].join("\n")
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "tanstack-code",
|
|
69
|
+
description: "Code style conventions for TanStack applications",
|
|
70
|
+
body: [
|
|
71
|
+
"# TanStack Code Conventions",
|
|
72
|
+
"",
|
|
73
|
+
"## TypeScript",
|
|
74
|
+
"- Enable strict mode in tsconfig",
|
|
75
|
+
"- Infer types from TanStack APIs rather than writing manual type annotations",
|
|
76
|
+
"- Use `satisfies` operator for type-safe object literals",
|
|
77
|
+
"",
|
|
78
|
+
"## Naming",
|
|
79
|
+
"- Query keys: `['entity', ...params]` (e.g. `['user', userId]`)",
|
|
80
|
+
"- Query option factories: `entityQueryOptions` (e.g. `userQueryOptions`)",
|
|
81
|
+
"- Route files: `$param` for dynamic segments (e.g. `users/$userId.tsx`)",
|
|
82
|
+
"- Loaders: export as named `loader` from route file",
|
|
83
|
+
"",
|
|
84
|
+
"## Imports",
|
|
85
|
+
"- Import from `@tanstack/react-query`, `@tanstack/react-router`, etc.",
|
|
86
|
+
"- Never import internal modules from TanStack packages",
|
|
87
|
+
"- Use path aliases for project imports (`@/features/...`)"
|
|
88
|
+
].join("\n")
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "tanstack-testing",
|
|
92
|
+
description: "Testing conventions for TanStack applications",
|
|
93
|
+
body: [
|
|
94
|
+
"# TanStack Testing Conventions",
|
|
95
|
+
"",
|
|
96
|
+
"## Query Testing",
|
|
97
|
+
"- Wrap components in `QueryClientProvider` with a fresh `QueryClient` per test",
|
|
98
|
+
"- Use `@testing-library/react` with `renderHook` for testing custom query hooks",
|
|
99
|
+
"- Mock at the network level with MSW, not at the query level",
|
|
100
|
+
"",
|
|
101
|
+
"## Router Testing",
|
|
102
|
+
"- Use `createMemoryHistory` and `createRouter` for route testing",
|
|
103
|
+
"- Test route loaders independently as plain async functions",
|
|
104
|
+
"- Test search param validation with unit tests on the validator schema",
|
|
105
|
+
"",
|
|
106
|
+
"## Integration Tests",
|
|
107
|
+
"- Test full user flows through route transitions",
|
|
108
|
+
"- Assert on visible UI state, not internal query cache state",
|
|
109
|
+
"- Use `waitFor` for async query resolution in component tests"
|
|
110
|
+
].join("\n")
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "playwright-cli",
|
|
114
|
+
source: "microsoft/playwright-cli/skills/playwright-cli"
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
docsets: [
|
|
121
|
+
{
|
|
122
|
+
id: "tanstack-router-docs",
|
|
123
|
+
label: "TanStack Router",
|
|
124
|
+
origin: "https://github.com/TanStack/router.git",
|
|
125
|
+
description: "File-based routing, loaders, and search params"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: "tanstack-query-docs",
|
|
129
|
+
label: "TanStack Query",
|
|
130
|
+
origin: "https://github.com/TanStack/query.git",
|
|
131
|
+
description: "Server state management, caching, and mutations"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: "tanstack-form-docs",
|
|
135
|
+
label: "TanStack Form",
|
|
136
|
+
origin: "https://github.com/TanStack/form.git",
|
|
137
|
+
description: "Type-safe form state and validation"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: "tanstack-table-docs",
|
|
141
|
+
label: "TanStack Table",
|
|
142
|
+
origin: "https://github.com/TanStack/table.git",
|
|
143
|
+
description: "Headless table and datagrid utilities"
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: "nodejs-backend",
|
|
149
|
+
label: "Node.js Backend",
|
|
150
|
+
description: "Type-safe API server with Express 5, tRPC, and Drizzle ORM",
|
|
151
|
+
recipe: [
|
|
152
|
+
{
|
|
153
|
+
writer: "skills",
|
|
154
|
+
config: {
|
|
155
|
+
skills: [
|
|
156
|
+
{
|
|
157
|
+
name: "nodejs-backend-architecture",
|
|
158
|
+
description:
|
|
159
|
+
"Architecture conventions for Node.js backend applications",
|
|
160
|
+
body: [
|
|
161
|
+
"# Node.js Backend Architecture Conventions",
|
|
162
|
+
"",
|
|
163
|
+
"## Project Structure",
|
|
164
|
+
"- Layered architecture: `routes/` → `procedures/` → `services/` → `repositories/`",
|
|
165
|
+
"- Organize by feature, not by type (e.g. `features/users/`, `features/orders/`)",
|
|
166
|
+
"- Each feature exports its tRPC router via `index.ts`",
|
|
167
|
+
"- Shared code in `lib/` (db client, logger, error classes)",
|
|
168
|
+
"- Entry point: `src/server.ts` creates Express app and mounts tRPC adapter via `express.createHandler`",
|
|
169
|
+
"",
|
|
170
|
+
"## Module Boundaries",
|
|
171
|
+
"- Features must not import from other features' internals",
|
|
172
|
+
"- Services never touch `req`/`res` — they receive typed inputs and return plain objects",
|
|
173
|
+
"- Repositories are thin wrappers around Drizzle queries",
|
|
174
|
+
"- Dependency injection via function parameters, not DI containers",
|
|
175
|
+
"",
|
|
176
|
+
"## Configuration",
|
|
177
|
+
"- Config via environment variables (12-factor app)",
|
|
178
|
+
"- Validate all env vars at startup with a Zod schema",
|
|
179
|
+
"- Single `config.ts` module exports the validated config object"
|
|
180
|
+
].join("\n")
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "nodejs-backend-design",
|
|
184
|
+
description: "Design patterns for Node.js backend applications",
|
|
185
|
+
body: [
|
|
186
|
+
"# Node.js Backend Design Patterns",
|
|
187
|
+
"",
|
|
188
|
+
"## tRPC Patterns",
|
|
189
|
+
"- Define one tRPC router per feature: `export const usersRouter = router({ ... })`",
|
|
190
|
+
"- Merge feature routers into a root `appRouter` in `src/router.ts`",
|
|
191
|
+
"- Export `type AppRouter = typeof appRouter` for client type inference",
|
|
192
|
+
"- Use Zod schemas for `.input()` and `.output()` on every procedure",
|
|
193
|
+
"- Use `publicProcedure` and `protectedProcedure` base procedures with middleware",
|
|
194
|
+
"",
|
|
195
|
+
"## Middleware",
|
|
196
|
+
"- Auth middleware: validate tokens, attach user context via tRPC context",
|
|
197
|
+
"- Logging middleware: structured JSON logs with request ID, duration, status",
|
|
198
|
+
"- Error handling: throw `TRPCError` with typed codes (`NOT_FOUND`, `UNAUTHORIZED`, etc.)",
|
|
199
|
+
"",
|
|
200
|
+
"## Database Patterns",
|
|
201
|
+
"- Drizzle schema files colocated with features (`features/users/schema.ts`)",
|
|
202
|
+
"- Repository functions take the Drizzle `db` instance as first parameter",
|
|
203
|
+
"- Use Drizzle transactions for multi-table operations",
|
|
204
|
+
"- Migrations managed via `drizzle-kit` (`drizzle/migrations/` directory)"
|
|
205
|
+
].join("\n")
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: "nodejs-backend-code",
|
|
209
|
+
description:
|
|
210
|
+
"Code style conventions for Node.js backend applications",
|
|
211
|
+
body: [
|
|
212
|
+
"# Node.js Backend Code Conventions",
|
|
213
|
+
"",
|
|
214
|
+
"## TypeScript",
|
|
215
|
+
"- Enable strict mode in tsconfig",
|
|
216
|
+
"- Never use `any` — prefer `unknown` and narrow with Zod or type guards",
|
|
217
|
+
"- Infer types from Drizzle schema (`typeof users.$inferSelect`) and tRPC (`inferRouterInputs`, `inferRouterOutputs`)",
|
|
218
|
+
"- Use `satisfies` operator for config and constant objects",
|
|
219
|
+
"",
|
|
220
|
+
"## Naming",
|
|
221
|
+
"- tRPC routers: `*.router.ts` (e.g. `users.router.ts`)",
|
|
222
|
+
"- Services: `*.service.ts` (e.g. `users.service.ts`)",
|
|
223
|
+
"- Repositories: `*.repository.ts` (e.g. `users.repository.ts`)",
|
|
224
|
+
"- Drizzle table schemas: `*.schema.ts` (e.g. `users.schema.ts`)",
|
|
225
|
+
"",
|
|
226
|
+
"## Imports",
|
|
227
|
+
"- Use path aliases for project imports (`@/features/...`, `@/lib/...`)",
|
|
228
|
+
"- Prefer named exports over default exports",
|
|
229
|
+
"- Barrel files (`index.ts`) per feature for public API only"
|
|
230
|
+
].join("\n")
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: "nodejs-backend-testing",
|
|
234
|
+
description:
|
|
235
|
+
"Testing conventions for Node.js backend applications",
|
|
236
|
+
body: [
|
|
237
|
+
"# Node.js Backend Testing Conventions",
|
|
238
|
+
"",
|
|
239
|
+
"## Unit Tests",
|
|
240
|
+
"- Test services with mocked repositories using `vi.mock()`",
|
|
241
|
+
"- Test Zod schemas independently with valid and invalid inputs",
|
|
242
|
+
"- Test file colocation: `*.spec.ts` next to source file",
|
|
243
|
+
"",
|
|
244
|
+
"## Integration Tests",
|
|
245
|
+
"- Test tRPC procedures using `createCaller` — no HTTP needed",
|
|
246
|
+
"- Database tests against a real test database",
|
|
247
|
+
"- Use transaction rollback per test for isolation",
|
|
248
|
+
"- Run Drizzle migrations before the test suite",
|
|
249
|
+
"",
|
|
250
|
+
"## Patterns",
|
|
251
|
+
"- Use Vitest as test runner and assertion library",
|
|
252
|
+
"- Do not mock tRPC internals — test through the caller API",
|
|
253
|
+
"- Factory functions for test data (avoid fixtures with implicit state)",
|
|
254
|
+
"- Assert on returned data and side effects, not internal implementation"
|
|
255
|
+
].join("\n")
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
],
|
|
261
|
+
docsets: [
|
|
262
|
+
{
|
|
263
|
+
id: "trpc-docs",
|
|
264
|
+
label: "tRPC",
|
|
265
|
+
origin: "https://github.com/trpc/trpc.git",
|
|
266
|
+
description: "End-to-end type-safe APIs, routers, and procedures"
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
id: "drizzle-orm-docs",
|
|
270
|
+
label: "Drizzle ORM",
|
|
271
|
+
origin: "https://github.com/drizzle-team/drizzle-orm.git",
|
|
272
|
+
description: "Type-safe SQL schema, queries, and migrations"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
id: "express-docs",
|
|
276
|
+
label: "Express",
|
|
277
|
+
origin: "https://github.com/expressjs/express.git",
|
|
278
|
+
description: "HTTP server, routing, and middleware"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
id: "zod-docs",
|
|
282
|
+
label: "Zod",
|
|
283
|
+
origin: "https://github.com/colinhacks/zod.git",
|
|
284
|
+
description: "TypeScript-first schema validation"
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
id: "java-backend",
|
|
290
|
+
label: "Java Backend",
|
|
291
|
+
description:
|
|
292
|
+
"Production-grade API server with Spring Boot 3, JPA/Hibernate, Gradle, and Lombok",
|
|
293
|
+
recipe: [
|
|
294
|
+
{
|
|
295
|
+
writer: "skills",
|
|
296
|
+
config: {
|
|
297
|
+
skills: [
|
|
298
|
+
{
|
|
299
|
+
name: "java-backend-architecture",
|
|
300
|
+
description:
|
|
301
|
+
"Architecture conventions for Spring Boot backend applications",
|
|
302
|
+
body: [
|
|
303
|
+
"# Java Backend Architecture Conventions",
|
|
304
|
+
"",
|
|
305
|
+
"## Project Structure",
|
|
306
|
+
"- Layered architecture: `controller/` → `service/` → `repository/`",
|
|
307
|
+
"- Organize by feature, not by layer (e.g. `com.app.user/`, `com.app.order/`)",
|
|
308
|
+
"- Each feature package contains its own controller, service, repository, DTOs, and entity classes",
|
|
309
|
+
"- Shared code in a `common/` or `shared/` package (exceptions, base entities, utilities)",
|
|
310
|
+
"- Entry point: `@SpringBootApplication` class in root package",
|
|
311
|
+
"",
|
|
312
|
+
"## Module Boundaries",
|
|
313
|
+
"- Controllers handle HTTP concerns only — delegate to services immediately",
|
|
314
|
+
"- Services contain business logic, call repositories, never touch `HttpServletRequest`/`HttpServletResponse`",
|
|
315
|
+
"- Repositories extend `JpaRepository` or `CrudRepository` — no business logic",
|
|
316
|
+
"- Cross-feature communication goes through service interfaces, not direct repository access",
|
|
317
|
+
"",
|
|
318
|
+
"## Configuration",
|
|
319
|
+
"- Use `application.yml` with Spring profiles (`dev`, `test`, `prod`)",
|
|
320
|
+
"- Externalize secrets via environment variables with `${ENV_VAR}` placeholders",
|
|
321
|
+
"- Type-safe config with `@ConfigurationProperties` classes annotated with `@Validated`",
|
|
322
|
+
"- Gradle build with Kotlin DSL (`build.gradle.kts`)"
|
|
323
|
+
].join("\n")
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
name: "java-backend-design",
|
|
327
|
+
description:
|
|
328
|
+
"Design patterns for Spring Boot backend applications",
|
|
329
|
+
body: [
|
|
330
|
+
"# Java Backend Design Patterns",
|
|
331
|
+
"",
|
|
332
|
+
"## REST API Patterns",
|
|
333
|
+
"- Use `@RestController` with `@RequestMapping` per feature (e.g. `/api/v1/users`)",
|
|
334
|
+
"- DTOs for request/response — never expose JPA entities directly",
|
|
335
|
+
"- Use `@Valid` with Jakarta Bean Validation annotations on request DTOs",
|
|
336
|
+
"- Return `ResponseEntity<T>` for explicit status codes, or direct objects for 200 OK",
|
|
337
|
+
"- Use `@ControllerAdvice` with `@ExceptionHandler` for centralized error handling",
|
|
338
|
+
"",
|
|
339
|
+
"## JPA/Hibernate Patterns",
|
|
340
|
+
"- Entities use Lombok `@Data`, `@Builder`, `@NoArgsConstructor`, `@AllArgsConstructor`",
|
|
341
|
+
"- Use `@Entity` with explicit `@Table(name = ...)` and `@Column` mappings",
|
|
342
|
+
"- Prefer `FetchType.LAZY` for associations — use `@EntityGraph` or join fetch for eager loading when needed",
|
|
343
|
+
"- Database migrations managed by Flyway (`db/migration/V1__description.sql`)",
|
|
344
|
+
"- Use Spring Data JPA derived queries or `@Query` with JPQL",
|
|
345
|
+
"",
|
|
346
|
+
"## Middleware & Cross-Cutting",
|
|
347
|
+
"- Security with Spring Security filter chain — JWT or session-based",
|
|
348
|
+
"- Structured logging with SLF4J + Logback, MDC for request correlation",
|
|
349
|
+
"- Use `@Transactional` on service methods, read-only where appropriate"
|
|
350
|
+
].join("\n")
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
name: "java-backend-code",
|
|
354
|
+
description:
|
|
355
|
+
"Code style conventions for Spring Boot backend applications",
|
|
356
|
+
body: [
|
|
357
|
+
"# Java Backend Code Conventions",
|
|
358
|
+
"",
|
|
359
|
+
"## Lombok Usage",
|
|
360
|
+
"- Use `@Data` for DTOs, `@Value` for immutable objects",
|
|
361
|
+
"- Use `@Builder` for entities and complex DTOs",
|
|
362
|
+
"- Use `@RequiredArgsConstructor` for constructor injection (preferred over `@Autowired`)",
|
|
363
|
+
"- Use `@Slf4j` for logger injection",
|
|
364
|
+
"",
|
|
365
|
+
"## Naming",
|
|
366
|
+
"- Controllers: `*Controller.java` (e.g. `UserController.java`)",
|
|
367
|
+
"- Services: `*Service.java` interface + `*ServiceImpl.java`",
|
|
368
|
+
"- Repositories: `*Repository.java` (e.g. `UserRepository.java`)",
|
|
369
|
+
"- Entities: singular noun (e.g. `User.java`, `Order.java`)",
|
|
370
|
+
"- DTOs: `*Request.java`, `*Response.java` (e.g. `CreateUserRequest.java`)",
|
|
371
|
+
"",
|
|
372
|
+
"## Dependency Injection",
|
|
373
|
+
"- Constructor injection via `@RequiredArgsConstructor` — never field injection",
|
|
374
|
+
"- Declare dependencies as `private final` fields",
|
|
375
|
+
"- Program to interfaces for services (e.g. inject `UserService`, not `UserServiceImpl`)"
|
|
376
|
+
].join("\n")
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
name: "java-backend-testing",
|
|
380
|
+
description:
|
|
381
|
+
"Testing conventions for Spring Boot backend applications",
|
|
382
|
+
body: [
|
|
383
|
+
"# Java Backend Testing Conventions",
|
|
384
|
+
"",
|
|
385
|
+
"## Unit Tests",
|
|
386
|
+
"- Test services with mocked repositories using `@ExtendWith(MockitoExtension.class)`",
|
|
387
|
+
"- Use `@Mock` for dependencies and `@InjectMocks` for the class under test",
|
|
388
|
+
"- Test DTOs and validation annotations independently",
|
|
389
|
+
"- Follow `given/when/then` structure with descriptive method names",
|
|
390
|
+
"",
|
|
391
|
+
"## Integration Tests",
|
|
392
|
+
"- Use `@SpringBootTest` with `@AutoConfigureMockMvc` for controller tests",
|
|
393
|
+
"- Test through `MockMvc` — assert on status, headers, and JSON body",
|
|
394
|
+
"- Use `@DataJpaTest` for repository tests with an embedded H2 database",
|
|
395
|
+
"- Use `@Testcontainers` for integration tests against real databases (PostgreSQL, MySQL)",
|
|
396
|
+
"- Use `@Transactional` on test classes for automatic rollback",
|
|
397
|
+
"",
|
|
398
|
+
"## Patterns",
|
|
399
|
+
"- JUnit 5 as test framework, AssertJ for fluent assertions",
|
|
400
|
+
"- Test file location: `src/test/java/` mirroring main source structure",
|
|
401
|
+
"- Factory methods or builders for test data — avoid shared mutable fixtures",
|
|
402
|
+
"- Use `@WithMockUser` for security-aware controller tests"
|
|
403
|
+
].join("\n")
|
|
404
|
+
}
|
|
405
|
+
]
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
],
|
|
409
|
+
docsets: [
|
|
410
|
+
{
|
|
411
|
+
id: "spring-boot-docs",
|
|
412
|
+
label: "Spring Boot",
|
|
413
|
+
origin: "https://github.com/spring-projects/spring-boot.git",
|
|
414
|
+
description: "Spring Boot framework, auto-configuration, and actuator"
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
id: "spring-data-jpa-docs",
|
|
418
|
+
label: "Spring Data JPA",
|
|
419
|
+
origin: "https://github.com/spring-projects/spring-data-jpa.git",
|
|
420
|
+
description: "JPA repositories, derived queries, and specifications"
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
id: "spring-security-docs",
|
|
424
|
+
label: "Spring Security",
|
|
425
|
+
origin: "https://github.com/spring-projects/spring-security.git",
|
|
426
|
+
description: "Authentication, authorization, and security filters"
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
id: "lombok-docs",
|
|
430
|
+
label: "Lombok",
|
|
431
|
+
origin: "https://github.com/projectlombok/lombok.git",
|
|
432
|
+
description:
|
|
433
|
+
"Boilerplate reduction with annotations for getters, builders, and constructors"
|
|
434
|
+
}
|
|
435
|
+
]
|
|
436
|
+
}
|
|
437
|
+
]
|
|
438
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { Facet, Provision } from "../../types.js";
|
|
2
|
+
|
|
3
|
+
const NODEJS_LINT_BUILD_SCRIPT = `#!/bin/sh
|
|
4
|
+
output=$(npm run lint 2>&1 && npm run build 2>&1); exit_code=$?
|
|
5
|
+
if [ $exit_code -eq 0 ]; then echo "✓"; else echo "$output"; exit $exit_code; fi
|
|
6
|
+
`;
|
|
7
|
+
|
|
8
|
+
const JAVA_LINT_BUILD_SCRIPT = `#!/bin/sh
|
|
9
|
+
output=$(./gradlew compileJava checkstyleMain 2>&1); exit_code=$?
|
|
10
|
+
if [ $exit_code -eq 0 ]; then echo "✓"; else echo "$output"; exit $exit_code; fi
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
const NODEJS_UNIT_TEST_SCRIPT = `#!/bin/sh
|
|
14
|
+
output=$(npm test -- --bail 2>&1); exit_code=$?
|
|
15
|
+
if [ $exit_code -eq 0 ]; then echo "✓"; else echo "$output"; exit $exit_code; fi
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
const JAVA_UNIT_TEST_SCRIPT = `#!/bin/sh
|
|
19
|
+
output=$(./gradlew test 2>&1); exit_code=$?
|
|
20
|
+
if [ $exit_code -eq 0 ]; then echo "✓"; else echo "$output"; exit $exit_code; fi
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const WIP_COMMIT_INSTRUCTION =
|
|
24
|
+
"Commit often using small WIP commits so pre-commit quality gates run frequently and catch issues early.";
|
|
25
|
+
|
|
26
|
+
const NODEJS_LINT_BUILD_NOTE =
|
|
27
|
+
"Add lint and build scripts to package.json before committing:\n" +
|
|
28
|
+
' "lint": "eslint .",\n' +
|
|
29
|
+
' "build": "tsc --noEmit"';
|
|
30
|
+
|
|
31
|
+
const JAVA_LINT_BUILD_NOTE =
|
|
32
|
+
"Apply the Checkstyle Gradle plugin before committing:\n" +
|
|
33
|
+
" // build.gradle.kts\n" +
|
|
34
|
+
" plugins { checkstyle }";
|
|
35
|
+
|
|
36
|
+
const NODEJS_LINT_BUILD_RECIPE: Provision[] = [
|
|
37
|
+
{
|
|
38
|
+
writer: "git-hooks",
|
|
39
|
+
config: {
|
|
40
|
+
hooks: [{ phase: "pre-commit", script: NODEJS_LINT_BUILD_SCRIPT }]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
writer: "instruction",
|
|
45
|
+
config: { text: WIP_COMMIT_INSTRUCTION }
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
writer: "setup-note",
|
|
49
|
+
config: { text: NODEJS_LINT_BUILD_NOTE }
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
const JAVA_LINT_BUILD_RECIPE: Provision[] = [
|
|
54
|
+
{
|
|
55
|
+
writer: "git-hooks",
|
|
56
|
+
config: {
|
|
57
|
+
hooks: [{ phase: "pre-commit", script: JAVA_LINT_BUILD_SCRIPT }]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
writer: "instruction",
|
|
62
|
+
config: { text: WIP_COMMIT_INSTRUCTION }
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
writer: "setup-note",
|
|
66
|
+
config: { text: JAVA_LINT_BUILD_NOTE }
|
|
67
|
+
}
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const NODEJS_UNIT_TEST_RECIPE: Provision[] = [
|
|
71
|
+
{
|
|
72
|
+
writer: "git-hooks",
|
|
73
|
+
config: {
|
|
74
|
+
hooks: [{ phase: "pre-push", script: NODEJS_UNIT_TEST_SCRIPT }]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
const JAVA_UNIT_TEST_RECIPE: Provision[] = [
|
|
80
|
+
{
|
|
81
|
+
writer: "git-hooks",
|
|
82
|
+
config: {
|
|
83
|
+
hooks: [{ phase: "pre-push", script: JAVA_UNIT_TEST_SCRIPT }]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
export const backpressureFacet: Facet = {
|
|
89
|
+
id: "backpressure",
|
|
90
|
+
label: "Backpressure",
|
|
91
|
+
description:
|
|
92
|
+
"Install git hooks that enforce quality gates — silent on success, surface only relevant failures",
|
|
93
|
+
required: false,
|
|
94
|
+
multiSelect: true,
|
|
95
|
+
dependsOn: ["architecture"],
|
|
96
|
+
options: [
|
|
97
|
+
{
|
|
98
|
+
id: "lint-build-precommit-tanstack",
|
|
99
|
+
label: "Lint + Build (pre-commit)",
|
|
100
|
+
description:
|
|
101
|
+
"Block commits if lint or build fails; emit only ✓ on success",
|
|
102
|
+
available: (deps) => deps["architecture"]?.id === "tanstack",
|
|
103
|
+
recipe: NODEJS_LINT_BUILD_RECIPE
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: "lint-build-precommit-nodejs-backend",
|
|
107
|
+
label: "Lint + Build (pre-commit)",
|
|
108
|
+
description:
|
|
109
|
+
"Block commits if lint or build fails; emit only ✓ on success",
|
|
110
|
+
available: (deps) => deps["architecture"]?.id === "nodejs-backend",
|
|
111
|
+
recipe: NODEJS_LINT_BUILD_RECIPE
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: "lint-build-precommit-java-backend",
|
|
115
|
+
label: "Lint + Build (pre-commit)",
|
|
116
|
+
description:
|
|
117
|
+
"Block commits if lint or build fails; emit only ✓ on success",
|
|
118
|
+
available: (deps) => deps["architecture"]?.id === "java-backend",
|
|
119
|
+
recipe: JAVA_LINT_BUILD_RECIPE
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: "unit-test-prepush-tanstack",
|
|
123
|
+
label: "Unit Tests (pre-push)",
|
|
124
|
+
description: "Block pushes if unit tests fail; emit only ✓ on success",
|
|
125
|
+
available: (deps) => deps["architecture"]?.id === "tanstack",
|
|
126
|
+
recipe: NODEJS_UNIT_TEST_RECIPE
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "unit-test-prepush-nodejs-backend",
|
|
130
|
+
label: "Unit Tests (pre-push)",
|
|
131
|
+
description: "Block pushes if unit tests fail; emit only ✓ on success",
|
|
132
|
+
available: (deps) => deps["architecture"]?.id === "nodejs-backend",
|
|
133
|
+
recipe: NODEJS_UNIT_TEST_RECIPE
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: "unit-test-prepush-java-backend",
|
|
137
|
+
label: "Unit Tests (pre-push)",
|
|
138
|
+
description: "Block pushes if unit tests fail; emit only ✓ on success",
|
|
139
|
+
available: (deps) => deps["architecture"]?.id === "java-backend",
|
|
140
|
+
recipe: JAVA_UNIT_TEST_RECIPE
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
};
|