Skip to main content

stacks-validation

Use when implementing validation in Stacks - type guards (isString, isNumber, isBoolean, isObject, isArray, isFunction, etc.), numeric checks (isPositive, isEven, isInteger), the schema builder for model attribute validation, or request validation. Covers @stacksjs/validation.

소스 정보

저장소
stacksjs/stacks
최근 소스 활동
2026년 8월 29일 17:05
감지된 SKILL.md 언어
영어
스타
631
포크
20

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
stacks-validation
description
Use when implementing validation in Stacks - type guards (isString, isNumber, isBoolean, isObject, isArray, isFunction, etc.), numeric checks (isPositive, isEven, isInteger), the schema builder for model attribute validation, or request validation. Covers @stacksjs/validation.
license
MIT
compatibility
Bun >= 1.3.0, TypeScript
allowed-tools
Read Edit Write Bash Grep Glob
# Stacks Validation ## Key Paths - Core package: `storage/framework/core/validation/src/` - Package: `@stacksjs/validation` ## Architecture The `index.ts` re-exports from multiple sources: ```typescript // Re-export everything from the validation library export * from '@stacksjs/ts-validation' // Local modules export * from './reporter' // error reporting export * from './validator' // model/custom validation export { schema } from './schema' // schema builder instance // Type guard functions defined directly in index.ts export function isString(value: unknown): value is string export function isNumber(value: unknown): value is number export function isBoolean(value: unknown): value is boolean export function isObject(value: unknown): value is Record<string, unknown> export function isArray(value: unknown): value is unknown[] export function isFunction(value: unknown): value is Function export function isUndefined(value: unknown): value is undefined export function isNull(value: unknown): value is null export function isNullOrUndefined(value: unknown): value is null | undefined ``` Additional type guards are in `is.ts` (but not directly imported by index.ts -- available via separate import). ## Type Guards (`index.ts`) Basic type guards with TypeScript type narrowing: ```typescript import { isString, isNumber, isBoolean, isObject, isArray, isFunction } from '@stacksjs/validation' isString('hello') // true -- typeof value === 'string' isNumber(42) // true -- typeof value === 'number' && !Number.isNaN(value) isNumber(NaN) // FALSE -- NaN is explicitly excluded isBoolean(true) // true -- typeof value === 'boolean' isObject({}) // true -- typeof === 'object' && !== null && !Array.isArray isObject([]) // FALSE -- arrays are excluded isObject(null) // FALSE -- null is excluded isArray([]) // true -- Array.isArray() isFunction(() => {}) // true -- typeof value === 'function' isUndefined(undefined) // true isNull(null) // true isNullOrUndefined(null) // true isNullOrUndefined(undefined) // true ``` ## Extended Type Guards (`is.ts`) Additional guards using `getTypeName()` from `@stacksjs/types` and `toString()` from `@stacksjs/strings`: ```typescript isDef(value) // true if typeof value !== 'undefined' isMap(new Map()) // true -- toString check '[object Map]' isSet(new Set()) // true -- toString check '[object Set]' isPromise(Promise.resolve()) // true -- toString check '[object Promise]' isSymbol(Symbol()) // true isDate(new Date()) // true isRegExp(/test/) // true isWindow(globalThis) // true in browser -- toString check '[object Window]' isPrimitive(42) // true (string, number, boolean, null, undefined, symbol) isPrimitive({}) // false // Environment detection isBrowser: boolean // typeof window !== 'undefined' isServer: boolean // typeof document === 'undefined' ``` ## Numeric Checks (`is.ts`) ```typescript isInteger(42) // true -- Number.isInteger() isInteger(42.0) // true -- 42.0 is an integer in JS isFloat(3.14) // true -- isNumber && !Number.isInteger isFloat(42) // false isPositive(5) // true -- > 0 isNegative(-5) // true -- < 0 isEven(4) // true -- % 2 === 0 isOdd(3) // true -- % 2 !== 0 // Classification functions (return string, not boolean) isEvenOrOdd(4) // 'even' isEvenOrOdd(3) // 'odd' isEvenOrOdd('not a number') // 'odd' -- non-numbers default to 'odd' isPositiveOrNegative(5) // 'positive' isPositiveOrNegative(-5) // 'negative' isPositiveOrNegative('x') // 'negative' -- non-numbers default to 'negative' isIntegerOrFloat(42) // 'integer' isIntegerOrFloat(3.14) // 'float' isIntegerOrFloat('x') // 'float' -- non-numbers default to 'float' ``` ## Schema Builder (`schema.ts`) The `schema` object is an instance of `ValidationInstance` from `@stacksjs/ts-validation`. It provides fluent validators for model attribute definitions. ```typescript import { schema } from '@stacksjs/validation' ``` ### Available Schema Types ```typescript // String types schema.string() // StringValidatorType schema.string().min(2) // chain: min length schema.string().max(100) // chain: max length schema.string().email() // chain: must be email schema.string().url() // chain: must be URL schema.string().matches(/pattern/) // chain: regex match schema.string().equals('exact') // chain: exact match schema.string().alphanumeric() // chain: alphanumeric only schema.string().alpha() // chain: letters only schema.string().numeric() // chain: numeric string schema.string().custom(fn, msg) // chain: custom validator schema.text() // TextValidatorType (extends StringValidatorType) // Number types schema.number() // NumberValidatorType schema.number().min(0).max(100) // chain: min/max schema.bigint() // BigintValidatorType schema.integer() // IntegerValidatorType schema.smallint() // SmallintValidatorType schema.float() // FloatValidatorType schema.double() // DoubleValidatorType schema.decimal() // DecimalValidatorType // Boolean schema.boolean() // BooleanValidatorType // Enum schema.enum(['draft', 'published', 'archived']) // EnumValidatorType // Date/time types schema.date() // DateValidatorType schema.datetime() // DatetimeValidatorType schema.timestamp() // TimestampValidatorType schema.timestampTz() // TimestampTzValidatorType (with timezone) schema.unix() // UnixValidatorType schema.time() // TimeValidatorType // Binary/blob schema.binary() // BinaryValidatorType schema.blob() // BlobValidatorType // JSON schema.json() // JsonValidatorType // Password schema.password() // PasswordValidatorType // Array schema.array<T>() // ArrayValidatorType<T> // Object schema.object<T>(shapeSchema?) // ObjectValidatorType<T> // Custom schema.custom<T>(validationFn, message) // CustomValidatorType<T> ``` ### Model Attribute Usage Schema validators are used in `defineModel()` attribute validation: ```typescript import { defineModel } from '@stacksjs/config' import { schema } from '@stacksjs/validation' export default defineModel({ attributes: { name: { validation: { rule: schema.string().min(2).max(100), message: { min: 'Name must be at least 2 characters', max: 'Name cannot exceed 100 characters', } } }, email: { validation: { rule: schema.string().email(), message: { email: 'Please provide a valid email address', } } }, price: { validation: { rule: schema.number().min(1), message: { min: 'Price must be at least 1', } } }, status: { validation: { rule: schema.enum(['active', 'inactive', 'archived']), message: { enum: 'Invalid status value', } } }, bio: { validation: { rule: schema.string().max(500), message: { max: 'Bio cannot exceed 500 characters', } } }, } }) ``` ## Model Validation (`validator.ts`) ### `validateField(modelFile, params)` Validates request data against a model's attribute rules. Used internally by the framework for API request validation. ```typescript import { validateField } from '@stacksjs/validation' // Loads model file, extracts validation rules, validates params const result = await validateField('User', { name: 'John', email: 'john@example.com' }) ``` Behavior: 1. Finds the model file by name in user models or framework defaults 2. Extracts validation rules from model attributes 3. Converts attribute names to snake_case for validation 4. Sets custom error messages via `MessageProvider` 5. Validates using `schema.object(ruleObject).validate(params)` 6. Throws `HttpError(422)` with error JSON on validation failure 7. Throws `HttpError(404)` if model not found 8. Skips validation for attributes with default values unless `isRequired` is true ### `customValidate(attributes, params)` Validates request data against custom attribute rules (not tied to a model): ```typescript import { customValidate } from '@stacksjs/validation' const result = await customValidate({ email: { rule: schema.string().email(), message: { email: 'Invalid email' } }, age: { rule: schema.number().min(18), message: { min: 'Must be at least 18' } } }, requestData) ``` Uses `schema.object().shape(ruleObject)` for validation. ### `isObjectNotEmpty(obj)` ```typescript isObjectNotEmpty({}) // false isObjectNotEmpty({ a: 1 }) // true isObjectNotEmpty(undefined) // false ``` ## Error Reporter (`reporter.ts`) Simple error accumulator for validation: ```typescript import { reportError, getErrors } from '@stacksjs/validation' reportError([{ message: 'Invalid', value: '', field: 'email' }]) const errors = getErrors() // returns accumulated MessageObject[] ``` Interface: `{ message: string, value: string, field: string }` ## Error Reporter Contract (from `rules.ts`) VineJS-inspired types for the validation pipeline: ```typescript interface FieldContext { value: unknown data: any // top-level object under validation meta: Record<string, any> mutate: (newValue: any, field: FieldContext) => void report: ErrorReporterContract['report'] isValid: boolean isDefined: boolean wildCardPath: string // nested pointer, '*' for array members parent: any name: string | number isArrayMember: boolean } interface ErrorReporterContract { hasErrors: boolean createError: () => Error report: (message: string, rule: string, field: FieldContext, args?: Record<string, any>) => any } ``` ## Re-exports from @stacksjs/ts-validation The package re-exports everything from `@stacksjs/ts-validation`, which includes: - `v` and `schema` -- the validation instance - `validator` -- the validator library (default export from lib) - `MessageProvider`, `setCustomMessages` -- custom message handling - All type definitions (ValidatorType, StringValidatorType, NumberValidatorType, etc.) - Configuration utilities ## Validation Types (`types/index.ts`) Local type definitions: ```typescript interface ValidationResult { valid: boolean errors?: Array<{ message: string }> } interface ValidationRule { validate: (value: unknown) => ValidationResult } type ValidationBoolean = ValidationRule type ValidationEnum = ValidationRule type ValidationNumber = ValidationRule type ValidationString = ValidationRule ``` ## Gotchas - `isNumber()` in `index.ts` returns FALSE for `NaN` -- this differs from `typeof NaN === 'number'` - `isObject()` in `index.ts` excludes arrays and null -- `isObject([])` is false - `isObject()` in `is.ts` uses `toString()` check (`[object Object]`) which also excludes arrays/null but through a different mechanism - `isPrimitive()` includes null and undefined (6 primitive types: string, number, boolean, null, undefined, symbol) - Numeric classification functions (`isEvenOrOdd`, etc.) return string defaults for non-numbers rather than throwing - Schema validators map to database column types -- `schema.integer()` creates an integer column, `schema.string()` creates a varchar, etc. - `validateField` converts attribute names to snake_case using `snakeCase()` from `@stacksjs/strings` - `validateField` skips attributes with default values unless `isRequired` is explicitly set - Validation error messages are customizable per-rule in model definitions via the `message` object - The `schema` export is the `v` instance from `@stacksjs/ts-validation` -- they are the same object - Custom validators can be added with `schema.custom<T>(fn, message)` for types not covered by built-in validators - `customValidate` uses `schema.object().shape()` while `validateField` uses `schema.object(ruleObject)` -- slightly different API
GitHub에서 보기