@skyf0xx/hedgehog 0.1.19 → 0.1.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyf0xx/hedgehog",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Install the Hedgehog build discipline (agents + skills) into a repo.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -36,7 +36,15 @@ when a new package needs wiring into a consumer's dependencies.
36
36
 
37
37
  - **Step 6 (hook)**: build the TanStack Query hook in `packages/hooks`,
38
38
  wrapping the ts-rest contract client. One hook per contract operation,
39
- typed end to end from the Zod contract.
39
+ typed end to end from the Zod contract. The client's base URL comes
40
+ from a `NEXT_PUBLIC_`-prefixed env var (added to
41
+ `packages/config/env.schema.ts` if it isn't there yet) — never a
42
+ hardcoded `http://localhost:<port>` literal, even as a "temporary"
43
+ fallback. `apps/api`'s dev port is `3333` (see `hedgehog-bootstrap-core`
44
+ — chosen specifically to not collide with `apps/web`'s `next dev`
45
+ default of `3000`); a literal fallback drifts out of sync with that the
46
+ moment either port changes and produces a silent 404 that looks like a
47
+ routing bug, not a config bug.
40
48
  - **Step 7 (screen)**: build the screen/component in `apps/web` and/or
41
49
  `apps/mobile`, consuming the hook and `ux-planner`'s rationale for that
42
50
  module (screen inventory, interaction pattern, information hierarchy).
@@ -77,3 +85,10 @@ when a new package needs wiring into a consumer's dependencies.
77
85
  - No inline styles, no CSS modules — Tailwind utilities only.
78
86
  - If the contract doesn't cover what the screen needs, stop and flag it
79
87
  as a Correction Protocol case rather than reaching past the contract.
88
+ - After editing anything under `packages/hooks/src` (or any other
89
+ workspace package a running dev server consumes), run
90
+ `nx run hooks:build` before checking the change in a browser. Next/Expo
91
+ resolve workspace packages through `package.json`'s `main`/`exports`
92
+ fields, which point at `dist/`, not live `src/` — a stale `dist/` means
93
+ the dev server keeps serving the pre-edit code with no error, no
94
+ warning, and no indication the fix didn't take.
@@ -0,0 +1,4 @@
1
+ # Copy to .env for local dev. Matches docker-compose.yml's Postgres
2
+ # service — no edits needed unless you've changed those credentials.
3
+ DATABASE_URL=postgresql://postgres:postgres@localhost:5432/app
4
+ NODE_ENV=development
@@ -84,6 +84,8 @@
84
84
  "@nestjs/common": "^11.0.0",
85
85
  "@nestjs/core": "^11.0.0",
86
86
  "@nestjs/platform-express": "^11.0.0",
87
+ "@ts-rest/core": "3.53.0-rc.1",
88
+ "@ts-rest/nest": "3.53.0-rc.1",
87
89
  "reflect-metadata": "^0.2.0",
88
90
  "rxjs": "^7.8.0",
89
91
  "tslib": "^2.3.0",
@@ -10,7 +10,10 @@ async function bootstrap() {
10
10
  app.useLogger(app.get(Logger));
11
11
  const globalPrefix = 'api';
12
12
  app.setGlobalPrefix(globalPrefix);
13
- const port = process.env.PORT || 3000;
13
+ // Defaults to 3333, not 3000 — `apps/web`'s `next dev` also defaults to
14
+ // 3000, and both apps run side by side in local dev (see root `dev`
15
+ // script), so the api needs a distinct default port to avoid colliding.
16
+ const port = process.env.PORT || 3333;
14
17
  await app.listen(port);
15
18
  app
16
19
  .get(Logger)
@@ -7,7 +7,7 @@ export default async function setup() {
7
7
  console.log('\nSetting up...\n');
8
8
 
9
9
  const host = process.env.HOST ?? 'localhost';
10
- const port = process.env.PORT ? Number(process.env.PORT) : 3000;
10
+ const port = process.env.PORT ? Number(process.env.PORT) : 3333;
11
11
  await waitForPortOpen(port, { host });
12
12
 
13
13
  return async function teardown() {
@@ -2,5 +2,5 @@ import axios from 'axios';
2
2
 
3
3
  // Configure axios for tests to use.
4
4
  const host = process.env.HOST ?? 'localhost';
5
- const port = process.env.PORT ?? '3000';
5
+ const port = process.env.PORT ?? '3333';
6
6
  axios.defaults.baseURL = `http://${host}:${port}`;
@@ -3,6 +3,9 @@
3
3
  "private": true,
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@9.0.0",
6
+ "scripts": {
7
+ "dev": "docker compose up -d && nx run-many --target=serve,dev --projects=api,web --parallel"
8
+ },
6
9
  "devDependencies": {
7
10
  "@commitlint/cli": "^21.2.1",
8
11
  "@commitlint/config-conventional": "^21.2.0",
@@ -212,6 +212,12 @@ importers:
212
212
  '@nestjs/platform-express':
213
213
  specifier: ^11.0.0
214
214
  version: 11.1.28(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@11.1.28)
215
+ '@ts-rest/core':
216
+ specifier: 3.53.0-rc.1
217
+ version: 3.53.0-rc.1(@types/node@22.20.1)
218
+ '@ts-rest/nest':
219
+ specifier: 3.53.0-rc.1
220
+ version: 3.53.0-rc.1(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@11.1.28(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@ts-rest/core@3.53.0-rc.1(@types/node@22.20.1))(rxjs@7.8.1)
215
221
  config:
216
222
  specifier: workspace:*
217
223
  version: link:../../packages/config
@@ -284,6 +290,9 @@ importers:
284
290
 
285
291
  packages/config:
286
292
  dependencies:
293
+ '@ts-rest/core':
294
+ specifier: 3.53.0-rc.1
295
+ version: 3.53.0-rc.1(@types/node@22.20.1)
287
296
  zod:
288
297
  specifier: ^4.0.0
289
298
  version: 4.4.3
@@ -4515,6 +4524,28 @@ packages:
4515
4524
  integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==,
4516
4525
  }
4517
4526
 
4527
+ '@ts-rest/core@3.53.0-rc.1':
4528
+ resolution:
4529
+ {
4530
+ integrity: sha512-hDMXqKHSys6w+kXFW1Q6EvN8QgRvtXKXJ2TpYByKI4TquaPjiTOv99aLD26X4LNRzdna8Ci1PVyzr0jYZv0oNQ==,
4531
+ }
4532
+ peerDependencies:
4533
+ '@types/node': ^18.18.7 || >=20.8.4
4534
+ peerDependenciesMeta:
4535
+ '@types/node':
4536
+ optional: true
4537
+
4538
+ '@ts-rest/nest@3.53.0-rc.1':
4539
+ resolution:
4540
+ {
4541
+ integrity: sha512-tiuxTwXElFrAGFiUpqn78HmGgVY848D5s+uz/wCQwzRgPsfEneeZwOnEtxvXyrAp6tS5VtbVIxrI/kD+yR2zjw==,
4542
+ }
4543
+ peerDependencies:
4544
+ '@nestjs/common': ^9.0.0 || ^10.0.0 || ^11.0.0
4545
+ '@nestjs/core': ^9.0.0 || ^10.0.0 || ^11.0.0
4546
+ '@ts-rest/core': 3.53.0-rc.1
4547
+ rxjs: ^7.1.0
4548
+
4518
4549
  '@tybys/wasm-util@0.10.3':
4519
4550
  resolution:
4520
4551
  {
@@ -16814,6 +16845,17 @@ snapshots:
16814
16845
 
16815
16846
  '@tokenizer/token@0.3.0': {}
16816
16847
 
16848
+ '@ts-rest/core@3.53.0-rc.1(@types/node@22.20.1)':
16849
+ optionalDependencies:
16850
+ '@types/node': 22.20.1
16851
+
16852
+ '@ts-rest/nest@3.53.0-rc.1(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@11.1.28(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@ts-rest/core@3.53.0-rc.1(@types/node@22.20.1))(rxjs@7.8.1)':
16853
+ dependencies:
16854
+ '@nestjs/common': 11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1)
16855
+ '@nestjs/core': 11.1.28(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.1)
16856
+ '@ts-rest/core': 3.53.0-rc.1(@types/node@22.20.1)
16857
+ rxjs: 7.8.1
16858
+
16817
16859
  '@tybys/wasm-util@0.10.3':
16818
16860
  dependencies:
16819
16861
  tslib: 2.8.1
@@ -168,7 +168,11 @@ pnpm add better-auth @thallesp/nestjs-better-auth
168
168
  Configure the Drizzle adapter against `packages/db`. Add
169
169
  `BETTER_AUTH_SECRET: z.string().min(32)` to `packages/config/env.schema.ts`
170
170
  now (it doesn't exist in the core schema `hedgehog-bootstrap-core`
171
- landed). Tag: `scope:auth`, `type:adapter`.
171
+ landed), and add a matching `BETTER_AUTH_SECRET=` line with a generated
172
+ value to the root `.env.example` — a schema entry with no `.env.example`
173
+ line reproduces the exact `loadEnv()` crash-on-boot that
174
+ `hedgehog-bootstrap-core`'s `DATABASE_URL` entry exists to prevent, just
175
+ for this var instead. Tag: `scope:auth`, `type:adapter`.
172
176
 
173
177
  Also wire the global auth guard on `apps/api`: `pnpm add
174
178
  @thallesp/nestjs-better-auth` there too and register the guard
@@ -196,7 +200,12 @@ pnpm add bullmq ioredis
196
200
  Add a `redis` service to the root `docker-compose.yml`
197
201
  `hedgehog-bootstrap-core` landed (Postgres-only until now) and
198
202
  `REDIS_URL: z.string().url()` to `packages/config/env.schema.ts` (it
199
- doesn't exist in the core schema):
203
+ doesn't exist in the core schema), plus a matching `REDIS_URL=` line in
204
+ the root `.env.example` pointing at that same `docker-compose.yml`
205
+ service (e.g. `redis://localhost:6379`) — same reasoning as
206
+ `BETTER_AUTH_SECRET` above, a schema entry without a `.env.example` line
207
+ just moves the `loadEnv()` crash-on-boot to this var instead of fixing
208
+ the class of bug:
200
209
 
201
210
  ```yaml
202
211
  redis:
@@ -27,12 +27,15 @@ Everything under `src/golden-core/` in the installed Hedgehog package,
27
27
  copied to the repo root:
28
28
 
29
29
  - Root: `nx.json`, `pnpm-workspace.yaml`, `package.json` (with the
30
- `pnpm.overrides.esbuild` pin and `packageManager` field),
31
- `eslint.config.mjs`, `docker-compose.yml` (Postgres only — Redis joins
32
- later, only if the Queue add-on turns on), `lefthook.yml`,
33
- `commitlint.config.cjs`, `tools/phase-gate.cjs`,
34
- `.github/workflows/phase-gate.yml`, `tsconfig.base.json`,
35
- `pnpm-lock.yaml`.
30
+ `pnpm.overrides.esbuild` pin, `packageManager` field, and a `dev`
31
+ script — `docker compose up -d && nx run-many --target=serve,dev
32
+ --projects=api,web --parallel` — so a fresh clone has one command that
33
+ brings up Postgres and both apps together), `eslint.config.mjs`,
34
+ `docker-compose.yml` (Postgres only — Redis joins later, only if the
35
+ Queue add-on turns on), `.env.example` (`DATABASE_URL`/`NODE_ENV`,
36
+ copied to `.env` in step 4), `lefthook.yml`, `commitlint.config.cjs`,
37
+ `tools/phase-gate.cjs`, `.github/workflows/phase-gate.yml`,
38
+ `tsconfig.base.json`, `pnpm-lock.yaml`.
36
39
  - `packages/config/` — `eslint-base.js`, `prettier.js` (no
37
40
  `prettier-plugin-tailwindcss` — that's `apps/web`'s own config, already
38
41
  wired), `env.schema.ts` (core fields only: `DATABASE_URL`, `NODE_ENV`).
@@ -96,9 +99,17 @@ lands" above should be on disk.
96
99
 
97
100
  ```bash
98
101
  pnpm install
102
+ cp .env.example .env
99
103
  docker compose up -d
100
104
  ```
101
105
 
106
+ `.env` is gitignored and never shipped — `.env.example` is the committed
107
+ template (`DATABASE_URL` matching `docker-compose.yml`'s Postgres
108
+ credentials, `NODE_ENV=development`). Skipping the copy means
109
+ `packages/config`'s `loadEnv()` fails its Zod check the moment `apps/api`
110
+ boots (`DATABASE_URL` missing) — a confusing crash to debug live instead
111
+ of one line here.
112
+
102
113
  `pnpm install` resolves against the committed `pnpm-lock.yaml` — this
103
114
  should be fast and produce no lockfile changes. A lockfile diff here
104
115
  means the shipped `pnpm-lock.yaml` doesn't match `package.json` — that's
@@ -191,6 +202,17 @@ bug by "cleaning up" what looks like an unnecessary pin or directive.
191
202
  is ESM (`export default`), and without a matching `"type": "module"`
192
203
  Node emits a `MODULE_TYPELESS_PACKAGE_JSON` warning on every prettier
193
204
  invocation touching that directory.
205
+ - **`apps/api`'s dev port defaults to 3333, not 3000.** `apps/web`'s
206
+ `next dev` also defaults to port 3000, and the root `dev` script runs
207
+ both side by side (`nx run-many --target=serve,dev
208
+ --projects=api,web`). If `apps/api/src/main.ts` ever falls back to
209
+ `process.env.PORT || 3000`, whichever process binds the port second
210
+ either crashes or is silently unreachable, and every API call from the
211
+ web client 404s against Next's own dev server instead (Next has no
212
+ matching route, so it serves its catch-all 404 page rather than a
213
+ connection error — easy to mistake for a routing bug in the api
214
+ itself). Keep `apps/api`'s fallback at `3333` and don't let it drift
215
+ back to matching Next's default.
194
216
  - **No `NODE_ENV=production` build-target override needed** (Nx
195
217
  23.1.0, Next 16.1.7). Targets are inferred from
196
218
  `package.json`/`next.config.js` via the `@nx/next` plugin, with no
@@ -164,7 +164,12 @@ When a downstream step reveals an upstream step was wrong:
164
164
  1. Stop.
165
165
  2. Patch the upstream step directly, in place.
166
166
  3. Fast-forward every dependent step that breaks, each its own small
167
- commit.
167
+ commit. If the patched step lives in a workspace package (e.g.
168
+ `packages/hooks`, `packages/contracts`) that a running `web`/`mobile`
169
+ dev server consumes, run that package's `nx run <pkg>:build` before
170
+ re-verifying — the dev server resolves the package's built `dist/`,
171
+ not its `src/`, so an unbuilt patch looks unchanged to anything
172
+ downstream even though the source is fixed.
168
173
  4. The commit messages are the explanation.
169
174
  5. Resume the loop.
170
175