Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
9af1835
docs: add v5 monorepo split & revival design spec
Isqanderm Aug 24, 2026
2cb2415
docs: add Phase 0-1 implementation plan (cleanup + monorepo split)
Isqanderm Aug 24, 2026
b046456
chore: remove stale release cruft, tracked IDE dirs, committed benchm…
Isqanderm Aug 24, 2026
7979553
chore: switch to pnpm workspace root, drop semantic-release deps
Isqanderm Aug 24, 2026
6e68e57
refactor: extract @om-data-mapper/core package
Isqanderm Aug 24, 2026
e65525b
refactor: extract @om-data-mapper/class-transformer package
Isqanderm Aug 24, 2026
96768d6
refactor: extract @om-data-mapper/class-validator package
Isqanderm Aug 24, 2026
e551e6e
refactor: use workspace devDependency + vitest alias for cross-packag…
Isqanderm Aug 24, 2026
36adfaa
feat: add om-data-mapper meta-package preserving v4 export surface
Isqanderm Aug 24, 2026
b6d6500
chore: wire root vitest projects, coverage, eslint and typedoc to mon…
Isqanderm Aug 24, 2026
a848a3b
chore: replace semantic-release with changesets
Isqanderm Aug 24, 2026
55bced7
ci: rewrite pipelines for pnpm monorepo, changesets release, stub ben…
Isqanderm Aug 24, 2026
678a3bf
fix: add @types/node devDependency — pnpm isolated linker exposed mis…
Isqanderm Aug 24, 2026
07f09c2
style: format repository with prettier (new CI gate)
Isqanderm Aug 24, 2026
dd2cf7b
fix: disarm release publish path until Phase 5; update CONTRIBUTING t…
Isqanderm Aug 24, 2026
c60ce55
feat(class-validator): support function-form message in compat layer
Isqanderm Aug 24, 2026
3810a78
feat(class-validator): implement skipMissingProperties/skipNullProper…
Isqanderm Aug 24, 2026
2a688e7
feat(class-validator): implement stopAtFirstError
Isqanderm Aug 24, 2026
fb83c0d
fix(class-validator): trim stopAtFirstError errors after async tasks …
Isqanderm Aug 24, 2026
b1645e0
feat(class-validator): implement whitelist and forbidNonWhitelisted
Isqanderm Aug 24, 2026
3f6859b
feat(class-validator): implement forbidUnknownValues
Isqanderm Aug 24, 2026
780e31e
feat(class-validator): support validationError target/value stripping…
Isqanderm Aug 24, 2026
567e320
fix(class-validator): wrap forbidUnknownValues early return in stripE…
Isqanderm Aug 24, 2026
4aa3906
feat(class-validator): add registerDecorator and getMetadataStorage c…
Isqanderm Aug 24, 2026
63c6e31
feat(class-transformer): implement enableImplicitConversion; drop dea…
Isqanderm Aug 24, 2026
623d95d
docs: add honest class-validator/class-transformer compat tables; cha…
Isqanderm Aug 24, 2026
fe7c092
docs: add Phase 2 implementation plan (compat honesty)
Isqanderm Aug 24, 2026
3017497
fix(class-validator): unwrap composite constraints in function messag…
Isqanderm Aug 24, 2026
316d6a7
chore(benchmarks): delete fabricated results, no-op comparison and de…
Isqanderm Aug 24, 2026
fec71ee
feat(benchmarks): rebuild as workspace package on vitest bench; fix c…
Isqanderm Aug 24, 2026
732b876
docs: add Phase 3 implementation plan (honest benchmarks)
Isqanderm Aug 24, 2026
c50c559
feat(benchmarks): honest validation comparison using om's own decorators
Isqanderm Aug 24, 2026
d95612d
feat(benchmarks): honest transformation comparison vs class-transformer
Isqanderm Aug 24, 2026
05c680b
docs(benchmarks): honest README; ci: un-masked benchmark workflow
Isqanderm Aug 24, 2026
67e0d38
chore(benchmarks): fix stale README reference; drop dead tinybench dep
Isqanderm Aug 24, 2026
d8d9457
docs: extract troubleshooting guide from root README into docs/
Isqanderm Aug 25, 2026
99ecaf8
docs: qualify drop-in claim in troubleshooting guide
Isqanderm Aug 25, 2026
ee933b8
docs: add v4-to-v5 migration guide
Isqanderm Aug 25, 2026
583fa13
docs: honest docs pass - complete index, real paths and APIs, no fabr…
Isqanderm Aug 25, 2026
055aeb7
docs: fix leftover "fastest" superlative in validation-jit-internals.md
Isqanderm Aug 25, 2026
24058bb
fix(examples): rebuild as workspace package importing published packa…
Isqanderm Aug 25, 2026
7ba4b04
fix(examples): fix review round 1 - README run command, composition r…
Isqanderm Aug 25, 2026
956ca34
docs: rewrite root README - honest, ~300 lines, class-validator section
Isqanderm Aug 25, 2026
7698b61
docs: add per-package READMEs for npm
Isqanderm Aug 25, 2026
868c7de
docs: cross-reference audit and CHANGELOG unreleased pointer
Isqanderm Aug 25, 2026
bcbe1ed
docs(ru): sync Russian docs - translate compat tables, migration guid…
Isqanderm Aug 25, 2026
81ed770
docs: describe class-transformer adapter honestly - interpreted metad…
Isqanderm Aug 25, 2026
7507b3a
docs: add Phase 4 implementation plan (documentation)
Isqanderm Aug 25, 2026
952ef22
docs: purge fabricated performance figure from SECURITY.md
Isqanderm Aug 25, 2026
1672308
docs: fix audit findings - dead always option, real codegen examples,…
Isqanderm Aug 25, 2026
4572c3e
docs: add PR #37 review-fixes implementation plan
Isqanderm Aug 25, 2026
41ff929
fix(class-validator): stopAtFirstError trim must check own keys, not …
Isqanderm Aug 25, 2026
2ab796b
fix(class-validator): return no-metadata for null-prototype objects i…
Isqanderm Aug 25, 2026
6c29416
fix(class-validator): stop unbounded constraint growth - one constrai…
Isqanderm Aug 25, 2026
e46d78e
fix(class-validator): key metadata via Symbol.for; add changeset for …
Isqanderm Aug 25, 2026
b57d42e
fix(class-validator): registerDecorator - enforce all registrations, …
Isqanderm Aug 25, 2026
461a304
fix(class-validator): options-aware dedup, upstream name precedence, …
Isqanderm Aug 25, 2026
225e726
fix(class-transformer): enableImplicitConversion coerces array elemen…
Isqanderm Aug 25, 2026
0f4e567
fix(class-transformer): static imports in method decorators - require…
Isqanderm Aug 25, 2026
5a219d4
fix(core): JSON-escape all keys and paths in generated mapper code - …
Isqanderm Aug 25, 2026
c500a26
docs(core): purge fabricated performance figures from JSDoc
Isqanderm Aug 25, 2026
937af72
fix(packaging): ship LICENSE in every published tarball - files decla…
Isqanderm Aug 25, 2026
8ade54e
test(om-data-mapper): import via real exports map, not vitest-alias-o…
Isqanderm Aug 25, 2026
f82e9b1
docs: fix overselling hoisting claim, sync stale codegen samples with…
Isqanderm Aug 25, 2026
c55293a
test(core): cover quote-bearing target field names in codegen escaping
Isqanderm Aug 25, 2026
188cee3
docs(core): fix codegen quote self-contradiction, drop unverifiable b…
Isqanderm Aug 25, 2026
0da556d
fix(core): drop unreachable legacy Mapper re-export; make ESM simulat…
Isqanderm Aug 25, 2026
278200c
ci: typecheck examples and benchmarks - the exact rot class that let …
Isqanderm Aug 25, 2026
838548e
test(class-transformer): add ESM smoke test - the gap that let requir…
Isqanderm Aug 25, 2026
8f2a63c
docs(om-data-mapper): tighten ESM simulation's success summary - two …
Isqanderm Aug 25, 2026
8c6fdb8
docs: stop presenting the unreachable legacy Mapper.create() as safe …
Isqanderm Aug 25, 2026
2600809
style: format review-fixes plan document
Isqanderm Aug 25, 2026
d1c1d30
test(class-validator): seed the property tests so failures are reprod…
Isqanderm Aug 26, 2026
57295a5
test(om-data-mapper): make the memory-leak tests actually measure ret…
Isqanderm Aug 26, 2026
5e66f40
docs: publish a dated benchmark snapshot in the README
Isqanderm Aug 26, 2026
aae5aa9
refactor: move scoped packages to the @tech-pioneer npm namespace
Isqanderm Aug 27, 2026
a9e6608
chore: retarget changeset frontmatter to the new package names
Isqanderm Aug 27, 2026
4946936
docs: update package names to @tech-pioneer/data-mapper-*
Isqanderm Aug 27, 2026
977a648
fix(class-transformer): apply nested @Exclude in the class->plain dir…
Isqanderm Aug 27, 2026
98c8ddf
feat(class-validator): implement the each option
Isqanderm Aug 27, 2026
f7a1d1d
docs: record the each option in both compat tables
Isqanderm Aug 27, 2026
a45ca6c
fix(class-validator): validate a subclass's own constraints
Isqanderm Aug 27, 2026
fc586d1
style: format the inheritance changeset
Isqanderm Aug 27, 2026
6f1cf5a
fix(class-validator)!: fail a constraint when the value is the wrong …
Isqanderm Aug 27, 2026
fe8a366
fix(class-validator)!: match upstream error keys and rejection shape
Isqanderm Aug 27, 2026
5996943
fix(class-validator)!: correct group filtering and make always work
Isqanderm Aug 27, 2026
3c5cbf4
style: format the groups changeset
Isqanderm Aug 27, 2026
189faca
feat(class-validator): export IsUrl and tighten IsBase64 padding
Isqanderm Aug 27, 2026
c7aa22f
feat(class-validator)!: name the property in default messages
Isqanderm Aug 27, 2026
ae022ab
fix(class-transformer)!: make classToClass a real deep clone
Isqanderm Aug 27, 2026
cc6e10b
feat(class-validator): add the 21 decorators upstream had and this pa…
Isqanderm Aug 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
781 changes: 0 additions & 781 deletions .augment/rules/rule-release.md

This file was deleted.

32 changes: 32 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Changesets

## What are changesets?

Changesets are a way of managing and documenting changes to a monorepo. They allow teams to:

- Document changes with clear descriptions
- Manage versioning across multiple packages
- Automate changelog generation
- Coordinate releases

## Creating a changeset

To create a changeset, run:

```bash
pnpm changeset
```

This will prompt you to:

1. Select which packages have changed
2. Determine the type of change (major, minor, or patch)
3. Write a summary of the change

## Before releasing

Always ensure your changes have accompanying changesets. You can check the status with:

```bash
pnpm changeset status
```
9 changes: 9 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "Isqanderm/data-mapper" }],
"commit": false,
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
11 changes: 11 additions & 0 deletions .changeset/feat-each-option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@tech-pioneer/data-mapper-class-validator': minor
---

Implement `ValidationOptions.each`, which was previously accepted nowhere and silently skipped per-element validation.

`@IsString({ each: true })` and every other decorator now apply their constraint to each element of an array or `Set` instead of to the property value. Behaviour follows class-validator 0.14.4: a failing element produces one error for the property (not one per element), the error's `value` is the whole collection, an empty collection passes, and a value that is neither an array nor a `Set` is left unvalidated.

Default messages for an `each` constraint are prefixed — `each value must be at least 5 characters`. Upstream's prefix is `each value in `, which runs on into the property name upstream puts in every message; this package's messages carry no property name, so the prefix stops at `each value`. A message supplied by the caller is used exactly as written, as upstream does.

Constraint deduplication now takes `each` into account, so `@MinLength(5)` and `@MinLength(5, { each: true })` on one property stay two constraints instead of collapsing into one.
23 changes: 23 additions & 0 deletions .changeset/feat-message-property-name.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@tech-pioneer/data-mapper-class-validator': major
---

**Breaking:** default messages now name the property they are about.

`@MinLength(3)` on `username` produced `must be at least 3 characters`. Anything showing `error.constraints` to a person — a form, an API response, a log line — had to pair the sentence back up with `error.property` by hand to say which field it meant. Upstream writes `username must be longer than or equal to 3 characters`; messages now carry the same subject: `username must be at least 3 characters`.

Under `each` the property follows upstream's prefix: `each value in tags must be at least 5 characters` (it previously stopped at `each value`, because there was no property name for the preposition to lead into).

A message supplied by the caller — string or function — is untouched.

Five defaults opened with their own noun and would have read as `lat latitude must be…` once prefixed, so they were reworded:

| decorator | before | now |
| -------------- | ------------------------------------------------- | --------------------------------------- |
| `@IsLatitude` | `latitude must be a number between -90 and 90` | `must be a number between -90 and 90` |
| `@IsLongitude` | `longitude must be a number between -180 and 180` | `must be a number between -180 and 180` |
| `@ArrayUnique` | `all elements must be unique` | `must contain only unique values` |
| `@MinDate` | `minimal allowed date is …` | `must not be before …` |
| `@MaxDate` | `maximal allowed date is …` | `must not be after …` |

The wording of the sentences still differs from upstream's in most cases — only the subject is matched. Three of the six messages compared came out identical to upstream anyway (`must be an email`, `should not be empty`, `must contain at least N elements`).
17 changes: 17 additions & 0 deletions .changeset/feat-missing-decorators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
'@tech-pioneer/data-mapper-class-validator': minor
---

Add the 21 decorators upstream ships that this package did not: `IsAscii`, `IsBase32`, `IsBase58`, `IsBooleanString`, `IsByteLength`, `IsFirebasePushId`, `IsFullWidth`, `IsHSL`, `IsHalfWidth`, `IsHash`, `IsHexadecimal`, `IsISRC`, `IsISSN`, `IsMilitaryTime`, `IsMultibyte`, `IsNumberString`, `IsOctal`, `IsRgbColor`, `IsSurrogatePair`, `IsTaxId` and `IsVariableWidth`.

Every one reports under the key upstream reports, follows the package's type rules (a value that is not a string fails rather than passing), and supports `each`, `groups`, `always` and a custom message like the rest. Comparing runtime exports, no decorator upstream exports is missing here any more.

Behaviour was measured against class-validator 0.14.4 rather than assumed, which is how these landed the way they did:

- `IsFirebasePushId` reports under `IsFirebasePushId` — capitalised, unlike every other key.
- `IsRgbColor` rejects `rgb(0, 0, 0)`: spaces between components are not allowed.
- `IsByteLength` measures UTF-8 bytes, not characters, so `'é'` counts as two.
- `IsBase58` accepts `abc`; `IsAscii` rejects the empty string; `IsNumberString` rejects exponent notation.
- `IsISSN` verifies the mod-11 check digit, so `0378-5954` fails where `0378-5955` passes.

Two limitations, both marked in the compat table: `IsTaxId` recognises only the `en-US` format (upstream takes a locale), and `IsHash` takes the algorithm name but none of the further options.
16 changes: 16 additions & 0 deletions .changeset/fix-class-to-class-deep-clone.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@tech-pioneer/data-mapper-class-transformer': major
---

**Breaking:** `classToClass` / `instanceToInstance` now produce a deep clone, and `@Transform` runs once instead of twice.

It was a `classToPlain` → `plainToClass` round trip carrying the `'classToClass'` transformation type through both legs. Neither leg recursed, because each descends only for its own direction, so nested instances and arrays came out shared with the source — mutating the clone mutated the original. `@Transform` ran on both legs, so a `value + 1` transform produced `value + 2`.

It is now a single recursive pass. A nested value's class is taken from the value itself rather than from `@Type`, matching upstream, which clones a nested instance back into its own class whether or not the property carries one. `Date` is cloned rather than walked as a plain object, and `Map` / `Set` keep their type instead of collapsing to `{}`.

Verified against class-transformer 0.5.1 across nested cloning, class preservation, arrays, Dates, `@Transform` call count and result, and the value an excluded property ends up with: no differences.

Two behaviours worth stating because they are easy to mistake for bugs, and both match upstream:

- `@Exclude()` does **not** remove a property in this direction, unlike class→plain.
- The target is built with `new`, and an excluded property is never copied onto it, so it holds whatever its field initializer gives it rather than the source's value.
11 changes: 11 additions & 0 deletions .changeset/fix-constraint-inheritance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@tech-pioneer/data-mapper-class-validator': patch
---

A subclass now validates the constraints it declares, not just the ones it inherits.

Validation metadata lives on the constructor, and the lookup that created it did not check for an _own_ property. A subclass reaches its parent's metadata through the static prototype chain, so `class Child extends Parent` wrote its constraints into `Parent`'s map — and since compiled validators are cached by `metadata.target`, `Child` was then served `Parent`'s validator. Its own constraints never ran and no error was reported for them.

Whether this happened depended on instantiation order: if the subclass was constructed first it created the map and worked, if the parent was constructed first the subclass silently validated only inherited fields. A base DTO with shared fields — the ordinary NestJS arrangement — hits the broken order.

Each class now gets its own metadata. Nothing is merged from the parent, because TC39 field initializers run for the whole hierarchy when a subclass is constructed, so inherited constraints are already registered against the subclass.
19 changes: 19 additions & 0 deletions .changeset/fix-error-keys-and-reject-shape.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
'@tech-pioneer/data-mapper-class-validator': major
---

**Breaking:** error keys and the `validateOrReject` rejection value now match class-validator 0.14.4.

Consumers read `error.constraints.isUrl` and `catch (errors) { errors.map(…) }`. Both were spelled differently here, so code migrated from upstream read `undefined` and carried on — the failure surfaced later, somewhere else.

Fourteen of 48 measured decorators reported a key upstream does not use. Ten were acronym casing: `isURL` → `isUrl`, `isUUID` → `isUuid`, `isJSON` → `isJson`, `isIP` → `isIp`, `isFQDN` → `isFqdn`, `isISO8601` → `isIso8601`, `isJWT` → `isJwt`, `isMACAddress` → `isMacAddress`, `isISIN` → `isIsin`, `isISBN` → `isIsbn`.

Four reported another constraint's key entirely:

- `@Length` emitted a `minLength` and a `maxLength` constraint. It is now one `isLength` constraint, reported under that key, and `max` is optional as upstream has it.
- `@IsDateString` delegated to `@IsISO8601` and inherited its key. It now reports `isDateString`.
- `@IsPositive` was implemented as `min: 0.000001` and reported `min`; `@IsNegative` as `max: -0.000001` reporting `max`. Both now test the sign directly and report `isPositive` / `isNegative`. This also fixes the range: `5e-7` is a positive number and was being rejected.

`validateOrReject` now rejects with the `ValidationError[]` itself instead of a `ValidationFailedError` wrapper, so the upstream idiom works. `validateOrRejectSync` — not an upstream API — throws the array too, so the two do not disagree. The `ValidationFailedError` class is still exported but no longer thrown by either.

All 48 decorators measured against upstream now report identical keys.
22 changes: 22 additions & 0 deletions .changeset/fix-groups-and-always.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
'@tech-pioneer/data-mapper-class-validator': major
---

**Breaking:** group filtering now follows class-validator 0.14.4, and `always` works.

The filter was inverted in both directions. A constraint carrying `groups` ran _only_ when the caller passed a matching group, so `validate(dto)` with no options silently skipped it — the opposite of upstream, where no filter means no filtering. And a constraint with no groups ran even under a filter that selected other groups, where upstream skips it.

`always` was declared on every decorator and in `ValidatorOptions`, stored in metadata, and never read by the compiler — so the escape hatch upstream provides for exactly this situation did nothing. It is now honoured, per decorator and as a default for the whole call through `ValidatorOptions.always`.

Measured against upstream (checking which constraint actually ran, since with `forbidUnknownValues` a filtered-away object reports an error of its own that is easy to mistake for the constraint running):

| validate options | constraint in group `g1` | ungrouped | `g1` + always |
| ---------------- | ------------------------ | --------- | ------------- |
| none | runs | runs | runs |
| `groups: []` | runs | runs | runs |
| `groups: ['g1']` | runs | skipped | runs |
| `groups: ['x']` | skipped | skipped | runs |

`@IsOptional({ groups })` used the same inverted rule and is fixed with it: the property counts as optional when no filter is set or when its group is selected. `optionalAlways` (`@IsOptional({ always: true })`), stored and never read, now works too.

`strictGroups` remains unimplemented and is still marked so in the compat table.
11 changes: 11 additions & 0 deletions .changeset/fix-isurl-alias-and-base64.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@tech-pioneer/data-mapper-class-validator': minor
---

Export `IsUrl`, and reject base64 strings whose length is not a multiple of four.

`IsUrl` is how class-validator spells it, and the implementation was already here — only the name was missing, so `import { IsUrl }` failed for anyone migrating. Both spellings now resolve to the same decorator, and the error key was already `isUrl`.

`@IsBase64` accepted `'zz'` and `'abc'`. Its pattern allowed a trailing group of two or three characters with no padding, so any length was permitted. Upstream (validator.js, padding on by default) requires a multiple of four. Verified against upstream across twelve inputs, including the padded, unpadded and malformed forms: no differences remain.

One existing test asserted that `'SGVsbG8gV29ybGQ'` — fifteen characters — is valid base64. Upstream rejects it by default and accepts it only under `IsBase64Options.padding: false`, an option this package does not accept; the test now asserts the rejection.
11 changes: 11 additions & 0 deletions .changeset/fix-nested-class-to-plain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@tech-pioneer/data-mapper-class-transformer': patch
---

`classToPlain` / `instanceToPlain` / `serialize` now descend into nested values, so a nested `@Exclude()` actually runs.

Previously the class->plain direction did not recurse: a nested class instance was copied into the output untouched, carrying every field its own decorators were supposed to remove. A `@Exclude()`d field one level down — the canonical `password` case — reached the serialized output, while the same decorator on a top-level property worked. Nested `@Expose({ name })` renames were dropped for the same reason.

Recursion is not gated on `@Type`: in the class->plain direction the class is known from the value itself, matching class-transformer 0.5.1, which recurses whether or not the property carries a `@Type`. `Date` values are passed through rather than expanded, and plain object literals are copied key-for-key, both verified against upstream.

Note that recursion makes a self-referential object graph throw `RangeError: Maximum call stack size exceeded`, exactly as upstream does without `enableCircularCheck` (an option this package does not implement).
13 changes: 13 additions & 0 deletions .changeset/fix-wrong-type-values.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@tech-pioneer/data-mapper-class-validator': major
---

**Breaking:** a constraint now fails when the value is not of the type it measures.

The generated checks were written as "if the type fits and the value is bad, report an error", so a value of the wrong type fell out of the condition and was reported as valid. `@IsEmail()` passed on the number `5`, `@Min(5)` passed on the string `'a'`, `@ArrayMinSize(2)` passed on `'ab'`, and — most consequentially — every one of them passed on `undefined` and `null`. Upstream's predicates return false for a value they cannot measure, which is an error.

61 of the 84 generated checks changed. Behaviour was compared against class-validator 0.14.4 across 46 decorators and six value shapes each: 321 of 322 comparisons now agree (the remaining difference is an unrelated `@IsBase64` regex that is more permissive than upstream's).

**What this means for existing code.** A decorated property with no value is now an error, exactly as upstream treats it. Code that relied on the old silence needs one of the escape hatches upstream provides for the same situation: `@IsOptional()` on the property, or the `skipUndefinedProperties` / `skipNullProperties` / `skipMissingProperties` validator options. All of them are already implemented here and are covered by tests.

`@IsLatitude` and `@IsLongitude` keep accepting both a number and a numeric string, as upstream does; anything else is now an error.
7 changes: 7 additions & 0 deletions .changeset/phase2-class-transformer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@tech-pioneer/data-mapper-class-transformer': minor
---

Implement `enableImplicitConversion` (primitive coercion via `@Type`). Remove dead `ClassTransformOptions` fields: `enableCircularCheck`, `exposeUnsetFields`, `targetMaps`, `enableValidation`.

See `docs/compat-class-transformer.md` for the full compatibility table, including the `enableImplicitConversion` array-of-primitives caveat.
9 changes: 9 additions & 0 deletions .changeset/phase2-class-validator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@tech-pioneer/data-mapper-class-validator': minor
---

Implement previously-dead `ValidatorOptions` (`whitelist`, `forbidNonWhitelisted`, `skipMissingProperties`, `skipNullProperties`, `skipUndefinedProperties`, `stopAtFirstError`, `forbidUnknownValues`), function-form `message`, `ValidationError.target`/`.value` stripping, `registerDecorator`, and `getMetadataStorage`.

Behavior change: `whitelist` now actually strips unknown properties from the validated object (was a silent no-op in v4).

Note: `forbidUnknownValues` defaults to `false` here, diverging from upstream `[email protected]`, which defaults to `true`. See `docs/compat-class-validator.md`.
8 changes: 8 additions & 0 deletions .changeset/remove-unreachable-legacy-mapper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@tech-pioneer/data-mapper-core': patch
'om-data-mapper': patch
---

Remove the dead `export * from './core/Mapper'` re-export: the decorator API's `Mapper` already shadowed the legacy class under ES module semantics, so `Mapper.create` was never reachable from the published surface. The ESM post-install simulation now exercises only imports that resolve through the real exports maps.

Documented one behavior change in `docs/migration-v4-to-v5.md`: bracket-index syntax inside a `@Map()` path (`@Map('items[0].name')`) worked by accident in v4 and no longer resolves now that every path segment is emitted as an escaped literal key. Use `@MapFrom`/`@Transform` or a nested mapper for array indexing.
7 changes: 7 additions & 0 deletions .changeset/review-fixes-class-transformer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@tech-pioneer/data-mapper-class-transformer': patch
---

`enableImplicitConversion` now coerces array-valued `@Type(() => Number|String|Boolean|Date)` properties per element (previously the whole array was passed to the constructor, yielding `NaN`/joined strings).

`@TransformClassToPlain`, `@TransformClassToClass`, and `@TransformPlainToClass` now use static imports instead of a runtime `require('./functions')`, which threw `ReferenceError: require is not defined` for ESM consumers.
5 changes: 5 additions & 0 deletions .changeset/review-fixes-class-validator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tech-pioneer/data-mapper-class-validator': patch
---

Review fixes: `stopAtFirstError` no longer drops all errors when a validator is named after an `Object.prototype` member; null-prototype inputs return the no-metadata result instead of throwing; constraint metadata no longer grows on every instantiation for `@Matches`/`@Validate`/`@ValidateBy`; `registerDecorator` enforces every registration (second unnamed inline validators and re-registered classes with new constraints are no longer silently dropped); class-based custom validators report errors under their registered name (upstream-compatible) instead of `custom`; validation metadata is keyed via `Symbol.for` so duplicate package copies interoperate.
1 change: 0 additions & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@
# https://help.github.com/en/articles/displaying-a-sponsor-button-in-your-repository

github: [Isqanderm]

11 changes: 5 additions & 6 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Bug Report
description: Report a bug or unexpected behavior
title: "[Bug]: "
labels: ["bug", "triage"]
title: '[Bug]: '
labels: ['bug', 'triage']
body:
- type: markdown
attributes:
Expand Down Expand Up @@ -55,7 +55,7 @@ body:
placeholder: |
```typescript
import { Mapper } from 'om-data-mapper';

// Your code here
```
render: typescript
Expand Down Expand Up @@ -109,8 +109,8 @@ body:
label: TypeScript
description: Are you using TypeScript?
options:
- "Yes"
- "No"
- 'Yes'
- 'No'
validations:
required: true

Expand Down Expand Up @@ -144,4 +144,3 @@ body:
required: false
- label: I am using the latest version of om-data-mapper
required: false

Loading
Loading