@veloxts/validation 0.6.68 → 0.6.69
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 +46 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -1
- package/dist/schemas/serialization.d.ts +43 -0
- package/dist/schemas/serialization.js +109 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# @veloxts/validation
|
|
2
2
|
|
|
3
|
+
## 0.6.69
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- implement user feedback improvements across packages
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Addresses 9 user feedback items to improve DX, reduce boilerplate, and eliminate template duplications.
|
|
12
|
+
|
|
13
|
+
### Phase 1: Validation Helpers (`@veloxts/validation`)
|
|
14
|
+
|
|
15
|
+
- Add `prismaDecimal()`, `prismaDecimalNullable()`, `prismaDecimalOptional()` for Prisma Decimal → number conversion
|
|
16
|
+
- Add `dateToIso`, `dateToIsoNullable`, `dateToIsoOptional` aliases for consistency
|
|
17
|
+
|
|
18
|
+
### Phase 2: Template Deduplication (`@veloxts/auth`)
|
|
19
|
+
|
|
20
|
+
- Export `createEnhancedTokenStore()` with token revocation and refresh token reuse detection
|
|
21
|
+
- Export `parseUserRoles()` and `DEFAULT_ALLOWED_ROLES`
|
|
22
|
+
- Fix memory leak: track pending timeouts for proper cleanup on `destroy()`
|
|
23
|
+
- Update templates to import from `@veloxts/auth` instead of duplicating code
|
|
24
|
+
- Fix jwtManager singleton pattern in templates
|
|
25
|
+
|
|
26
|
+
### Phase 3: Router Helpers (`@veloxts/router`)
|
|
27
|
+
|
|
28
|
+
- Add `createRouter()` returning `{ collections, router }` for DRY setup
|
|
29
|
+
- Add `toRouter()` for router-only use cases
|
|
30
|
+
- Update all router templates to use `createRouter()`
|
|
31
|
+
|
|
32
|
+
### Phase 4: Guard Type Narrowing - Experimental (`@veloxts/auth`, `@veloxts/router`)
|
|
33
|
+
|
|
34
|
+
- Add `NarrowingGuard` interface with phantom `_narrows` type
|
|
35
|
+
- Add `authenticatedNarrow` and `hasRoleNarrow()` guards
|
|
36
|
+
- Add `guardNarrow()` method to `ProcedureBuilder` for context narrowing
|
|
37
|
+
- Enables `ctx.user` to be non-null after guard passes
|
|
38
|
+
|
|
39
|
+
### Phase 5: Documentation (`@veloxts/router`)
|
|
40
|
+
|
|
41
|
+
- Document `.rest()` override patterns
|
|
42
|
+
- Document `createRouter()` helper usage
|
|
43
|
+
- Document `guardNarrow()` experimental API
|
|
44
|
+
- Add schema browser-safety patterns for RSC apps
|
|
45
|
+
|
|
46
|
+
- Updated dependencies
|
|
47
|
+
- @veloxts/core@0.6.69
|
|
48
|
+
|
|
3
49
|
## 0.6.68
|
|
4
50
|
|
|
5
51
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -34,4 +34,4 @@ export { baseEntitySchema, booleanStringSchema, createIdSchema, datetimeSchema,
|
|
|
34
34
|
export type { CursorPaginatedResponse, CursorPaginationInput, CursorPaginationMeta, PaginatedResponse, PaginationInput, PaginationMeta, } from './schemas/pagination.js';
|
|
35
35
|
export { calculateOffset, calculatePaginationMeta, createCursorPaginatedResponseSchema, createPaginatedResponse, createPaginatedResponseSchema, createPaginationSchema, cursorPaginationSchema, PAGINATION_DEFAULTS, paginationInputSchema, } from './schemas/pagination.js';
|
|
36
36
|
export type { InferWithTimestamps, OmitTimestamps, SerializedDates, WithOptional, } from './schemas/serialization.js';
|
|
37
|
-
export { dateToISOString, dateToISOStringNullable, dateToISOStringOptional, timestamps, timestampsWithSoftDelete, withTimestamps, } from './schemas/serialization.js';
|
|
37
|
+
export { dateToISOString, dateToISOStringNullable, dateToISOStringOptional, dateToIso, dateToIsoNullable, dateToIsoOptional, prismaDecimal, prismaDecimalNullable, prismaDecimalOptional, timestamps, timestampsWithSoftDelete, withTimestamps, } from './schemas/serialization.js';
|
package/dist/index.js
CHANGED
|
@@ -35,4 +35,12 @@ export { isSchema, isZodSchema, wrapSchema } from './types.js';
|
|
|
35
35
|
export { assertSchema, createTypeGuard, createValidator, formatZodErrors, parse, parseAll, safeParse, zodErrorToValidationError, } from './middleware.js';
|
|
36
36
|
export { baseEntitySchema, booleanStringSchema, createIdSchema, datetimeSchema, emailSchema, idParamSchema, integerStringSchema, makePartial, nonEmptyStringSchema, numberStringSchema, omitFields, partialExcept, pickFields, timestampFieldsSchema, urlSchema, uuidSchema, } from './schemas/common.js';
|
|
37
37
|
export { calculateOffset, calculatePaginationMeta, createCursorPaginatedResponseSchema, createPaginatedResponse, createPaginatedResponseSchema, createPaginationSchema, cursorPaginationSchema, PAGINATION_DEFAULTS, paginationInputSchema, } from './schemas/pagination.js';
|
|
38
|
-
export {
|
|
38
|
+
export {
|
|
39
|
+
// Date serialization
|
|
40
|
+
dateToISOString, dateToISOStringNullable, dateToISOStringOptional,
|
|
41
|
+
// Date aliases (shorter names)
|
|
42
|
+
dateToIso, dateToIsoNullable, dateToIsoOptional,
|
|
43
|
+
// Prisma Decimal helpers
|
|
44
|
+
prismaDecimal, prismaDecimalNullable, prismaDecimalOptional,
|
|
45
|
+
// Timestamp presets
|
|
46
|
+
timestamps, timestampsWithSoftDelete, withTimestamps, } from './schemas/serialization.js';
|
|
@@ -35,6 +35,34 @@ export type WithOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>
|
|
|
35
35
|
* Omits timestamp fields from a type (useful for create/update inputs)
|
|
36
36
|
*/
|
|
37
37
|
export type OmitTimestamps<T> = Omit<T, 'createdAt' | 'updatedAt' | 'deletedAt'>;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a field that accepts Prisma Decimal and transforms to number
|
|
40
|
+
*
|
|
41
|
+
* Use in OUTPUT schemas where Prisma returns Decimal objects.
|
|
42
|
+
* Handles Prisma Decimal, regular numbers, and string representations.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const ProductSchema = z.object({
|
|
47
|
+
* id: z.string(),
|
|
48
|
+
* price: prismaDecimal(), // Decimal -> number
|
|
49
|
+
* discount: prismaDecimalNullable() // Decimal | null -> number | null
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function prismaDecimal(): z.ZodEffects<z.ZodAny, number, any>;
|
|
54
|
+
/**
|
|
55
|
+
* Nullable version of prismaDecimal
|
|
56
|
+
*
|
|
57
|
+
* Returns null for null/undefined inputs, otherwise converts to number.
|
|
58
|
+
*/
|
|
59
|
+
export declare function prismaDecimalNullable(): z.ZodEffects<z.ZodAny, number | null, any>;
|
|
60
|
+
/**
|
|
61
|
+
* Optional version of prismaDecimal
|
|
62
|
+
*
|
|
63
|
+
* Returns undefined for null/undefined inputs, otherwise converts to number.
|
|
64
|
+
*/
|
|
65
|
+
export declare function prismaDecimalOptional(): z.ZodEffects<z.ZodAny, number | undefined, any>;
|
|
38
66
|
/**
|
|
39
67
|
* Creates a date field that serializes to ISO string
|
|
40
68
|
*
|
|
@@ -59,6 +87,21 @@ export declare function dateToISOStringNullable(): z.ZodEffects<z.ZodNullable<z.
|
|
|
59
87
|
* Creates an optional date field that serializes to ISO string or undefined
|
|
60
88
|
*/
|
|
61
89
|
export declare function dateToISOStringOptional(): z.ZodEffects<z.ZodOptional<z.ZodDate>, string | undefined, Date | undefined>;
|
|
90
|
+
/**
|
|
91
|
+
* Alias for dateToISOString for naming consistency
|
|
92
|
+
* @alias dateToISOString
|
|
93
|
+
*/
|
|
94
|
+
export declare const dateToIso: typeof dateToISOString;
|
|
95
|
+
/**
|
|
96
|
+
* Alias for dateToISOStringNullable for naming consistency
|
|
97
|
+
* @alias dateToISOStringNullable
|
|
98
|
+
*/
|
|
99
|
+
export declare const dateToIsoNullable: typeof dateToISOStringNullable;
|
|
100
|
+
/**
|
|
101
|
+
* Alias for dateToISOStringOptional for naming consistency
|
|
102
|
+
* @alias dateToISOStringOptional
|
|
103
|
+
*/
|
|
104
|
+
export declare const dateToIsoOptional: typeof dateToISOStringOptional;
|
|
62
105
|
/**
|
|
63
106
|
* Standard timestamp fields for entities
|
|
64
107
|
*
|
|
@@ -8,6 +8,100 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { z } from 'zod';
|
|
10
10
|
// ============================================================================
|
|
11
|
+
// Prisma Decimal Helpers
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Creates a field that accepts Prisma Decimal and transforms to number
|
|
15
|
+
*
|
|
16
|
+
* Use in OUTPUT schemas where Prisma returns Decimal objects.
|
|
17
|
+
* Handles Prisma Decimal, regular numbers, and string representations.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const ProductSchema = z.object({
|
|
22
|
+
* id: z.string(),
|
|
23
|
+
* price: prismaDecimal(), // Decimal -> number
|
|
24
|
+
* discount: prismaDecimalNullable() // Decimal | null -> number | null
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function prismaDecimal() {
|
|
29
|
+
return z.any().transform((val) => {
|
|
30
|
+
if (val === null || val === undefined) {
|
|
31
|
+
throw new Error('Expected Decimal, got null/undefined');
|
|
32
|
+
}
|
|
33
|
+
// Prisma Decimal has toNumber() method
|
|
34
|
+
if (typeof val === 'object' && 'toNumber' in val && typeof val.toNumber === 'function') {
|
|
35
|
+
return val.toNumber();
|
|
36
|
+
}
|
|
37
|
+
// Already a number
|
|
38
|
+
if (typeof val === 'number') {
|
|
39
|
+
return val;
|
|
40
|
+
}
|
|
41
|
+
// String (from JSON)
|
|
42
|
+
if (typeof val === 'string') {
|
|
43
|
+
const num = Number.parseFloat(val);
|
|
44
|
+
if (Number.isNaN(num)) {
|
|
45
|
+
throw new Error(`Cannot convert "${val}" to number`);
|
|
46
|
+
}
|
|
47
|
+
return num;
|
|
48
|
+
}
|
|
49
|
+
throw new Error(`Cannot convert ${typeof val} to number`);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Nullable version of prismaDecimal
|
|
54
|
+
*
|
|
55
|
+
* Returns null for null/undefined inputs, otherwise converts to number.
|
|
56
|
+
*/
|
|
57
|
+
export function prismaDecimalNullable() {
|
|
58
|
+
return z.any().transform((val) => {
|
|
59
|
+
if (val === null || val === undefined) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
if (typeof val === 'object' && 'toNumber' in val && typeof val.toNumber === 'function') {
|
|
63
|
+
return val.toNumber();
|
|
64
|
+
}
|
|
65
|
+
if (typeof val === 'number') {
|
|
66
|
+
return val;
|
|
67
|
+
}
|
|
68
|
+
if (typeof val === 'string') {
|
|
69
|
+
const num = Number.parseFloat(val);
|
|
70
|
+
if (Number.isNaN(num)) {
|
|
71
|
+
throw new Error(`Cannot convert "${val}" to number`);
|
|
72
|
+
}
|
|
73
|
+
return num;
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Cannot convert ${typeof val} to number`);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Optional version of prismaDecimal
|
|
80
|
+
*
|
|
81
|
+
* Returns undefined for null/undefined inputs, otherwise converts to number.
|
|
82
|
+
*/
|
|
83
|
+
export function prismaDecimalOptional() {
|
|
84
|
+
return z.any().transform((val) => {
|
|
85
|
+
if (val === null || val === undefined) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
if (typeof val === 'object' && 'toNumber' in val && typeof val.toNumber === 'function') {
|
|
89
|
+
return val.toNumber();
|
|
90
|
+
}
|
|
91
|
+
if (typeof val === 'number') {
|
|
92
|
+
return val;
|
|
93
|
+
}
|
|
94
|
+
if (typeof val === 'string') {
|
|
95
|
+
const num = Number.parseFloat(val);
|
|
96
|
+
if (Number.isNaN(num)) {
|
|
97
|
+
throw new Error(`Cannot convert "${val}" to number`);
|
|
98
|
+
}
|
|
99
|
+
return num;
|
|
100
|
+
}
|
|
101
|
+
throw new Error(`Cannot convert ${typeof val} to number`);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// ============================================================================
|
|
11
105
|
// Date Field Helpers
|
|
12
106
|
// ============================================================================
|
|
13
107
|
/**
|
|
@@ -46,6 +140,21 @@ export function dateToISOStringOptional() {
|
|
|
46
140
|
.optional()
|
|
47
141
|
.transform((date) => (date ? date.toISOString() : undefined));
|
|
48
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Alias for dateToISOString for naming consistency
|
|
145
|
+
* @alias dateToISOString
|
|
146
|
+
*/
|
|
147
|
+
export const dateToIso = dateToISOString;
|
|
148
|
+
/**
|
|
149
|
+
* Alias for dateToISOStringNullable for naming consistency
|
|
150
|
+
* @alias dateToISOStringNullable
|
|
151
|
+
*/
|
|
152
|
+
export const dateToIsoNullable = dateToISOStringNullable;
|
|
153
|
+
/**
|
|
154
|
+
* Alias for dateToISOStringOptional for naming consistency
|
|
155
|
+
* @alias dateToISOStringOptional
|
|
156
|
+
*/
|
|
157
|
+
export const dateToIsoOptional = dateToISOStringOptional;
|
|
49
158
|
// ============================================================================
|
|
50
159
|
// Timestamp Schema Presets
|
|
51
160
|
// ============================================================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veloxts/validation",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.69",
|
|
4
4
|
"description": "Zod integration and validation middleware for VeloxTS framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"zod": "3.25.76",
|
|
26
|
-
"@veloxts/core": "0.6.
|
|
26
|
+
"@veloxts/core": "0.6.69"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@vitest/coverage-v8": "4.0.16",
|