Skip to content

Fix mikro-orm decorator failures under bun 1.3, and pin bun in CI - #10

Merged
sanketsahu merged 2 commits into
mainfrom
fix/decorators-under-bun-1.3
Aug 3, 2026
Merged

Fix mikro-orm decorator failures under bun 1.3, and pin bun in CI#10
sanketsahu merged 2 commits into
mainfrom
fix/decorators-under-bun-1.3

Conversation

@sanketsahu

Copy link
Copy Markdown
Collaborator

Fixes the red main. Not caused by any recent change — these failures were always there, and CI pointing at master (which never receives pushes in this fork) is what kept them invisible. The first run CI has ever had immediately found them.

The failure

3 tests, all in the mikro-orm sample:

TypeError: undefined is not an object (evaluating 'target.constructor')
  at node_modules/@mikro-orm/core/decorators/PrimaryKey.js:9:74
  at samples/mikro-orm/simple.ts:6:8

They pass locally, which is why I wrongly reported the steps as green in #9 — I verified against my bun 1.2.21, and CI's setup-bun@v1 downloads latest. I reproduced CI exactly by fetching bun 1.3.14 into a temp dir: 1249 pass / 3 fail, matching the run.

Root cause: a bun regression, reduced to 10 lines

// base.json
{ "compilerOptions": { "alwaysStrict": true } }
// tsconfig.json
{ "extends": "./base.json", "compilerOptions": { "experimentalDecorators": true } }
function legacy(target: any, prop?: string) { console.log(typeof target) }
class C { @legacy x = 1 }
bun with extends without extends
1.2.21 object object
1.3.14 undefined object

bun 1.3.x reads experimentalDecorators only from the base of an extends chain and ignores the child's value, so it applied modern TC39 decorator semantics to decorators written against the legacy protocol. Under TC39 a field decorator gets (value, context) with value undefined — hence target.constructor throwing. mikro-orm 5's decorators are legacy.

The fix, and why not the obvious alternatives

experimentalDecorators: true declared in tsconfig.deno.json, the base of the chain. Duplicated with tsconfig.json, which tsc resolves identically either way.

Things I tried and rejected, with reasons:

  • Drop the extends. Works, but I checked tsc --showConfig first: that base is where strict, noImplicitAny, strictNullChecks, strictFunctionTypes and 25 other options come from. Dropping it silently disables strict mode across the codebase, which would hide real type errors. Not worth it.
  • A tsconfig.json beside the sample (samples/ and samples/mikro-orm/). No effect — bun resolves tsconfig from the cwd, not from the file.
  • Strip the // comments from the base config so it's strict JSON. No effect; it isn't a parse failure.

Also: bun is pinned in CI

setup-bun@v1 with no version downloads latest, which means a bun release can break CI with no change of ours — precisely what happened here. Pinned to 1.3.14, which I've verified.

Verified

Under both bun versions, since that was the gap last time:

1.2.21 1.3.14
bun typecheck clean clean
bun test 1266 pass / 0 fail 1266 pass / 0 fail

Plus build:deno a no-op and the Deno port check 9/9, so nothing regressed there.

sanketsahu and others added 2 commits August 3, 2026 18:50
… in CI

The first CI run this fork has ever had went red: 3 failures in the mikro-orm
sample, all `TypeError: undefined is not an object (evaluating
'target.constructor')` from @mikro-orm/core's @PrimaryKey. They pass locally and
are unrelated to any recent change - CI pointing at `master`, which never receives
pushes here, is what kept them invisible.

The cause is a bun regression, reduced to:

    base.json      { "compilerOptions": { "alwaysStrict": true } }
    tsconfig.json  { "extends": "./base.json",
                     "compilerOptions": { "experimentalDecorators": true } }

Under bun 1.3.14 a legacy decorator on a class field receives `undefined` as its
target; drop the `extends` and it receives the object. bun reads
experimentalDecorators only from the base of an extends chain and ignores the
child's value, so it applied modern TC39 semantics to decorators written against
the legacy protocol. mikro-orm 5's decorators are legacy, hence the sample.
bun 1.2.21, which is what I had locally, is unaffected.

Declaring it in tsconfig.deno.json - the base of the chain - fixes it. Duplication
with tsconfig.json, which tsc resolves identically either way, and preferable to
the alternatives: dropping the `extends` also drops strict, noImplicitAny and
strictNullChecks, since that base is where they come from, and a per-directory
tsconfig beside the sample has no effect because bun resolves from the cwd.

CI's bun is pinned rather than `latest`, since an unpinned toolchain lets a bun
release break CI with no change of ours - which is exactly what happened.

Verified under both 1.2.21 and 1.3.14: typecheck clean, 1266 pass / 0 fail, and
the Deno port check still 9/9 with build:deno a no-op.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CodeQL was the 2020 template inherited from upstream and had never run
successfully here, so nothing flagged how far behind it was. Two hard failures:

  Error: This version of the CodeQL Action was deprecated on January 18th, 2023,
         and is no longer updated or supported.
  Error: Encountered an error while trying to determine feature enablement:
         HttpError: Resource not accessible by integration

So: codeql-action v1 -> v3, and a permissions block, which is what the second
error is about - uploading results needs security-events: write, and the action
reads workflow metadata to correlate runs. The default token grants neither.

Also drops the Autobuild step. That exists for compiled languages; CodeQL extracts
JS/TS straight from source, so it only added time and a way to fail. The language
is now 'javascript-typescript', the current name for what used to be 'javascript'.

actions/checkout v2 -> v4 in both workflows, which clears the Node 20 deprecation
warnings the runner emits.

No change to what is analysed or tested, only to the machinery running it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sanketsahu
sanketsahu merged commit 3efea23 into main Aug 3, 2026
3 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.

1 participant