@classytic/repo-core 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,21 @@ All notable changes to `@classytic/repo-core` are documented here.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.10.0] - 2026-07-13
8
+
9
+ ### Added — `ValidationErrorMeta.path` + `.meta` (field-scoped validation errors)
10
+
11
+ - **`ValidationErrorMeta.path?: string`** — dot-path to the offending field
12
+ (e.g. `'journalItems.2.account'`). Set by kits with field-scoped validation
13
+ (ledger's `FieldError`, Mongoose `ValidationError`). Absent when the kit doesn't
14
+ have a field path.
15
+ - **`ValidationErrorMeta.meta?: Readonly<Record<string, unknown>>`** — non-PII
16
+ structured extra for the field (e.g. `{ value: 'bad' }`). Never include secrets.
17
+ - **`toErrorContract`** now forwards `path` and `meta` from each `validationErrors`
18
+ entry onto the wire `ErrorDetail`. Previously only `code` and `message` were mapped;
19
+ field paths were silently dropped. No breaking change — both fields are optional and
20
+ additive. Kits that don't set them produce the same wire shape as before.
21
+
7
22
  ## [0.9.0] - 2026-07-11
8
23
 
9
24
  ### Added — `StandardRepo.getByIds` (batch point-read)
@@ -23,9 +23,10 @@ declare function statusToErrorCode(status: number): ErrorCode;
23
23
  * `validationErrors` (mongokit-shaped throwable field) is mapped into the
24
24
  * canonical `details` array so wire consumers see one shape regardless
25
25
  * of which kit threw the error. Each `validationErrors[i]` becomes an
26
- * `ErrorDetail` with `code: validator`, `message: error`, `path` left
27
- * unset (kits that have field paths set them in their own ErrorDetail
28
- * mapping).
26
+ * `ErrorDetail` with `code: validator`, `message: error`, plus `path` and
27
+ * `meta` when the throwing kit populates them (field-scoped validators
28
+ * like ledger's `FieldError` — so a kernel's rich field errors reach the
29
+ * wire natively, with NO per-host errorMapper).
29
30
  *
30
31
  * `duplicate.fields` is similarly flattened into `details` with the
31
32
  * duplicate-key code so unique-constraint failures look uniform on the
@@ -36,9 +36,10 @@ function statusToErrorCode(status) {
36
36
  * `validationErrors` (mongokit-shaped throwable field) is mapped into the
37
37
  * canonical `details` array so wire consumers see one shape regardless
38
38
  * of which kit threw the error. Each `validationErrors[i]` becomes an
39
- * `ErrorDetail` with `code: validator`, `message: error`, `path` left
40
- * unset (kits that have field paths set them in their own ErrorDetail
41
- * mapping).
39
+ * `ErrorDetail` with `code: validator`, `message: error`, plus `path` and
40
+ * `meta` when the throwing kit populates them (field-scoped validators
41
+ * like ledger's `FieldError` — so a kernel's rich field errors reach the
42
+ * wire natively, with NO per-host errorMapper).
42
43
  *
43
44
  * `duplicate.fields` is similarly flattened into `details` with the
44
45
  * duplicate-key code so unique-constraint failures look uniform on the
@@ -59,8 +60,10 @@ function toErrorContract(error) {
59
60
  };
60
61
  const details = [];
61
62
  if (Array.isArray(e.validationErrors)) for (const v of e.validationErrors) details.push({
63
+ ...v.path ? { path: v.path } : {},
62
64
  code: v.validator,
63
- message: v.error
65
+ message: v.error,
66
+ ...v.meta ? { meta: v.meta } : {}
64
67
  });
65
68
  if (e.duplicate?.fields?.length) for (const field of e.duplicate.fields) details.push({
66
69
  path: field,
@@ -39,6 +39,19 @@ interface DuplicateKeyMeta {
39
39
  interface ValidationErrorMeta {
40
40
  validator: string;
41
41
  error: string;
42
+ /**
43
+ * Dot-path to the offending field (e.g. `'journalItems.2.account'`).
44
+ * Optional — kits with field-scoped validation (ledger's `FieldError`,
45
+ * mongoose ValidationError) set it so it flows onto the wire
46
+ * {@link ErrorDetail.path} via {@link toErrorContract} instead of being
47
+ * dropped. Kits without a path leave it unset.
48
+ */
49
+ path?: string;
50
+ /**
51
+ * Non-PII structured extra for this field (e.g. the offending value under
52
+ * `{ value }`). Flows onto {@link ErrorDetail.meta}. Never include secrets.
53
+ */
54
+ meta?: Readonly<Record<string, unknown>>;
42
55
  }
43
56
  /**
44
57
  * HTTP-shaped error — the throwable envelope every repository error and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/repo-core",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Driver-agnostic repository primitives: hooks, Filter IR, operations, pagination, cache contract. Foundation for mongokit, sqlitekit, pgkit, and prismakit. Lean by design — no plugins ship here; each kit owns its own.",
5
5
  "type": "module",
6
6
  "sideEffects": false,