Skip to content

fix(turbo): declare plugin-auth's typecheck dependency on its own build - #12043

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-11620-plugin-auth-examples-typecheck-dep
Aug 25, 2026
Merged

fix(turbo): declare plugin-auth's typecheck dependency on its own build#12043
yinlianghui merged 1 commit into
mainfrom
claude/issue-11620-plugin-auth-examples-typecheck-dep

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#11620

The defect, reproduced

@objectstack/plugin-auth's typecheck script runs two tsc programs:

"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.examples.json"

The second checks examples/basic-usage.ts, whose line 13 imports the package by its own name. That resolves through the package's exports to ./dist/index.d.ts — so the program's inputs include an artifact the package itself produces, and nothing in the task graph said so. The generic typecheck task depends on ^build, the dependencies' build, never the package's own.

Measured on this branch's merge base, in a fresh worktree with OS_SKIP_DTS unset and packages/plugins/plugin-auth/dist/ absent:

$ pnpm exec turbo run typecheck --filter=@objectstack/plugin-auth --concurrency=2
...
@objectstack/plugin-auth:typecheck: examples/basic-usage.ts(13,28): error TS2307: Cannot find module '@objectstack/plugin-auth' or its corresponding type declarations.
Tasks: 25 successful, 26 total
Failed: @objectstack/plugin-auth#typecheck
TURBO_EXIT=2

Turbo built 25 dependency packages via ^build and never built plugin-auth; dist/ was still absent when the run ended.

Why this repair, and not the card's other two

The card listed three candidate repairs and deliberately declined to pick. Triage picked by deferring to whichever convention the repo already uses. Measured against the tree:

CandidatePrecedent in this tree
Declare it in the task graphThree.@objectstack/metadata#test, @objectstack/cli#test and test:e2e all carry dependsOn: ["build"] — self, no caret
Point the examples program at src/ via a paths mappingNone that is self-referential. Ten tsconfigs carry paths; every entry maps another package's name to that package's src/, redirects a third-party type root (knex), or is a within-app alias. Not one maps a package's own name to its own src/
Rename the script, e.g. typecheck:examplesNone. No typecheck:-prefixed variant exists in any workspace package.json. The convention for a second tsc program is to chain it into the single typecheck script with && — thirteen packages do exactly that (nine tsconfig.scripts.json, three tsconfig.test.json, one tsconfig.examples.json), which is the shape plugin-auth already has

Only the first follows a convention this repo actually has; the other two would each establish a new one.

That also settles the card's semantic question in the direction that preserves today's behaviour: the examples keep type-checking against the published surface, and the ordering requirement simply becomes explicit. The paths precedents point the other way by design — packages/qa/downstream-contract uses one specifically to move a dependency off dist and onto src, and its own comment records that without the rule the types came from dist — but none of them is self-referential, so nothing in the tree supports doing that to a package's own name.

The change

Five lines in turbo.json, next to the package's existing #test entry:

"@objectstack/plugin-auth#typecheck": {
"dependsOn": ["build"],
"outputs": [],
"inputs": ["$TURBO_DEFAULT$", "!dist/**", "!coverage/**", "!.turbo/**"]
}
  • dependsOn: ["build"] alone is sufficient: the build task itself depends on ^build, so the dependency closure stays ordered ahead. Both existing self-build entries also list only ["build"].
  • inputs is repeated verbatim from the generic typecheck task because package-scoped entries in this file do not merge with the generic definition — every existing package-scoped entry repeats it in full.
  • !dist/** stays. Ordering is now carried by the task dependency, which contributes the build's hash; hashing dist/ content as an input is neither needed nor what the convention does.

After

Same command, same worktree:

@objectstack/plugin-auth:build: DTS dist/index.d.ts 272.91 KB
@objectstack/plugin-auth:typecheck: cache miss, executing eecbc2499b926593
@objectstack/plugin-auth:typecheck: > tsc --noEmit && tsc --noEmit -p tsconfig.examples.json
Tasks: 27 successful, 27 total
TURBO_EXIT=0

26 tasks to 27 — the declaration added exactly one node to the graph, and both the build and the typecheck were real executions, not cache hits. Turbo's own resolved graph agrees:

resolvedTaskDefinition.dependsOn: ["build"]
own build in dependencies: true

CI cost is unchanged: the lint job builds the workspace before type-checking, so plugin-auth's build is a cache hit there.

Gates

Derived at the final commit 2e70f26c1 with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack — no hand-written path list; the script takes the change set from the merge base itself.

  • change set: turbo.json, one path
  • verdict: "No check family names the given paths in its own source, and no workflow's path filter schedules one for them." — zero matched families

Run anyway, as visibly implicated by the edit:

GateExitIts own verdict line
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 6672 text file(s) -- 6672 tracked, 0 untracked-not-ignored; skipped 6 binary; no raw ASCII control bytes).
pnpm check:cross-package-test-inputs0OK: 16 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.
turbo run typecheck --filter=@objectstack/plugin-auth0Tasks: 27 successful, 27 total

The second parses turbo.json directly in its Layer B, which is why it is here; it inspects only pkg#test tasks, and this change adds a #typecheck task.

Scope


Generated by Claude Code

`@objectstack/plugin-auth`'s `typecheck` script runs a second tsc program
(`tsconfig.examples.json`) over `examples/basic-usage.ts`, which imports the
package by its own name. That resolves through `exports` to
`./dist/index.d.ts`, so the program's inputs include an artifact the package
itself produces -- and nothing declared it.
The generic `typecheck` task depends on `^build` (dependencies' build), never
the package's own, so `turbo run typecheck --filter=@objectstack/plugin-auth`
on a tree without the package's `dist/` fails with TS2307 on the example.
Declared with a package-scoped task carrying `dependsOn: ["build"]` -- the
shape the repo already uses for a task that needs its own package's build
output (`@objectstack/metadata#test`, `@objectstack/cli#test`, `test:e2e`).
Own `build` transitively pulls `^build`, so dependency ordering is unchanged.
@yinlianghuiyinlianghui added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 25, 2026 — with Claude
@yinlianghui
yinlianghui marked this pull request as ready for review August 25, 2026 06:50
@yinlianghui
yinlianghui added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 3def551Aug 25, 2026
27 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-11620-plugin-auth-examples-typecheck-dep branch August 25, 2026 07:09
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] @objectstack/plugin-auth's typecheck cannot pass unless the package's OWN dist/ is built, and no task dependency says so

2 participants

@yinlianghui@claude