@stacksjs/validation 0.75.203 → 0.75.205
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/input.d.ts +2 -0
- package/dist/input.js +1 -1
- package/package.json +7 -7
package/dist/input.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare function parseNumberInput(value: unknown, field: string, min: num
|
|
|
6
6
|
export declare function parseBooleanInput(value: unknown, field: string): boolean | undefined;
|
|
7
7
|
/** Validate supplied fields only, so partial updates use the model's own rules. */
|
|
8
8
|
export declare function validateModelInput(model: InputValidatableModel, values: Record<string, unknown>): void;
|
|
9
|
+
/** Membership guard for boundaries that provide their own protocol error response. */
|
|
10
|
+
export declare function isEnumInput<const T extends readonly string[]>(value: unknown, choices: T): value is T[number];
|
|
9
11
|
/** Exact enum membership without turning objects or numbers into text. */
|
|
10
12
|
export declare function parseEnumInput<const T extends readonly string[]>(value: unknown, field: string, choices: T): T[number];
|
|
11
13
|
/** Validate a bounded enum list as an ordered set, without silently dropping invalid entries. */
|
package/dist/input.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export class InputValidationError extends Error{status=422}export async function readJsonObject(request){let body;try{body=await request.json()}catch{throw new InputValidationError("Send a valid JSON object")}if(!body||typeof body!=="object"||Array.isArray(body))throw new InputValidationError("Send a JSON object");return body}export function parsePositiveId(value){if(typeof value!=="string"&&typeof value!=="number")throw new InputValidationError("Invalid identifier");const id=Number(value);if(!Number.isSafeInteger(id)||id<=0)throw new InputValidationError("Invalid identifier");return id}export function parseTextInput(value,field,required=!1,maxLength){if(value==null&&!required)return null;if(typeof value!=="string")throw new InputValidationError(`${field} must be text`);const text=value.trim();if(maxLength!==void 0&&text.length>maxLength)throw new InputValidationError(`${field} is too long`);if(!text&&required)throw new InputValidationError(`${field} is required`);return text||null}export function parseNumberInput(value,field,min,max,integer=!1){if(value==null||value==="")return null;if(typeof value!=="number"&&typeof value!=="string"||typeof value==="string"&&!value.trim())throw new InputValidationError(`${field} must be a number`);const number=Number(value);if(!Number.isFinite(number)||number<min||number>max||integer&&!Number.isSafeInteger(number))throw new InputValidationError(`${field} is out of range`);return number}export function parseBooleanInput(value,field){if(value===void 0)return;if(value===!0||value==="true"||value===1||value==="1")return!0;if(value===!1||value==="false"||value===0||value==="0")return!1;throw new InputValidationError(`${field} must be a boolean`)}export function validateModelInput(model,values){const attributes=model.getDefinition().attributes??{};for(const[field,value]of Object.entries(values)){const attribute=Object.prototype.hasOwnProperty.call(attributes,field)?field:Object.keys(attributes).find((key)=>key===field||key.replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()===field),rule=attribute?attributes[attribute]?.validation?.rule:void 0;if(rule&&!rule.validate(value).valid)throw new InputValidationError(`Invalid ${field.replaceAll("_"," ")}`)}}export function
|
|
1
|
+
export class InputValidationError extends Error{status=422}export async function readJsonObject(request){let body;try{body=await request.json()}catch{throw new InputValidationError("Send a valid JSON object")}if(!body||typeof body!=="object"||Array.isArray(body))throw new InputValidationError("Send a JSON object");return body}export function parsePositiveId(value){if(typeof value!=="string"&&typeof value!=="number")throw new InputValidationError("Invalid identifier");const id=Number(value);if(!Number.isSafeInteger(id)||id<=0)throw new InputValidationError("Invalid identifier");return id}export function parseTextInput(value,field,required=!1,maxLength){if(value==null&&!required)return null;if(typeof value!=="string")throw new InputValidationError(`${field} must be text`);const text=value.trim();if(maxLength!==void 0&&text.length>maxLength)throw new InputValidationError(`${field} is too long`);if(!text&&required)throw new InputValidationError(`${field} is required`);return text||null}export function parseNumberInput(value,field,min,max,integer=!1){if(value==null||value==="")return null;if(typeof value!=="number"&&typeof value!=="string"||typeof value==="string"&&!value.trim())throw new InputValidationError(`${field} must be a number`);const number=Number(value);if(!Number.isFinite(number)||number<min||number>max||integer&&!Number.isSafeInteger(number))throw new InputValidationError(`${field} is out of range`);return number}export function parseBooleanInput(value,field){if(value===void 0)return;if(value===!0||value==="true"||value===1||value==="1")return!0;if(value===!1||value==="false"||value===0||value==="0")return!1;throw new InputValidationError(`${field} must be a boolean`)}export function validateModelInput(model,values){const attributes=model.getDefinition().attributes??{};for(const[field,value]of Object.entries(values)){const attribute=Object.prototype.hasOwnProperty.call(attributes,field)?field:Object.keys(attributes).find((key)=>key===field||key.replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()===field),rule=attribute?attributes[attribute]?.validation?.rule:void 0;if(rule&&!rule.validate(value).valid)throw new InputValidationError(`Invalid ${field.replaceAll("_"," ")}`)}}export function isEnumInput(value,choices){return typeof value==="string"&&choices.includes(value)}export function parseEnumInput(value,field,choices){if(!isEnumInput(value,choices))throw new InputValidationError(`${field} must be ${choices.join(", ")}`);return value}export function parseEnumListInput(value,field,choices,minItems=1,maxItems=100){if(!Number.isSafeInteger(minItems)||!Number.isSafeInteger(maxItems)||minItems<0||maxItems<minItems)throw RangeError("Invalid enum list bounds");if(!Array.isArray(value)||value.length<minItems||value.length>maxItems)throw new InputValidationError(`${field} must contain ${minItems} to ${maxItems} entries`);return[...new Set(value.map((item)=>parseEnumInput(item,field,choices)))]}export function parseObjectInput(value,field){if(!value||typeof value!=="object"||Array.isArray(value)||![Object.prototype,null].includes(Object.getPrototypeOf(value)))throw new InputValidationError(`${field} must be a JSON object`);return value}export function parseArrayInput(value,field,minItems=0,maxItems=100){if(!Number.isSafeInteger(minItems)||!Number.isSafeInteger(maxItems)||minItems<0||maxItems<minItems)throw RangeError("Invalid array bounds");if(!Array.isArray(value)||value.length<minItems||value.length>maxItems)throw new InputValidationError(`${field} must contain ${minItems} to ${maxItems} entries`);return value}export function parsePositiveIdListInput(value,field,minItems=1,maxItems=100){const items=parseArrayInput(value,field,minItems,maxItems);try{return[...new Set(items.map(parsePositiveId))]}catch(error){if(error instanceof InputValidationError)throw new InputValidationError(`${field} contains an invalid identifier`);throw error}}export function storedBoolean(value,fallback){if(value==null)return fallback;try{return parseBooleanInput(value,"Stored value")??fallback}catch(error){if(error instanceof InputValidationError)return fallback;throw error}}export function positiveIdOrNull(value){try{return parsePositiveId(value)}catch(error){if(error instanceof InputValidationError)return null;throw error}}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/validation",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.205",
|
|
6
6
|
"description": "The Stacks Validation ways.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -64,18 +64,18 @@
|
|
|
64
64
|
"prepublishOnly": "bun run build"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@stacksjs/error-handling": "0.75.
|
|
68
|
-
"@stacksjs/path": "0.75.
|
|
69
|
-
"@stacksjs/strings": "0.75.
|
|
67
|
+
"@stacksjs/error-handling": "0.75.205",
|
|
68
|
+
"@stacksjs/path": "0.75.205",
|
|
69
|
+
"@stacksjs/strings": "0.75.205",
|
|
70
70
|
"@stacksjs/ts-validation": "^0.5.6",
|
|
71
|
-
"@stacksjs/types": "0.75.
|
|
72
|
-
"@stacksjs/utils": "0.75.
|
|
71
|
+
"@stacksjs/types": "0.75.205",
|
|
72
|
+
"@stacksjs/utils": "0.75.205"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"better-dx": "^0.2.24"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
|
-
"@stacksjs/database": "0.75.
|
|
78
|
+
"@stacksjs/database": "0.75.205"
|
|
79
79
|
},
|
|
80
80
|
"peerDependenciesMeta": {
|
|
81
81
|
"@stacksjs/database": {
|