@zudojs/types 1.1.1 → 1.3.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/dist/index.d.ts CHANGED
@@ -13,4 +13,3 @@ export * from "./typeGuards/index.js";
13
13
  export * from "./typeUtilities/index.js";
14
14
  export * from "./typeConverters/index.js";
15
15
  export * from "./runtime/index.js";
16
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -13,4 +13,3 @@ export * from "./typeGuards/index.js";
13
13
  export * from "./typeUtilities/index.js";
14
14
  export * from "./typeConverters/index.js";
15
15
  export * from "./runtime/index.js";
16
- //# sourceMappingURL=index.js.map
@@ -9,4 +9,3 @@ export type { Clock, ClockSeconds, Random, PseudoRandom, } from "./runtime.core.
9
9
  export { systemClock, systemClockSeconds, defineSecureRandom, systemRandom, FixedClock, } from "./runtime.core.js";
10
10
  export { SeededRandom } from "./runtime.seeded.js";
11
11
  export { MAX_RANDOM_INT_BOUND } from "./runtime.int.js";
12
- //# sourceMappingURL=index.d.ts.map
@@ -8,4 +8,3 @@
8
8
  export { systemClock, systemClockSeconds, defineSecureRandom, systemRandom, FixedClock, } from "./runtime.core.js";
9
9
  export { SeededRandom } from "./runtime.seeded.js";
10
10
  export { MAX_RANDOM_INT_BOUND } from "./runtime.int.js";
11
- //# sourceMappingURL=index.js.map
@@ -85,4 +85,3 @@ export declare class FixedClock implements Clock {
85
85
  advance(deltaMs: number): void;
86
86
  }
87
87
  export {};
88
- //# sourceMappingURL=runtime.core.d.ts.map
@@ -84,4 +84,3 @@ export class FixedClock {
84
84
  this.current += deltaMs;
85
85
  }
86
86
  }
87
- //# sourceMappingURL=runtime.core.js.map
@@ -28,4 +28,3 @@ export declare function assertIntBound(max: number, owner: string): void;
28
28
  export declare function sampleInt(max: number, nextWord: WordSource): number;
29
29
  /** Returns one cryptographically secure unsigned 32-bit word. */
30
30
  export declare function cryptoWord(): number;
31
- //# sourceMappingURL=runtime.int.d.ts.map
@@ -51,4 +51,3 @@ export function cryptoWord() {
51
51
  }
52
52
  return cryptoBuffer[0];
53
53
  }
54
- //# sourceMappingURL=runtime.int.js.map
@@ -28,4 +28,3 @@ export declare class SeededRandom implements PseudoRandom {
28
28
  /** Advances the mulberry32 state and returns an unsigned 32-bit word. */
29
29
  private next;
30
30
  }
31
- //# sourceMappingURL=runtime.seeded.d.ts.map
@@ -67,4 +67,3 @@ export class SeededRandom {
67
67
  return (t ^ (t >>> 14)) >>> 0;
68
68
  }
69
69
  }
70
- //# sourceMappingURL=runtime.seeded.js.map
@@ -1,7 +1,8 @@
1
1
  /**
2
- * Runtime type conversion helpers: JSON parsing, string/number/boolean conversion, case transforms.
2
+ * Runtime type conversion helpers: JSON parsing, string/number/boolean conversion, case transforms, count formatting.
3
3
  *
4
4
  * @module typeConverters
5
5
  */
6
6
  export { safeJsonParse, toString, toNumber, toBoolean, toArray, mapToObject, objectToMap, snakeToCamel, camelToSnake, kebabToCamel, camelToKebab, } from "./typeConverters.core.js";
7
- //# sourceMappingURL=index.d.ts.map
7
+ export { formatCount } from "./typeConverters.count.js";
8
+ export { characterLength, jsonStringByteLength, } from "./typeConverters.length.js";
@@ -1,7 +1,8 @@
1
1
  /**
2
- * Runtime type conversion helpers: JSON parsing, string/number/boolean conversion, case transforms.
2
+ * Runtime type conversion helpers: JSON parsing, string/number/boolean conversion, case transforms, count formatting.
3
3
  *
4
4
  * @module typeConverters
5
5
  */
6
6
  export { safeJsonParse, toString, toNumber, toBoolean, toArray, mapToObject, objectToMap, snakeToCamel, camelToSnake, kebabToCamel, camelToKebab, } from "./typeConverters.core.js";
7
- //# sourceMappingURL=index.js.map
7
+ export { formatCount } from "./typeConverters.count.js";
8
+ export { characterLength, jsonStringByteLength, } from "./typeConverters.length.js";
@@ -82,4 +82,3 @@ export declare function kebabToCamel(str: string): string;
82
82
  * Convert camelCase or PascalCase to kebab-case.
83
83
  */
84
84
  export declare function camelToKebab(str: string): string;
85
- //# sourceMappingURL=typeConverters.core.d.ts.map
@@ -199,4 +199,3 @@ export function camelToKebab(str) {
199
199
  .map((word) => word.toLowerCase())
200
200
  .join("-");
201
201
  }
202
- //# sourceMappingURL=typeConverters.core.js.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Count-and-noun formatting for human-readable messages.
3
+ *
4
+ * @module typeConverters/count
5
+ */
6
+ /**
7
+ * Formats a count with the singular or plural form of a noun, so messages
8
+ * read "at least 1 character" rather than "at least 1 characters".
9
+ *
10
+ * Only an exact count of 1 (or -1) is singular; 0, fractions and everything
11
+ * else take the plural. The plural defaults to the singular plus "s"; pass it
12
+ * explicitly for irregular nouns.
13
+ *
14
+ * @example
15
+ * formatCount(1, "character"); // "1 character"
16
+ * formatCount(3, "item"); // "3 items"
17
+ * formatCount(2, "entry", "entries"); // "2 entries"
18
+ */
19
+ export declare function formatCount(count: number, singular: string, plural?: string): string;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Count-and-noun formatting for human-readable messages.
3
+ *
4
+ * @module typeConverters/count
5
+ */
6
+ /**
7
+ * Formats a count with the singular or plural form of a noun, so messages
8
+ * read "at least 1 character" rather than "at least 1 characters".
9
+ *
10
+ * Only an exact count of 1 (or -1) is singular; 0, fractions and everything
11
+ * else take the plural. The plural defaults to the singular plus "s"; pass it
12
+ * explicitly for irregular nouns.
13
+ *
14
+ * @example
15
+ * formatCount(1, "character"); // "1 character"
16
+ * formatCount(3, "item"); // "3 items"
17
+ * formatCount(2, "entry", "entries"); // "2 entries"
18
+ */
19
+ export function formatCount(count, singular, plural = `${singular}s`) {
20
+ return `${count} ${Math.abs(count) === 1 ? singular : plural}`;
21
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * String length helpers that count what a person or the wire sees rather
3
+ * than UTF-16 code units.
4
+ *
5
+ * @module typeConverters/length
6
+ */
7
+ /**
8
+ * Number of Unicode code points in a string.
9
+ *
10
+ * `String.prototype.length` counts UTF-16 code units, so an emoji or any
11
+ * other character outside the Basic Multilingual Plane counts as two. A
12
+ * constraint phrased in "characters" should count with this instead.
13
+ *
14
+ * @example
15
+ * characterLength("abc"); // 3
16
+ * characterLength("🛒🛒"); // 2 ("🛒🛒".length is 4)
17
+ */
18
+ export declare function characterLength(value: string): number;
19
+ /**
20
+ * Bytes that `JSON.stringify(value)` occupies when encoded as UTF-8, the
21
+ * surrounding quotes and JSON escapes included.
22
+ *
23
+ * `value.length * 2` (the UTF-16 size) undercounts every character above
24
+ * U+07FF: "₦" is three bytes on the wire, so a payload limit measured that
25
+ * way let bodies half again larger than the limit through. Lone surrogates
26
+ * are counted as `JSON.stringify` writes them, as a `\uXXXX` escape.
27
+ *
28
+ * @example
29
+ * jsonStringByteLength("ab"); // 4 — "ab" with quotes
30
+ * jsonStringByteLength("₦"); // 5 — 3 bytes plus quotes
31
+ * jsonStringByteLength("\n"); // 4 — written as \n
32
+ */
33
+ export declare function jsonStringByteLength(value: string): number;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * String length helpers that count what a person or the wire sees rather
3
+ * than UTF-16 code units.
4
+ *
5
+ * @module typeConverters/length
6
+ */
7
+ /** Control characters that `JSON.stringify` writes as a two-byte escape. */
8
+ const SHORT_ESCAPES = new Set([
9
+ 0x08, 0x09, 0x0a, 0x0c, 0x0d,
10
+ ]);
11
+ /** A string JSON writes byte-for-byte: printable ASCII without `"` or `\`. */
12
+ const PLAIN_ASCII = /^[\x20\x21\x23-\x5b\x5d-\x7e]*$/;
13
+ function isHighSurrogate(code) {
14
+ return code >= 0xd800 && code <= 0xdbff;
15
+ }
16
+ function isLowSurrogate(code) {
17
+ return code >= 0xdc00 && code <= 0xdfff;
18
+ }
19
+ /**
20
+ * Number of Unicode code points in a string.
21
+ *
22
+ * `String.prototype.length` counts UTF-16 code units, so an emoji or any
23
+ * other character outside the Basic Multilingual Plane counts as two. A
24
+ * constraint phrased in "characters" should count with this instead.
25
+ *
26
+ * @example
27
+ * characterLength("abc"); // 3
28
+ * characterLength("🛒🛒"); // 2 ("🛒🛒".length is 4)
29
+ */
30
+ export function characterLength(value) {
31
+ let count = 0;
32
+ for (let i = 0; i < value.length; i++) {
33
+ if (isHighSurrogate(value.charCodeAt(i)) &&
34
+ i + 1 < value.length &&
35
+ isLowSurrogate(value.charCodeAt(i + 1))) {
36
+ i++;
37
+ }
38
+ count++;
39
+ }
40
+ return count;
41
+ }
42
+ /**
43
+ * Bytes that `JSON.stringify(value)` occupies when encoded as UTF-8, the
44
+ * surrounding quotes and JSON escapes included.
45
+ *
46
+ * `value.length * 2` (the UTF-16 size) undercounts every character above
47
+ * U+07FF: "₦" is three bytes on the wire, so a payload limit measured that
48
+ * way let bodies half again larger than the limit through. Lone surrogates
49
+ * are counted as `JSON.stringify` writes them, as a `\uXXXX` escape.
50
+ *
51
+ * @example
52
+ * jsonStringByteLength("ab"); // 4 — "ab" with quotes
53
+ * jsonStringByteLength("₦"); // 5 — 3 bytes plus quotes
54
+ * jsonStringByteLength("\n"); // 4 — written as \n
55
+ */
56
+ export function jsonStringByteLength(value) {
57
+ if (PLAIN_ASCII.test(value))
58
+ return value.length + 2;
59
+ let bytes = 2;
60
+ for (let i = 0; i < value.length; i++) {
61
+ const code = value.charCodeAt(i);
62
+ if (code < 0x20) {
63
+ bytes += SHORT_ESCAPES.has(code) ? 2 : 6;
64
+ }
65
+ else if (code < 0x80) {
66
+ bytes += code === 0x22 || code === 0x5c ? 2 : 1;
67
+ }
68
+ else if (code < 0x800) {
69
+ bytes += 2;
70
+ }
71
+ else if (isHighSurrogate(code) &&
72
+ i + 1 < value.length &&
73
+ isLowSurrogate(value.charCodeAt(i + 1))) {
74
+ bytes += 4;
75
+ i++;
76
+ }
77
+ else if (isHighSurrogate(code) || isLowSurrogate(code)) {
78
+ bytes += 6;
79
+ }
80
+ else {
81
+ bytes += 3;
82
+ }
83
+ }
84
+ return bytes;
85
+ }
@@ -4,4 +4,3 @@
4
4
  * @module typeGuards
5
5
  */
6
6
  export { MAX_EMAIL_LENGTH, isPlainObject, isNonNullObject, isNonEmptyString, isPositiveNumber, isFiniteNumber, isInteger, isDate, isUrl, isEmail, isUuid, isUuidV4, isIsoDateString, isIsoDateTimeString, isArrayOfType, isDefined, isFunction, isPromise, isThenable, } from "./typeGuards.core.js";
7
- //# sourceMappingURL=index.d.ts.map
@@ -4,4 +4,3 @@
4
4
  * @module typeGuards
5
5
  */
6
6
  export { MAX_EMAIL_LENGTH, isPlainObject, isNonNullObject, isNonEmptyString, isPositiveNumber, isFiniteNumber, isInteger, isDate, isUrl, isEmail, isUuid, isUuidV4, isIsoDateString, isIsoDateTimeString, isArrayOfType, isDefined, isFunction, isPromise, isThenable, } from "./typeGuards.core.js";
7
- //# sourceMappingURL=index.js.map
@@ -111,4 +111,3 @@ export declare function isPromise(value: unknown): value is Promise<unknown>;
111
111
  * makes those calls throw at the point the guard was supposed to make safe.
112
112
  */
113
113
  export declare function isThenable(value: unknown): value is PromiseLike<unknown>;
114
- //# sourceMappingURL=typeGuards.core.d.ts.map
@@ -216,4 +216,3 @@ export function isThenable(value) {
216
216
  "then" in value &&
217
217
  typeof value.then === "function");
218
218
  }
219
- //# sourceMappingURL=typeGuards.core.js.map
@@ -4,4 +4,3 @@
4
4
  * @module typeUtilities
5
5
  */
6
6
  export type { DeepReadonly, DeepPartial, DeepRequired, Prettify, StringKeysOf, NumberKeysOf, PartialExcept, RequiredExcept, PartialKeys, OptionalKeyNames, RequireKeys, AsyncReturnType, Nullable, Undefinable, Maybe, MaybePromise, NestedKeyOf, NestedValueOf, OmitByValue, PickByValue, } from "./typeUtilities.core.js";
7
- //# sourceMappingURL=index.d.ts.map
@@ -4,4 +4,3 @@
4
4
  * @module typeUtilities
5
5
  */
6
6
  export {};
7
- //# sourceMappingURL=index.js.map
@@ -112,4 +112,3 @@ export type OmitByValue<T, ValueType> = Pick<T, {
112
112
  export type PickByValue<T, ValueType> = Pick<T, {
113
113
  [K in keyof T]: T[K] extends ValueType ? K : never;
114
114
  }[keyof T]>;
115
- //# sourceMappingURL=typeUtilities.core.d.ts.map
@@ -4,4 +4,3 @@
4
4
  * @module typeUtilities/typeUtilities
5
5
  */
6
6
  export {};
7
- //# sourceMappingURL=typeUtilities.core.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zudojs/types",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "description": "Shared type guards, utility types, and type converters for the Zudojs framework.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -29,9 +29,9 @@
29
29
  "node": ">=24.0.0"
30
30
  },
31
31
  "devDependencies": {
32
- "@types/node": "^26.4.1",
32
+ "@types/node": "^26.6.2",
33
33
  "typescript": "7.0.2",
34
- "vitest": "^4.1.11"
34
+ "vitest": "^5.0.1"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public"
@@ -42,7 +42,7 @@
42
42
  "type-guards",
43
43
  "utilities"
44
44
  ],
45
- "homepage": "https://github.com/oyinlola-tech/zudo#readme",
45
+ "homepage": "https://zudojs.oyinlola.site/docs/packages-types",
46
46
  "bugs": {
47
47
  "url": "https://github.com/oyinlola-tech/zudo/issues"
48
48
  },