Skip to content

refactor(global): unify OpenAPI types and brand IDs consistently - #49

Merged
CptSchnitz merged 16 commits into
masterfrom
feat/unify-openapi-types
Sep 24, 2026
Merged

CptSchnitz merged 16 commits into
masterfrom
feat/unify-openapi-types

Conversation

@CptSchnitz

@CptSchnitz CptSchnitz commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • jobnik-openapi becomes the single place OpenAPI-derived types are generated, with JobId/StageId/TaskId branding baked into paths/components/operations/TypedRequestHandlers
  • jobnik-sdk stops regenerating its own duplicate types and consumes jobnik-openapi's types directly
  • jobnik-manager retypes job/stage/task ids end-to-end (service layer + DAL) to the branded ids, so the compiler rejects a mismatched id kind anywhere in the call chain
  • Follow-up commit addresses code review findings

Test plan

  • pnpm --filter jobnik-openapi type-check / generate:check
  • pnpm --filter jobnik-sdk type-check / generate:check
  • pnpm --filter jobnik-manager type-check
  • Existing unit/integration test suites pass unmodified (jobnik-manager, jobnik-sdk, jobnik-e2e)

🤖 Generated with Claude Code

CptSchnitz and others added 6 commits September 16, 2026 14:46
Move Brand/JobId/StageId/TaskId from jobnik-sdk into jobnik-openapi and
wire generateTypes.mts to brand jobId/stageId/taskId schema refs, so
jobnik-openapi becomes the single place OpenAPI-derived types (brands
included) are generated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Stop regenerating a duplicate openapi.ts/brands.ts and import
paths/components/operations/JobId/StageId/TaskId straight from
jobnik-openapi, removing the second independently-generated copy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Retype every jobId parameter in the job service layer and the job-id
flow through the stage manager to JobId from jobnik-openapi, so the
compiler rejects a StageId/TaskId passed where a job id is expected.
Prisma-sourced job ids are cast at the DB boundary, since Prisma keeps
plain strings while the branded id only exists in the API/service
layer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Retype every stageId parameter in the stage service layer, the
stage-id flow through the task manager, and stageRepository.
updateStageSummary to StageId from jobnik-openapi, so getStageById and
the repository reject a JobId/TaskId at compile time. Prisma-sourced
stage ids are cast at the DB boundary, matching the JobId pattern from
the previous commit. Also casts the Prisma->API boundary in
convertPrismaToStageResponse, and closes a couple of JobId gaps in the
stages integration spec that the job-id-branding commit missed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Retype every taskId parameter in the task service layer to TaskId from
jobnik-openapi, so getTaskById rejects a JobId/StageId at compile
time. Casts the Prisma->API boundary in convertPrismaToTaskResponse
and convertPrismaToJobResponse (the latter closes a JobId gap the
job-id-branding commit missed), matching the pattern already used for
JobId/StageId. This is the last of the three id-branding commits;
jobnik-manager now type-checks, builds, and its full test suite passes
with the branded ids threaded end-to-end.

Also fixes import ordering (eslint import-x/order) flagged in a couple
of test files touched by the earlier job/stage id commits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Export Brand from jobnik-openapi's brands.ts/index.ts, matching
  ticket 01's acceptance checklist (JobId/StageId/TaskId were already
  re-exported, Brand itself was missed).
- Hoist the repeated stage.jobId/stage.job.id as JobId cast in
  StageManager.executeUpdateStatus into a single local, removing
  four near-identical casts and a stage.jobId/stage.job.id
  inconsistency.
- Fix a test that cast a job id to StageId and passed it to
  addTasks instead of the actual stage id (tests/unit/tasks/tasks.spec.ts).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Coverage Report for apps/jobnik-manager

Status Category Percentage Covered / Total
🟢 Lines 100% (🎯 80%) 751 / 751
🟢 Statements 100% (🎯 80%) 768 / 768
🟢 Functions 100% (🎯 80%) 112 / 112
🟢 Branches 100% (🎯 80%) 219 / 219
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/jobnik-manager/src/api/v1/jobs/controller.ts 100% 100% 100% 100%
apps/jobnik-manager/src/api/v1/stages/controller.ts 100% 100% 100% 100%
apps/jobnik-manager/src/api/v1/tasks/controller.ts 100% 100% 100% 100%
apps/jobnik-manager/src/jobs/models/manager.ts 100% 100% 100% 100%
apps/jobnik-manager/src/stages/DAL/stageRepository.ts 100% 100% 100% 100%
apps/jobnik-manager/src/stages/models/helper.ts 100% 100% 100% 100%
apps/jobnik-manager/src/stages/models/manager.ts 100% 100% 100% 100%
apps/jobnik-manager/src/tasks/models/helper.ts 100% 100% 100% 100%
apps/jobnik-manager/src/tasks/models/manager.ts 100% 100% 100% 100%
apps/jobnik-manager/src/tasks/models/taskStateMachine.ts 100% 100% 100% 100%
Generated in workflow #105 for commit ac45492 by the Vitest Coverage Report Action

CptSchnitz and others added 2 commits September 17, 2026 08:58
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rror classes/mapping

jobnik-sdk and jobnik-manager each independently regenerated error classes/mapping
from the same spec. jobnik-openapi now generates both once; jobnik-manager imports
them directly (never published, so a runtime dependency is safe), while jobnik-sdk
stages a physical local copy at build time via a new copy:errors step, since it
publishes standalone and jobnik-openapi is a private, unpublished package.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@CptSchnitz CptSchnitz changed the title Unify OpenAPI types and brand IDs consistently refactor(global): unify OpenAPI types and brand IDs consistently Sep 22, 2026
CptSchnitz and others added 4 commits September 22, 2026 10:35
…moval

pnpm-lock.yaml still listed @map-colonies/openapi-helpers for jobnik-sdk
after 467c03f dropped it from package.json, breaking frozen-lockfile CI installs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ead of at each cast site

getStageEntityById/getJobEntityById/getTaskEntityById and their raw ad-hoc
query call sites now cast Prisma results to JobId/StageId/TaskId once, at
the point the value leaves Prisma, instead of scattering `as JobId`/
`as StageId`/`as TaskId` casts across every call site that reads the field.

Prisma has no concept of branded scalars, so this can't be pushed further
down into schema.prisma: prisma-json-types-generator throws on `@db.Uuid`
string columns (breaks its UuidFilter handling and silently drops Json
overrides for later models). Revisit once that's fixed upstream.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…y:generated step

copySpec.mts and copyErrors.mts each did the same thing (copy a file
resolved through jobnik-openapi's exports into src/, since jobnik-openapi
is private and unpublished so jobnik-sdk must vendor these at build time).
Collapse both into a single copyGenerated.mts and one prebuild step.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…n knip

src/generated/openapi-errors.ts is staged by the copy:generated prebuild
step and gitignored, so it doesn't exist on a fresh checkout — knip's
static analysis (which doesn't run build scripts) flagged the import in
sdkErrors.ts as unresolved, failing CI. Same pattern already used for
jobnik-manager's generated ./instrumentation.mjs.

Also drop the now-stale ignore entry for src/types/openapi.ts, removed
when the SDK started consuming jobnik-openapi types directly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@ronenkapelian ronenkapelian left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Comment thread packages/jobnik-openapi/scripts/generateTypes.mts Outdated
CptSchnitz and others added 4 commits September 22, 2026 13:21
…s import

1b3a062 dropped this entry while cleaning up the unrelated @prismaClient
ignoreDependencies hint, regressing the CI failure fixed in acd7990.
src/generated/openapi-errors.ts is still only staged by the gitignored
copy:generated prebuild step, so it still doesn't exist on a fresh
checkout and knip's static analysis still can't resolve the import
in sdkErrors.ts without this entry. Reproduced and verified locally by
deleting the staged file before running knip.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1b3a062 dropped @prismaClient from ignoreDependencies based on a knip
"unused config" hint, but that hint only held locally where the generated
Prisma client was already built. Only src/db/prisma/generated/client/sql
is committed to git (see apps/jobnik-manager/.gitignore); the rest of the
client, including its index, is gitignored and generated at build time.
On a fresh checkout knip's static analysis can't resolve @prismaClient
and flags it as an unlisted dependency in ~35 files, failing CI.

Verified by simulating a true fresh checkout (git checkout -- the
generated dir, which restores only the tracked sql/ subfolder) and
running knip against it: fails without this entry, passes with it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@CptSchnitz
CptSchnitz merged commit 18dca64 into master Sep 24, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants