Skip to content

Release v2.2.3 - #24

Merged
kodjunkie merged 17 commits into
masterfrom
release/v2.2.3
Jun 10, 2026
Merged

Release v2.2.3#24
kodjunkie merged 17 commits into
masterfrom
release/v2.2.3

Conversation

@kodjunkie

Copy link
Copy Markdown
Owner

Patch release — fixes broken @nestjs-crud/core subpath exports and restores Swagger metadata under @nestjs/swagger 11.4.3+.

Fixed

  • Subpath exports now resolve from the published tarball. @nestjs-crud/core/cache, @nestjs-crud/core/cursor, and @nestjs-crud/core/query previously threw ERR_PACKAGE_PATH_NOT_EXPORTED or MODULE_NOT_FOUND when imported from a downstream project (broken in 2.2.0–2.2.2). The exports map in packages/core/package.json now correctly maps each subpath to its compiled lib/ counterpart. The @nestjs-crud/core/lib/* deep-import workaround paths continue to work for any consumer who used them.
  • Swagger route metadata survives @nestjs/swagger 11.4.3+. An exports map change in that release blocked the internal ./dist/constants deep-require used by this package's Swagger integration. The import now resolves correctly against the published exports.
  • qs is a direct dependency of @nestjs-crud/core. Previously the package relied on qs being hoisted transitively from other dependencies, which fails under pnpm and Yarn PnP with strict hoisting disabled. qs is now declared explicitly in @nestjs-crud/core's dependencies.

Maintenance

Dependency sweep closing 8 dev-tree Dependabot alerts via lockfile dedupe; a new pack-and-install smoke gate in CI permanently guards the publish layout so subpath-export regressions are caught before a release ships.

kodjunkie added 17 commits June 10, 2026 15:56
- packages/core/src/types/query-filter-option.type.ts: import from '@nestjs-crud/request'
- packages/core/src/interfaces/auth-options.interface.ts: import from '@nestjs-crud/request'
- packages/core/src/interfaces/query-options.interface.ts: import from '@nestjs-crud/request'
- Root CHANGELOG.md: add ### Fixed entry describing the exports map addition
  and internal declaration import cleanup; names affected versions 2.2.0-2.2.2
  and documents the lib/* workaround passthrough
- packages/core/CHANGELOG.md: insert new ## [Unreleased] block above ## [2.2.2]
  with the same plain-English description scoped to the core package
- Create scripts/smoke-pack.js (CJS, Node built-ins only)
- Pack all 7 workspace packages via npm pack to a PID-suffixed os.tmpdir
- Install into a temp project outside the monorepo with npm overrides
- Check require.resolve for @nestjs-crud/core root, /cache, /cursor, /query, /lib/cache, /lib/cursor, /lib/query and all 6 other package roots
- Exit non-zero on any resolution failure; cleanup on exit + SIGINT
- Wire "smoke:pack": "node scripts/smoke-pack.js" in root package.json
Write the child check script to a temp file instead of passing it via
node -e to avoid shell quoting / newline double-escape issues that caused
a SyntaxError in Node's eval path.
@nestjs/swagger 11.4.3 added an exports map exposing only the root entry,
./plugin, and ./package.json.  The four swagger helpers each called
safeRequire('@nestjs/swagger/dist/constants') which now throws
ERR_PACKAGE_PATH_NOT_EXPORTED; safeRequire swallowed the error and returned
null, causing every helper to take the no-swagger degradation path and emit no
OpenAPI metadata on generated CRUD routes.

- Add packages/core/src/crud/swagger/swagger-constants.ts as the single source
  of truth for swaggerConst, with three-state resolution:
  1. Deep require '@nestjs/swagger/dist/constants' (wins on older swagger or
     any version whose exports map still permits ./dist/*)
  2. Inlined-literal fallback when the deep path is blocked but root swagger is
     installed (the 11.4.3+ exports-map case)
  3. null when swagger is genuinely not installed (no-swagger degradation
     preserved unchanged)
- Rewire responses.helper.ts, operations.helper.ts, params.helper.ts, and
  examples.helper.ts to import swaggerConst from ./swagger-constants instead of
  each deep-requiring directly; responses.helper.ts re-exports swaggerConst
  under the same name to keep the swagger.helper.ts re-export chain intact
- Inlined DECORATORS key strings copied verbatim from dist/constants.js;
  no top-level API_EXTRA_MODELS added to the fallback (latent quirk preserved)
…map fix

- Export SwaggerConstants interface from swagger-constants.ts to satisfy
  TS4023 (exported variable cannot be named without the type being exported)
- Add plain-English ### Fixed entries under [Unreleased] in the root and
  packages/core CHANGELOG files describing the swagger exports-map fix
- Add exports field with 9 keys: root (.), /cache, /cursor, /query,
  /package.json, explicit /lib/cache, /lib/cursor, /lib/query, /lib/* wildcard
- types condition listed before default in every condition object (TS requirement)
- Explicit ./lib/cache, ./lib/cursor, ./lib/query entries required alongside
  ./lib/* wildcard — wildcard alone does not resolve extensionless directory requires
- typesVersions block maps cache/cursor/query subpaths for legacy moduleResolution:node consumers
- main and typings fields preserved for non-exports-aware resolvers
…gate

- New top-level smoke job runs yarn smoke:pack on every PR to master
- Bootstrap mirrors the parity job exactly: checkout@v5, corepack enable,
  yarn set version 4.12.0, yarn install --immutable, yarn build
- No needs: dependency — runs in parallel with parity/test/test-no-swagger
- yarn build precedes yarn smoke:pack so lib/ is current at pack time
- Verified locally: all 13 specifiers PASS after exports map fix (EXIT=0)
…nted deep paths

The unreleased entries claimed no consumer migration is required, but the
new exports map disables CJS extension search and directory-index
resolution for wildcard targets. Only the explicit /lib/cache, /lib/cursor,
/lib/query entries and exact-extension file paths under lib/ resolve;
other extensionless or directory deep imports (never public API) now fail.
Both CHANGELOG entries now state this restriction explicitly.
… constants in CI

With @nestjs/swagger 11.4.3+ installed, the inlined fallback is the active
path everywhere in this repo, and its only behavioral guard
(swagger-openapi-snapshot.spec.ts) ran in no CI job — parity filters to
packages/core/test/parity, the test matrix runs per-adapter configs, and
the no-swagger sentinel skips the swagger specs. Upstream key drift would
silently strip OpenAPI metadata again.

- New swagger-constants-fallback.spec.ts deep-equals INLINED_FALLBACK
  against the real dist/constants.js, loaded by absolute path via
  require.resolve on package.json (absolute requires bypass exports maps).
- INLINED_FALLBACK is now an @internal export so the spec can reach it.
- The smoke CI job gains a bare-root-jest step (core/request/util suites,
  no DB needed) so the guard — and the rest of the root suite — actually
  runs in CI; bootstrap is unchanged.
- axios 1.15.2 → 1.17.0 (no vulnerable 1.15.2 copy remains)
- tmp 0.2.5 → 0.2.7 (no vulnerable 0.2.5 copy remains)
- qs 6.15.0 → 6.15.2 everywhere (orphan qs@6.15.0 descriptor removed)
- root dependencies.qs exact pin removed (orphan; only @nestjs-crud/request imports qs)
- @types/qs devDep retained; resolutions block unchanged

Closes GHSAs:
  axios: GHSA-j5f8-grm9-p9fc, GHSA-p92q-9vqr-4j8v, GHSA-hfxv-24rg-xrqf,
         GHSA-777c-7fjr-54vf, GHSA-654m-c8p4-x5fp
  tmp:   GHSA-ph9p-34f9-6g65
  qs:    GHSA-q8mj-m7cp-5q26
Closes GHSA-q8mj-m7cp-5q26 (qs prototype pollution) in the standalone
examples/typeorm-demo manifest. Scoped dedupe resolves the transitive qs
descriptors (^6.14.0, ^6.14.1, ^6.15.2) to the patched 6.15.2.

uuid@11.1.0 untouched (GHSA-w5hq-g745-h8pq deferred — typeorm peer ^11 +
pure-ESM ts-jest blocker). No package.json manifest changes.
CrudRequestInterceptor imports qs at runtime but core never declared it;
resolution relied on hoisting @nestjs-crud/request's copy. Breaks under
pnpm strict isolation and Yarn PnP. Affects all previously published
versions; surfaced by code review after the root-level qs pin was
dropped during the dependency sweep.
…st config

swagger-constants-fallback.spec.ts loads the real @nestjs/swagger
dist/constants.js via an absolute-path require (intentionally bypassing
the exports map). When the no-swagger sentinel replaces @nestjs/swagger
with the throwing stub, require.resolve on package.json resolves to
the stub path and the subsequent dist/constants.js require fails with
MODULE_NOT_FOUND.

The spec belongs in the smoke job (bare root jest with swagger installed)
not in the no-swagger sentinel. Add it to testPathIgnorePatterns.
@kodjunkie
kodjunkie merged commit bc67c7c into master Jun 10, 2026
12 checks passed
@github-actions

Copy link
Copy Markdown

Packages with version v2.2.3 have been released

@kodjunkie
kodjunkie deleted the release/v2.2.3 branch June 10, 2026 18:14
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