@clipboard-health/contract-core 2.3.46 → 3.0.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/README.md +14 -14
- package/package.json +2 -2
- package/src/lib/schemas/enum.d.ts +10 -4
- package/src/lib/schemas/enum.js +23 -9
- package/src/lib/schemas/enum.js.map +1 -1
package/README.md
CHANGED
|
@@ -29,8 +29,8 @@ This package provides four enum validation helpers to cover different use cases:
|
|
|
29
29
|
|
|
30
30
|
**Fallback validation (with coalescing):**
|
|
31
31
|
|
|
32
|
-
- `requiredEnumWithFallback(values
|
|
33
|
-
- `optionalEnumWithFallback(values
|
|
32
|
+
- `requiredEnumWithFallback(values)` - Invalid values are coerced to `ENUM_FALLBACK` (`"UNRECOGNIZED_"`), a business-context-neutral sentinel automatically appended to the enum type. `undefined` fails validation.
|
|
33
|
+
- `optionalEnumWithFallback(values)` - Invalid values are coerced to `ENUM_FALLBACK` (`"UNRECOGNIZED_"`). `undefined` passes through as `undefined`.
|
|
34
34
|
|
|
35
35
|
**Strict validation (no fallback):**
|
|
36
36
|
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
apiErrors,
|
|
45
45
|
booleanString,
|
|
46
46
|
dateTimeSchema,
|
|
47
|
+
ENUM_FALLBACK,
|
|
47
48
|
nonEmptyString,
|
|
48
49
|
optionalEnum,
|
|
49
50
|
optionalEnumWithFallback,
|
|
@@ -134,12 +135,13 @@ const someDate = schema.parse("2026-03-15T10:30:00.000Z");
|
|
|
134
135
|
console.log(someDate);
|
|
135
136
|
|
|
136
137
|
// Enum with fallback examples
|
|
138
|
+
// ENUM_FALLBACK is a neutral sentinel ("UNRECOGNIZED_") automatically appended
|
|
139
|
+
// to the enum type. Consumers cannot choose their own fallback value, preventing
|
|
140
|
+
// misuse where a business-meaningful value is treated as a default.
|
|
141
|
+
|
|
137
142
|
/* -- required -- */
|
|
138
|
-
const requiredStatusEnumSchema = requiredEnumWithFallback(
|
|
139
|
-
|
|
140
|
-
"unspecified",
|
|
141
|
-
);
|
|
142
|
-
// type RequiredStatusEnum = "unspecified" | "pending" | "completed" | "failed"
|
|
143
|
+
const requiredStatusEnumSchema = requiredEnumWithFallback(["pending", "completed", "failed"]);
|
|
144
|
+
// type RequiredStatusEnum = "pending" | "completed" | "failed" | "UNRECOGNIZED_"
|
|
143
145
|
type RequiredStatusEnum = z.infer<typeof requiredStatusEnumSchema>;
|
|
144
146
|
|
|
145
147
|
const completedStatus: RequiredStatusEnum = requiredStatusEnumSchema.parse("completed");
|
|
@@ -147,8 +149,9 @@ const completedStatus: RequiredStatusEnum = requiredStatusEnumSchema.parse("comp
|
|
|
147
149
|
console.log(completedStatus);
|
|
148
150
|
|
|
149
151
|
const additionalStatus = requiredStatusEnumSchema.parse("additional");
|
|
150
|
-
// => "
|
|
152
|
+
// => "UNRECOGNIZED_" (ENUM_FALLBACK)
|
|
151
153
|
console.log(additionalStatus);
|
|
154
|
+
console.log(additionalStatus === ENUM_FALLBACK); // true
|
|
152
155
|
|
|
153
156
|
try {
|
|
154
157
|
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
@@ -159,11 +162,8 @@ try {
|
|
|
159
162
|
}
|
|
160
163
|
|
|
161
164
|
/* -- optional -- */
|
|
162
|
-
const optionalStatusEnumSchema = optionalEnumWithFallback(
|
|
163
|
-
|
|
164
|
-
"unspecified",
|
|
165
|
-
);
|
|
166
|
-
// type OptionalStatusEnum = "unspecified" | "pending" | "completed" | "failed" | undefined
|
|
165
|
+
const optionalStatusEnumSchema = optionalEnumWithFallback(["pending", "completed", "failed"]);
|
|
166
|
+
// type OptionalStatusEnum = "pending" | "completed" | "failed" | "UNRECOGNIZED_" | undefined
|
|
167
167
|
type OptionalStatusEnum = z.infer<typeof optionalStatusEnumSchema>;
|
|
168
168
|
|
|
169
169
|
const failedStatus: OptionalStatusEnum = optionalStatusEnumSchema.parse("failed");
|
|
@@ -171,7 +171,7 @@ const failedStatus: OptionalStatusEnum = optionalStatusEnumSchema.parse("failed"
|
|
|
171
171
|
console.log(failedStatus);
|
|
172
172
|
|
|
173
173
|
const extraStatus = optionalStatusEnumSchema.parse("extra");
|
|
174
|
-
// => "
|
|
174
|
+
// => "UNRECOGNIZED_" (ENUM_FALLBACK)
|
|
175
175
|
console.log(extraStatus);
|
|
176
176
|
|
|
177
177
|
// eslint-disable-next-line unicorn/no-useless-undefined
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/contract-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Shared Zod schemas for Clipboard's contracts.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"contract",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"tslib": "2.8.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@clipboard-health/testing-core": "2.2.
|
|
28
|
+
"@clipboard-health/testing-core": "2.2.88",
|
|
29
29
|
"zod": "3.25.76"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
type EnumValues = readonly [string, ...string[]];
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* A business-context-neutral sentinel returned when an enum field
|
|
5
|
+
* receives a value the consumer does not recognize.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ENUM_FALLBACK: "UNRECOGNIZED_";
|
|
8
|
+
type EnumFallback = typeof ENUM_FALLBACK;
|
|
9
|
+
export declare function enumWithFallback<const V extends EnumValues>(values: V, options: {
|
|
4
10
|
optional: true;
|
|
5
|
-
}): z.ZodEffects<z.ZodOptional<z.ZodEnum<[...V]>>, V[number] | undefined, unknown>;
|
|
6
|
-
export declare
|
|
7
|
-
export declare
|
|
11
|
+
}): z.ZodEffects<z.ZodOptional<z.ZodEnum<[...V, EnumFallback]>>, V[number] | EnumFallback | undefined, unknown>;
|
|
12
|
+
export declare function requiredEnumWithFallback<const V extends EnumValues>(values: V): z.ZodEffects<z.ZodEnum<[...V, "UNRECOGNIZED_"]>, "UNRECOGNIZED_" | V[number], unknown>;
|
|
13
|
+
export declare function optionalEnumWithFallback<const V extends EnumValues>(values: V): z.ZodEffects<z.ZodOptional<z.ZodEnum<[...V, "UNRECOGNIZED_"]>>, "UNRECOGNIZED_" | V[number] | undefined, unknown>;
|
|
8
14
|
export declare function requiredEnum<const V extends EnumValues>(values: V): z.ZodEnum<[...V]>;
|
|
9
15
|
export declare function optionalEnum<const V extends EnumValues>(values: V): z.ZodOptional<z.ZodEnum<[...V]>>;
|
|
10
16
|
export {};
|
package/src/lib/schemas/enum.js
CHANGED
|
@@ -1,25 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ENUM_FALLBACK = void 0;
|
|
4
4
|
exports.enumWithFallback = enumWithFallback;
|
|
5
|
+
exports.requiredEnumWithFallback = requiredEnumWithFallback;
|
|
6
|
+
exports.optionalEnumWithFallback = optionalEnumWithFallback;
|
|
5
7
|
exports.requiredEnum = requiredEnum;
|
|
6
8
|
exports.optionalEnum = optionalEnum;
|
|
7
9
|
const zod_1 = require("zod");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
/**
|
|
11
|
+
* A business-context-neutral sentinel returned when an enum field
|
|
12
|
+
* receives a value the consumer does not recognize.
|
|
13
|
+
*/
|
|
14
|
+
exports.ENUM_FALLBACK = "UNRECOGNIZED_";
|
|
15
|
+
function enumWithFallback(values, options = {}) {
|
|
16
|
+
if (values.includes(exports.ENUM_FALLBACK)) {
|
|
17
|
+
throw new Error(`Enum values must not include "${exports.ENUM_FALLBACK}". It is appended automatically.`);
|
|
18
|
+
}
|
|
19
|
+
const OriginalEnum = zod_1.z.enum([...values]);
|
|
20
|
+
const ExpandedEnum = zod_1.z.enum([...values, exports.ENUM_FALLBACK]);
|
|
10
21
|
const optional = options.optional ?? false;
|
|
11
|
-
const schema = optional ?
|
|
22
|
+
const schema = optional ? ExpandedEnum.optional() : ExpandedEnum;
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
12
24
|
return zod_1.z.preprocess((value) => {
|
|
13
25
|
if (value === undefined) {
|
|
14
26
|
return optional ? undefined : value;
|
|
15
27
|
}
|
|
16
|
-
return
|
|
28
|
+
return OriginalEnum.safeParse(value).success ? value : exports.ENUM_FALLBACK;
|
|
17
29
|
}, schema);
|
|
18
30
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
function requiredEnumWithFallback(values) {
|
|
32
|
+
return enumWithFallback(values, { optional: false });
|
|
33
|
+
}
|
|
34
|
+
function optionalEnumWithFallback(values) {
|
|
35
|
+
return enumWithFallback(values, { optional: true });
|
|
36
|
+
}
|
|
23
37
|
function requiredEnum(values) {
|
|
24
38
|
return zod_1.z.enum([...values]);
|
|
25
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enum.js","sourceRoot":"","sources":["../../../../../../packages/contract-core/src/lib/schemas/enum.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"enum.js","sourceRoot":"","sources":["../../../../../../packages/contract-core/src/lib/schemas/enum.ts"],"names":[],"mappings":";;;AAiCA,4CAuBC;AAED,4DAEC;AAED,4DAEC;AAED,oCAEC;AAED,oCAIC;AA1ED,6BAAwB;AAIxB;;;GAGG;AACU,QAAA,aAAa,GAAG,eAAwB,CAAC;AAyBtD,SAAgB,gBAAgB,CAC9B,MAAS,EACT,UAAkC,EAAE;IAEpC,IAAK,MAA4B,CAAC,QAAQ,CAAC,qBAAa,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CACb,iCAAiC,qBAAa,kCAAkC,CACjF,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IACzC,MAAM,YAAY,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,EAAE,qBAAa,CAAC,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC;IAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;IAEjE,+DAA+D;IAC/D,OAAO,OAAC,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE;QAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;QACtC,CAAC;QAED,OAAO,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,qBAAa,CAAC;IACvE,CAAC,EAAE,MAAM,CAAC,CAAC;AACb,CAAC;AAED,SAAgB,wBAAwB,CAA6B,MAAS;IAC5E,OAAO,gBAAgB,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,SAAgB,wBAAwB,CAA6B,MAAS;IAC5E,OAAO,gBAAgB,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AACtD,CAAC;AAED,SAAgB,YAAY,CAA6B,MAAS;IAChE,OAAO,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED,SAAgB,YAAY,CAC1B,MAAS;IAET,OAAO,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;AACxC,CAAC"}
|