@zipbul/baker 3.3.1 → 3.4.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
@@ -1,5 +1,23 @@
1
1
  # @zipbul/baker
2
2
 
3
+ ## 3.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 92028cf: Add two binary-value validation rules to `@zipbul/baker/rules`:
8
+
9
+ - `isUint8Array` — a bare type guard (`value instanceof Uint8Array`), mirroring `isRegExp` /
10
+ `isArray`. Accepts `Uint8Array` and its subclasses (e.g. `Buffer`); rejects `Uint8ClampedArray`,
11
+ `DataView`, and plain arrays.
12
+ - `isByteSize(min, max?)` — the binary analogue of `isByteLength`. Validates the `.byteLength` of
13
+ any `ArrayBuffer.isView(v)` value (all typed arrays + `DataView`), measuring the view window
14
+ rather than the backing buffer. The generated code guards `ArrayBuffer.isView` before any
15
+ `.byteLength` read, so non-views fail cleanly instead of throwing.
16
+
17
+ Both are exported from `@zipbul/baker/rules` as imported identifiers (AOT-safe), are synchronous,
18
+ and compose inside a single `@Field(...)` — e.g. `@Field(isUint8Array, isByteSize(16), { optional: true })`
19
+ for raw key material such as an HKDF salt.
20
+
3
21
  ## 3.3.1
4
22
 
5
23
  ### Patch Changes
@@ -0,0 +1,3 @@
1
+ import type { EmittableRule } from '../types';
2
+ export declare const isUint8Array: import("../types").InternalRule;
3
+ export declare function isByteSize(min: number, max?: number): EmittableRule;
@@ -0,0 +1,51 @@
1
+ import { makeRule } from '../rule-plan.js';
2
+ // ─────────────────────────────────────────────────────────────────────────────
3
+ // isUint8Array — instanceof guard (self-narrowing, no typeof gate; mirrors isRegExp)
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ export const isUint8Array = makeRule({
6
+ name: 'isUint8Array',
7
+ constraints: {},
8
+ validate: value => value instanceof Uint8Array,
9
+ emit: (varName, ctx) => `if (!(${varName} instanceof Uint8Array)) ${ctx.fail('isUint8Array')};`,
10
+ });
11
+ // ─────────────────────────────────────────────────────────────────────────────
12
+ // isByteSize(min, max?) — byte length of any ArrayBufferView (binary analogue of isByteLength)
13
+ //
14
+ // The ArrayBuffer.isView guard MUST short-circuit before any .byteLength read: reading .byteLength
15
+ // on a non-view yields undefined (and undefined < min is false → would wrongly pass), and on
16
+ // null/undefined it throws. The guard-first else-if chain prevents both. .byteLength is inlined
17
+ // (not aliased to a local like isByteLength) — it is a trivial getter, not an expensive call.
18
+ //
19
+ // min/max are dev-supplied constants; per "trust TS for dev inputs" they are not runtime-guarded,
20
+ // consistent with isByteLength.
21
+ // ─────────────────────────────────────────────────────────────────────────────
22
+ export function isByteSize(min, max) {
23
+ return makeRule({
24
+ name: 'isByteSize',
25
+ constraints: { min, max },
26
+ // Fail-form mirrors emit exactly (same as isByteLength), so validate() and the generated code
27
+ // agree for ALL inputs — including degenerate NaN bounds, where pass-form (>= NaN) would reject
28
+ // but the emitted (< NaN) accepts, breaking validate/emit parity.
29
+ validate: value => {
30
+ if (!ArrayBuffer.isView(value)) {
31
+ return false;
32
+ }
33
+ const byteLen = value.byteLength;
34
+ if (byteLen < min) {
35
+ return false;
36
+ }
37
+ if (max !== undefined && byteLen > max) {
38
+ return false;
39
+ }
40
+ return true;
41
+ },
42
+ emit: (varName, ctx) => {
43
+ let code = `if (!ArrayBuffer.isView(${varName})) ${ctx.fail('isByteSize')};`;
44
+ code += `\nelse if (${varName}.byteLength < ${min}) ${ctx.fail('isByteSize')};`;
45
+ if (max !== undefined) {
46
+ code += `\nelse if (${varName}.byteLength > ${max}) ${ctx.fail('isByteSize')};`;
47
+ }
48
+ return code;
49
+ },
50
+ });
51
+ }
@@ -10,3 +10,4 @@ export { arrayContains, arrayNotContains, arrayMinSize, arrayMaxSize, arrayUniqu
10
10
  export { isNotEmptyObject, isInstance } from './object';
11
11
  export type { IsNotEmptyObjectOptions } from './object';
12
12
  export { isMobilePhone, isPostalCode, isIdentityCard, isPassportNumber } from './locales';
13
+ export { isUint8Array, isByteSize } from './binary';
@@ -7,3 +7,4 @@ export { minLength, maxLength, length, contains, notContains, matches, isLowerca
7
7
  export { arrayContains, arrayNotContains, arrayMinSize, arrayMaxSize, arrayUnique, arrayNotEmpty } from './array.js';
8
8
  export { isNotEmptyObject, isInstance } from './object.js';
9
9
  export { isMobilePhone, isPostalCode, isIdentityCard, isPassportNumber } from './locales.js';
10
+ export { isUint8Array, isByteSize } from './binary.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zipbul/baker",
3
- "version": "3.3.1",
3
+ "version": "3.4.0",
4
4
  "description": "Bun-only AOT decorator-based DTO validation & serialization. class-validator DX, sealed code generation, zero reflect-metadata.",
5
5
  "keywords": [
6
6
  "aot",