@regle/mcp-server 1.18.2 → 1.18.3
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/regle-mcp-server.js +16 -16
- package/package.json +3 -3
package/dist/regle-mcp-server.js
CHANGED
|
@@ -20,7 +20,7 @@ var docs_data_default = {
|
|
|
20
20
|
"title": "Global configuration",
|
|
21
21
|
"category": "advanced-usage",
|
|
22
22
|
"path": "advanced-usage/global-config.md",
|
|
23
|
-
"content": "# Global configuration\n\nIf your app includes multiple forms, it can be helpful to define a global configuration that centralizes your custom validators, error messages, and modifiers. This eliminates the need to declare these settings repeatedly for every `useRegle` call, improving both code consistency and developer experience with features like autocompletion and type checking.\n\n## Replace built-in rules messages\n\nEach `@regle/rules` rule provides a default error message. You may
|
|
23
|
+
"content": "# Global configuration\n\nIf your app includes multiple forms, it can be helpful to define a global configuration that centralizes your custom validators, error messages, and modifiers. This eliminates the need to declare these settings repeatedly for every `useRegle` call, improving both code consistency and developer experience with features like autocompletion and type checking.\n\n## Replace built-in rules messages\n\nEach `@regle/rules` rule provides a default error message. You may not want to call `withMessage` every time you need to use one with a custom error message.\n\n`defineRegleConfig` allows you to redefine the default messages of built-in rules.\n\n```ts\nimport { defineRegleConfig } from '@regle/core';\nimport { withMessage, minLength, required } from '@regle/rules';\n\nconst { useRegle: useCustomRegle } = defineRegleConfig({\n rules: () => ({\n required: withMessage(required, 'You need to provide a value'),\n minLength: withMessage(minLength, ({ $value, $params: [min] }) => {\n return `Minimum length is ${min}. Current length: ${$value?.length}`;\n })\n })\n})\n\nconst { r$ } = useCustomRegle({ name: '' }, {\n name: {\n required,\n minLength: minLength(6)\n }\n})\n```\n\nResult: \n\n:::tip\nIf you use Nuxt, check out the [Nuxt module](/integrations/nuxt) for a even better DX. \nIt provides a way to add your custom global config to your auto-imports.\n:::\n\n### i18n\n\nYou can also use any i18n library directly inside the config.\n\n```ts\nimport { defineRegleConfig } from '@regle/core';\nimport { withMessage, minLength, required } from '@regle/rules';\nimport { useI18n } from 'vue-i18n';\n\nconst { useRegle: useCustomRegle } = defineRegleConfig({\n rules: () => {\n const { t } = useI18n()\n\n return {\n required: withMessage(required, t('general.required')),\n minLength: withMessage(minLength, ({ $value, $params: [max] }) => {\n return t('general.minLength', {max});\n })\n }\n }\n})\n```\n\n## Declare new rules\n\nWhile `useRegle` allows you to use any rule key, adding custom rules to the global configuration provides autocompletion and type checking. This improves maintainability and consistency across your application.\n\n```ts twoslash\nconst someAsyncCall = async () => await Promise.resolve(true);\n// ---cut---\n\nimport { defineRegleConfig, createRule, Maybe } from '@regle/core';\nimport { withMessage, isFilled } from '@regle/rules';\n\nconst asyncEmail = createRule({\n async validator(value: Maybe<string>) {\n if (!isFilled(value)) {\n return true;\n }\n\n const result = await someAsyncCall();\n return result;\n },\n message: 'Email already exists',\n});\n\nconst { useRegle: useCustomRegle } = defineRegleConfig({\n rules: () => ({\n asyncEmail\n })\n})\n\nconst { r$ } = useCustomRegle({ name: '' }, {\n name: {\n asy\n\n }\n})\n```\n\n## Declare modifiers\n\nYou can include global modifiers in your configuration to automatically apply them wherever you use the `useRegle` composable. This avoids repetitive declarations and keeps your code clean.\n\n```ts\nimport { defineRegleConfig } from '@regle/core';\nimport { withMessage, minLength, required } from '@regle/rules';\n\nexport const { useRegle: useCustomRegle } = defineRegleConfig({\n modifiers: {\n autoDirty: false,\n silent: true,\n lazy: true,\n rewardEarly: true\n }\n})\n```\n\n## Export scoped `inferRules` helper\n\n`defineRegleConfig` also returns a scoped `inferRules` helper, similar to the one exported from `@regle/core`, but that will autocomplete and check your custom rules.\n\nFor information about `inferRules`, check [Typing rules docs](/typescript/typing-rules)\n\n```ts\nimport { defineRegleConfig } from '@regle/core';\nimport { withMessage, minLength, required } from '@regle/rules';\n\nexport const { useRegle, inferRules } = defineRegleConfig({/* */})\n```\n\n## Extend global config\n\nIt's also possible to add additional config to an already created custom `useRegle`.\n\nWith `extendRegleConfig`, you can recreate a custom one with a existing composable as an input.\n\n```ts twoslash\n\nimport { defineRegleConfig, extendRegleConfig, createRule } from '@regle/core';\nimport { withMessage, required } from '@regle/rules';\n\nconst { useRegle: useCustomRegle } = defineRegleConfig({\n rules: () => ({\n customRule: withMessage(required, 'Custom rule'),\n })\n})\n\nconst {useRegle: useExtendedRegle} = extendRegleConfig(useCustomRegle, {\n rules: () => ({\n customRuleExtended: withMessage(required, 'Custom rule 2'),\n })\n})\n\nuseExtendedRegle({name: ''}, {\n name: {\n custom\n \n }\n})\n\n```\n\n## Override default behaviors\n\nYou can override the default behaviors of Regle processors by using the `overrides` property.\n\n### `isEdited`\n\nOverride the default `$edited` property handler. Useful to handle custom comparisons for complex object types.\n\n:::warning\nIt's highly recommended to use this override with the [`markStatic`](/advanced-usage/immutable-constructors) helper to handle immutable constructors.\n:::\n\n```ts\nimport { defineRegleConfig } from '@regle/core';\nimport { Decimal } from 'decimal.js';\n\nexport const { useRegle: useCustomRegle } = defineRegleConfig({\n overrides: {\n isEdited(currentValue, initialValue, defaultHandlerFn) {\n if (currentValue instanceof Decimal && initialValue instanceof Decimal) {\n return currentValue.toNearest(0.01).toString() !== initialValue.toNearest(0.01).toString();\n }\n // fallback to the default handler\n return defaultHandlerFn(currentValue, initialValue);\n },\n },\n})\n```"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"id": "advanced-usage-immutable-constructors",
|
|
@@ -34,7 +34,7 @@ var docs_data_default = {
|
|
|
34
34
|
"title": "Merge multiple Regles",
|
|
35
35
|
"category": "advanced-usage",
|
|
36
36
|
"path": "advanced-usage/merge-regles.md",
|
|
37
|
-
"content": "# Merge multiple Regles\n\nIf you need to combine multiple Regle instances into one, it's possible with the `mergeRegles` helper.\n\
|
|
37
|
+
"content": "# Merge multiple Regles\n\nIf you need to combine multiple Regle instances into one, it's possible with the `mergeRegles` helper.\n\n## When to use\n\n`mergeRegles` is useful when:\n- You have forms split across multiple components and need to validate them together\n- You want to compose smaller, reusable form sections into a larger form\n- Different parts of your form have different validation lifecycles but need unified submission\n\n## Basic usage\n\nThe helper returns an output similar to the main `r$`, while still being able to call `$touch`, `$validate`, or `$reset` on all merged instances at once.\n\nAll types are preserved, giving you full autocomplete support.\n\n```ts twoslash\nimport {required, numeric, email} from '@regle/rules';\n// ---cut---\n\nimport { mergeRegles, useRegle } from '@regle/core';\n\nconst { r$ } = useRegle({email: ''}, {\n email: { required, email },\n});\n\nconst { r$: otherR$ } = useRegle({firstName: ''}, {\n firstName: { required },\n});\n\nconst r$Merged = mergeRegles({ r$, otherR$ });\n\nr$Merged.$value.otherR$.\n\n```\n\nResult:\n\n## Accessing merged data\n\nYou can access each merged instance's data through the merged object:\n\n```ts\n// Access values\nr$Merged.$value.r$.email\nr$Merged.$value.otherR$.firstName\n\n// Access validation states\nr$Merged.r$.email.$valid\nr$Merged.otherR$.firstName.$error\n\n// Access errors\nr$Merged.$errors.r$.email\nr$Merged.$errors.otherR$.firstName\n```\n\n## Global operations\n\nThe merged instance exposes global methods that operate on all child instances:\n\n```ts\n// Validate all merged forms\nawait r$Merged.$validate()\n\n// Reset all merged forms\nr$Merged.$reset({ toInitialState: true })\n\n// Touch all fields\nr$Merged.$touch()\n```\n\n:::tip\nThe merged instance's `$valid`, `$error`, and `$pending` properties reflect the combined state of all child instances.\n:::"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"id": "advanced-usage-rule-metadata",
|
|
@@ -76,7 +76,7 @@ var docs_data_default = {
|
|
|
76
76
|
"title": "Async validations",
|
|
77
77
|
"category": "common-usage",
|
|
78
78
|
"path": "common-usage/async-validation.md",
|
|
79
|
-
"content": "# Async validation\n\nA common pattern in forms is to asynchronously check for a value on the server side.\nAsync rules can perform these tasks, and they update the `$pending` state whenever invoked.\n\n:::tip\nBy default, all async rules will be debounced by `200ms`. It can be
|
|
79
|
+
"content": "# Async validation\n\nA common pattern in forms is to asynchronously check for a value on the server side.\nAsync rules can perform these tasks, and they update the `$pending` state whenever invoked.\n\n:::tip\nBy default, all async rules will be debounced by `200ms`. It can be overridden with the `$debounce` modifier.\n:::\n\n## Inline Async rule\n\nTo declare an async rule, you simply have to use the `async await` syntax.\n\n```ts\nconst myAsyncRule = async (value: Maybe<number>) => {\n if (isFilled(value)) {\n return await someStuff();\n }\n return true;\n}\n```\n\nIf your rule doesn't use `async await` syntax, but still returns a `Promise`, you have to use the `withAsync` helper when using your rule in your form. Otherwise, Regle can't know it's an async rule.\n\n## Async using `createRule`\n\nIn the same way of an inline rule, your validator function must be using `async await` to be declared as an async rule.\n\n```ts\nconst myAsyncRule = createRule({\n async validator(value: Maybe<string>) {\n if (isFilled(value)) {\n return await someStuff();\n }\n return true;\n },\n message: 'Error'\n})\n```\n\n## `$pending` property\n\nEvery time you update the `$value` of the field using an async rule, the `$pending` [validation property](/core-concepts/validation-properties#pending) will be updated. The `$error` status depends on `$pending` so a field cannot be errored if it's still pending.\n\nThis can be used to display a loading icon and a custom message indicating that an operation is taking time.\n\n## Full example\n\n```vue [App.vue]\n<template>\n <div class=\"demo-container\">\n <div>\n <input\n v-model=\"form.email\"\n :class=\"{ pending: r$.email.$pending }\"\n placeholder=\"Type your email\"\n />\n\n <button type=\"button\" @click=\"r$.$reset({toInitialState: true})\">Reset</button>\n <button type=\"button\" @click=\"r$.$validate()\">Submit</button>\n </div>\n\n <span v-if=\"r$.email.$pending\"> Checking... </span>\n \n <ul v-if=\"r$.$errors.email.length\">\n <li v-for=\"error of r$.$errors.email\" :key=\"error\">\n {{ error }}\n </li>\n </ul>\n </div>\n</template>\n\n```"
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
"id": "common-usage-collections",
|
|
@@ -97,14 +97,14 @@ var docs_data_default = {
|
|
|
97
97
|
"title": "Reset forms",
|
|
98
98
|
"category": "common-usage",
|
|
99
99
|
"path": "common-usage/reset-form.md",
|
|
100
|
-
"content": "# Reset forms\n\nRegle offers multiple options to reset a form. It depends on your use case and what you want to achieve.\n\nIt can be either:\n- Only resetting the validation state ($dirty, $invalid, $pending etc..)\n- Only resetting the form state ($value) and keeping the validation state\n- Resetting the form state to a given state and keeping the validation state\n- Resetting the form state to a given state and clearing the validation state\n- Reset both form state and validation state to a pristine state\n\n## Basic usage, with `$reset` method\n\nThe `$reset` method is available on every nested instance of field of a form. So you can reset fields individually or the whole form.\n\n### Options\n\n
|
|
100
|
+
"content": "# Reset forms\n\nRegle offers multiple options to reset a form. It depends on your use case and what you want to achieve.\n\nIt can be either:\n- Only resetting the validation state ($dirty, $invalid, $pending etc..)\n- Only resetting the form state ($value) and keeping the validation state\n- Resetting the form state to a given state and keeping the validation state\n- Resetting the form state to a given state and clearing the validation state\n- Reset both form state and validation state to a pristine state\n\n## Basic usage, with `$reset` method\n\nThe `$reset` method is available on every nested instance of field of a form. So you can reset fields individually or the whole form.\n\n### Options\n\nThe `$reset` method accepts an options object with the following properties:\n\n#### `toInitialState`\n- **Type:** `boolean`\n- **Description:** \n Reset validation status and reset form state to its initial state. \n Initial state is different from the original state, as it can be mutated when using `$reset`. This serves as the base comparison for `$edited`. \n ⚠️ This doesn't work if the state is a `reactive` object.\n\n#### `toOriginalState`\n- **Type:** `boolean`\n- **Description:** \n Reset validation status and reset form state to its original state. \n Original state is the unmutated state that was passed to the form when it was initialized.\n\n#### `toState`\n- **Type:** `TState` or `() => TState`\n- **Description:** \n Reset validation status and reset form state to the given state. Also sets the new state as the new initial state.\n\n#### `clearExternalErrors`\n- **Type:** `boolean`\n- **Description:** \n Clears the `$externalErrors` state back to an empty object.\n\n```ts\nr$.$reset(); // Only reset validation state, set the initialValue as the current value\n```\n\n```ts\nr$.$reset({ toInitialState: true }); // Reset validation state and form state to initial state\n```\n\n```ts\nr$.$reset({ toOriginalState: true }); // Reset validation state and form state to original state\n```\n\n```ts\nr$.$reset({ toState: { email: 'test@test.com' } }); // Reset validation state and form state to the given state\n```\n\n```ts\nr$.$reset({ clearExternalErrors: true }); // Clear $externalErrors state\n```\n\n## Example\n\n```vue\n<template>\n <input\n v-model=\"r$.$value.email\"\n :class=\"{ valid: r$.email.$correct, error: r$.email.$error }\"\n placeholder=\"Type your email\"\n />\n <ul v-if=\"r$.$errors.email.length\">\n <li v-for=\"error of r$.$errors.email\" :key=\"error\">\n {{ error }}\n </li>\n </ul>\n <div>\n <button type=\"button\" @click=\"r$.$reset()\">Reset validation state</button>\n <button type=\"button\" @click=\"r$.$reset({ toInitialState: true })\">Reset to initial state</button>\n <button type=\"button\" @click=\"r$.$reset({ toOriginalState: true })\">Reset to original state</button>\n <button type=\"button\" @click=\"r$.$reset({ toState: { email: 'test@test.com' } })\"\n >Reset to a given state</button\n >\n <button class=\"primary\" type=\"button\" @click=\"r$.$validate()\">Submit</button>\n </div>\n</template>\n\n```\n\nResult:"
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
"id": "common-usage-standard-schema",
|
|
104
104
|
"title": "Standard Schema",
|
|
105
105
|
"category": "common-usage",
|
|
106
106
|
"path": "common-usage/standard-schema.md",
|
|
107
|
-
"content": "# Standard Schema\n\nRegle implements the [Standard Schema](https://standardschema.dev/) specification.\n\nThis means that you can use Regle on any third party package that supports the Standard Schema spec.\n\nRegle can also use itself as a schema library when using `useRegleSchema`.\n\n## Usage\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { required } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { required }\n})\n\nconst result = await r$.['~standard'].validate({ name: '' });\n\nconsole.log(result.issues);\n```\n\n### Schema only usage\n\n```ts\nimport { useRules } from '@regle/core';\nimport { required, string } from '@regle/rules';\n\nconst schema = useRules({\n name: { string, required }\n})\n\nconst result = await schema['~standard'].validate({ name: '' });\n```\n\n## Composition usage\n\n```vue\n<template>\n <input \n v-model='r$.$value.email' \n :class=\"{ error: r$.email.$error }\" \n placeholder='Type your email'\n />\n\n <li v-for=\"error of r$.email.$errors\" :key='error'>\n {{ error }}\n </li>\n</template>\n\n```\n\n### `InferInput`\n\n`InferInput` is an utility type that can produce a object state from any rules object.\n\nIt will try to extract the possible state type that a rule may have, prioritizing rules that have a strict input type.\n\nSome rules may have `unknown` type because it could apply to any value. To cover this, there is now type-helpers rules to help you type your state from the rules: `type`, `string`, `number`, `boolean`, `date`.\n\n:::info\nSome types like `numeric` will feel weird as it's typed `string | number`, it's normal as the rule can also validate numeric strings. You can enforce the type by applying `number` rule to it.\n:::\n\n```ts twoslash\nimport {ref} from 'vue';\n// ---cut---\nimport { defineRules, type InferInput} from '@regle/core';\nimport { required, string, numeric, type } from '@regle/rules';\n\n/* defineRules is not required, but it helps you catch errors in structure */\nconst rules = defineRules({\n firstName: { required, string },\n count: { numeric },\n enforceType: { required, type: type<'FOO' | 'BAR'>()}\n})\n\ntype State = InferInput<typeof rules>;\n\n```\n\n<br/>\n<br/>\n<br/>\n\n## `useRules`\n\n`useRules` is a composable that allows you to write your rules in a more declarative way.\n\nIt works exactly like `useRegle`, but it doesn't accept a state parameter, it will create
|
|
107
|
+
"content": "# Standard Schema\n\nRegle implements the [Standard Schema](https://standardschema.dev/) specification.\n\nThis means that you can use Regle on any third party package that supports the Standard Schema spec.\n\nRegle can also use itself as a schema library when using `useRegleSchema`.\n\n## Usage\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { required } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { required }\n})\n\nconst result = await r$.['~standard'].validate({ name: '' });\n\nconsole.log(result.issues);\n```\n\n### Schema only usage\n\n```ts\nimport { useRules } from '@regle/core';\nimport { required, string } from '@regle/rules';\n\nconst schema = useRules({\n name: { string, required }\n})\n\nconst result = await schema['~standard'].validate({ name: '' });\n```\n\n## Composition usage\n\n```vue\n<template>\n <input \n v-model='r$.$value.email' \n :class=\"{ error: r$.email.$error }\" \n placeholder='Type your email'\n />\n\n <li v-for=\"error of r$.email.$errors\" :key='error'>\n {{ error }}\n </li>\n</template>\n\n```\n\n### `InferInput`\n\n`InferInput` is an utility type that can produce a object state from any rules object.\n\nIt will try to extract the possible state type that a rule may have, prioritizing rules that have a strict input type.\n\nSome rules may have `unknown` type because it could apply to any value. To cover this, there is now type-helpers rules to help you type your state from the rules: `type`, `string`, `number`, `boolean`, `date`.\n\n:::info\nSome types like `numeric` will feel weird as it's typed `string | number`, it's normal as the rule can also validate numeric strings. You can enforce the type by applying `number` rule to it.\n:::\n\n```ts twoslash\nimport {ref} from 'vue';\n// ---cut---\nimport { defineRules, type InferInput} from '@regle/core';\nimport { required, string, numeric, type } from '@regle/rules';\n\n/* defineRules is not required, but it helps you catch errors in structure */\nconst rules = defineRules({\n firstName: { required, string },\n count: { numeric },\n enforceType: { required, type: type<'FOO' | 'BAR'>()}\n})\n\ntype State = InferInput<typeof rules>;\n\n```\n\n<br/>\n<br/>\n<br/>\n\n## `useRules`\n\n`useRules` is a composable that allows you to write your rules in a more declarative way.\n\nIt works exactly like `useRegle`, but it doesn't accept a state parameter, it will create an empty state from the rules.\n\n```ts twoslash\n\nimport { useRules, type InferInput } from '@regle/core';\nimport { required, string } from '@regle/rules';\n\nconst r$ = useRules({\n name: { required, string },\n});\n```\n\nResult:\n\n## `refineRules`\n\nRegle is state first because in real world forms, rules can depend a state values. \nThis make it a problem for dynamic rules as it would make a cyclic type error when trying to use the state inside the rules.\n\nTo cover this case and inspired by Zod's `refine`, Regle provides a `refineRules` helper to write dynamic rules that depend on the state, while making it possible to access a typed state.\n\nAnything returned by the rule refine function will override what's defined in the default rules.\n\n```ts twoslash\nimport {ref} from 'vue';\n// ---cut---\nimport { refineRules, type InferInput} from '@regle/core';\nimport { required, string, sameAs } from '@regle/rules';\n\nconst rules = refineRules({\n password: { required, string },\n}, \n (state) => ({\n confirmPassword: { required, sameAs: sameAs(() => state.value.password) }\n })\n)\n\ntype State = InferInput<typeof rules>;\n\n```"
|
|
108
108
|
},
|
|
109
109
|
{
|
|
110
110
|
"id": "common-usage-usage-with-pinia",
|
|
@@ -139,7 +139,7 @@ var docs_data_default = {
|
|
|
139
139
|
"title": "Built-in rules",
|
|
140
140
|
"category": "rules",
|
|
141
141
|
"path": "core-concepts/rules/built-in-rules.md",
|
|
142
|
-
"content": "# Built-in rules\n\nAll built-in rules are available through the `@regle/rules` package.\n\nDon't forget to install it if you haven't:\n\n::: code-group\n\n```sh [pnpm]\npnpm add @regle/rules\n```\n\n```sh [npm]\nnpm install @regle/rules\n```\n\n```sh [yarn]\nyarn add @regle/rules\n```\n\n```sh [bun]\nbun add @regle/rules\n```\n\n:::\n\n:::tip\nEvery built-in rule will check if the value of the field is set before checking if it's valid.\n\nThis allow to have rules even if the field is not required.\n:::\n\n## `alpha`\n\n_**Params**_\n - `allowSymbols?: MaybeRefOrGetter<boolean>`\n\nAllows only alphabetic characters.\n\n```ts\nimport { alpha } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { \n alpha,\n // or\n alpha: alpha({ allowSymbols: true }),\n },\n})\n```\n\n## `alphaNum`\n\n_**Params**_\n - `allowSymbols?: MaybeRefOrGetter<boolean>`\n\nAllows only alphanumeric characters.\n\n```ts\nimport { alphaNum } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { \n alphaNum,\n // or\n alphaNum: alphaNum({ allowSymbols: true }),\n})\n```\n\n## `atLeastOne`\n\n_**Params**_\n - `keys?: MaybeRefOrGetter<string[]>` - Optional list of keys to check. If not provided, checks if the object has at least one filled property.\n\n_**Works with**_\n - `Record | object`\n\nChecks if at least one key is filled in the object. Useful for object-level validation with `$self`.\n\n```ts\nimport { atLeastOne } from '@regle/rules';\n\nconst { r$ } = useRegle({ user: { firstName: '', lastName: '' } }, {\n user: {\n $self: {\n // Check if any property is filled\n atLeastOne,\n // or check specific keys\n atLeastOne: atLeastOne(['firstName', 'lastName']),\n },\n },\n})\n```\n\n## `between`\n\n_**Params**_\n - `min: Ref<number> | number | () => number`\n - `max: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\nChecks if a number is in specified bounds. `min` and `max` are both inclusive.\n\n```ts\nimport { between } from '@regle/rules';\n\nconst maxCount = ref(6);\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: {\n between: between(1, 6),\n between: between(1, maxCount, {allowEqual: false}),\n between: between(() => maxCount.value, 10)\n },\n})\n```\n\n## `boolean`\n\nRequires a value to be a native boolean type. Mainly used for typing.\n\n```ts\nimport {type InferInput} from '@regle/core';\nimport { boolean } from '@regle/rules';\n\nconst rules = {\n checkbox: { boolean },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `checked`\n\nRequires a boolean value to be `true`. This is useful for checkbox inputs.\n\n### Note\n\nThis rule does not need `required` to be set, it will assert the value is set.\n\n```ts\nimport { checked } from '@regle/rules';\n\nconst { r$ } = useRegle({ confirm: false }, {\n confirm: { checked },\n})\n```\n\n## `contains`\n\n_**Params**_\n- `contain: Ref<string> | string | () => string`\n\nChecks if the string contains the specified substring.\n\n```ts\nimport { contains } from '@regle/rules';\n\nconst { r$ } = useRegle({ bestLib: '' }, {\n bestLib: {\n contains: contains('regle')\n },\n})\n```\n\n## `date`\n\nRequires a value to be a native Date constructor. Mainly used for typing.\n\n```ts\nimport {type InferInput} from '@regle/core';\nimport { date } from '@regle/rules';\n\nconst rules = {\n birthday: { date },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `dateAfter`\n_**Params**_\n - `after: Ref<string | Date> | string | Date | () => string | Date`\n - `options?: {allowEqual?: boolean}`\n\nChecks if the date is after the given parameter.\n\n```ts\nimport { dateAfter } from '@regle/rules';\n\nconst today = ref(new Date());\n\nconst { r$ } = useRegle({ birthday: null as Date | null }, {\n birthday: {\n dateAfter: dateAfter(today),\n // or\n dateAfter: dateAfter(today, { allowEqual: false }),\n },\n})\n```\n\n## `dateBefore`\n_**Params**_\n - `before: Ref<string | Date> | string | Date | () => string | Date`\n - `options?: {allowEqual?: boolean}`\n\nChecks if the date is before the given parameter.\n\n```ts\nimport { dateBefore } from '@regle/rules';\n\nconst today = ref(new Date());\n\nconst { r$ } = useRegle({ birthday: null as Date | null }, {\n birthday: {\n dateBefore: dateBefore(today),\n // or\n dateBefore: dateBefore(today, { allowEqual: false }),\n },\n})\n```\n\n## `dateBetweeen`\n\n_**Params**_\n - `before: Ref<string | Date> | string | Date | () => string | Date`\n - `after: Ref<string | Date> | string | Date | () => string | Date`\n - `options?: {allowEqual?: boolean}`\n\nChecks if the date falls between the specified bounds.\n\n```ts\nimport { dateBetween } from '@regle/rules';\n\nconst before = ref(new Date());\nconst after = ref(new Date(2030, 3, 1));\n\nconst { r$ } = useRegle({ birthday: null as Date | null }, {\n birthday: {\n dateBetween: dateBetween(before, after),\n // or\n dateBetween: dateBetween(before, after, { allowEqual: false }),\n },\n})\n```\n\n## `decimal`\n\nAllows positive and negative decimal numbers.\n\n```ts\nimport { decimal } from '@regle/rules';\n\nconst { r$ } = useRegle({ price: 0 }, {\n price: { decimal },\n})\n```\n\n## `email`\n\nValidates email addresses. Always verify on the server to ensure the address is real and not already in use.\n\n```ts\nimport { email } from '@regle/rules';\n\nconst { r$ } = useRegle({ email: '' }, {\n email: { email },\n})\n```\n\n## `emoji`\n\nValidates emojis.\n\n```ts\nimport { emoji } from '@regle/rules';\n\nconst { r$ } = useRegle({ emoji: '' }, {\n emoji: { emoji },\n})\n```\n\n## `endsWith`\n\n_**Params**_\n- `end: Ref<string> | string | () => string`\n\nChecks if the string ends with the specified substring.\n\n```ts\nimport { endsWith } from '@regle/rules';\n\nconst { r$ } = useRegle({ firstName: '' }, {\n firstName: { endsWith: endsWith('foo') },\n})\n```\n\n## `exactDigits`\n_**Params**_\n - `count: Ref<number> | number | () => number`\n\nRequires the input value to have a strict specified number of digits.\n\n```ts\nimport { exactDigits } from '@regle/rules';\n\nconst exactValue = ref(6);\n\nconst { r$ } = useRegle({ digits: '' }, {\n digits: {\n exactDigits: exactDigits(6),\n // or with ref\n exactDigits: exactDigits(exactValue),\n // or with getter\n exactDigits: exactDigits(() => exactValue.value)\n },\n})\n```\n\n## `exactLength`\n\n_**Params**_\n - `count: Ref<number> | number | () => number`\n\nRequires the input value to have a strict specified length, inclusive. Works with arrays, objects and strings.\n\n```ts\nimport { exactLength } from '@regle/rules';\n\nconst exactValue = ref(6);\n\nconst { r$ } = useRegle({ name: '' }, {\n name: {\n exactLength: exactLength(6),\n exactLength: exactLength(exactValue),\n exactLength: exactLength(() => exactValue.value)\n },\n})\n```\n\n## `exactValue`\n\n_**Params**_\n - `count: Ref<number> | number | () => number`\n\nRequires a field to have a strict numeric value.\n\n```ts\nimport { exactValue } from '@regle/rules';\n\nconst exactCount = ref(6);\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: {\n exactValue: exactValue(6),\n exactValue: exactValue(exactCount),\n exactValue: exactValue(() => exactCount.value)\n },\n})\n```\n\n## `file`\n\nRequires a value to be a native File constructor. Mainly used for typing.\n\n```ts\nimport { file } from '@regle/rules';\n\nconst rules = {\n file: { file },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `fileType`\n\nRequires a value to be a file with a specific type.\n\n```ts\nimport { fileType } from '@regle/rules';\n\nconst { r$ } = useRegle({ file: null as File | null }, {\n file: { fileType: fileType(['image/png', 'image/jpeg']) },\n})\n```\n\n## `hexadecimal`\n\nValidates hexadecimal values.\n\n```ts\nimport { hexadecimal } from '@regle/rules';\n\nconst { r$ } = useRegle({ hexadecimal: '' }, {\n hexadecimal: { hexadecimal },\n})\n```\n\n## `hostname`\n\nValidates hostnames.\n\n```ts\nimport { hostname } from '@regle/rules';\n\nconst { r$ } = useRegle({ siteHost: '' }, {\n siteHost: { hostname },\n})\n```\n\n## `httpUrl`\n\n_**Params**_\n- `options?: {protocol?: RegExp}`\n\nValidates HTTP URLs.\n\n```ts\nimport { httpUrl } from '@regle/rules';\n\nconst { r$ } = useRegle({ bestUrl: '' }, {\n bestUrl: { httpUrl },\n // or with custom protocol validation\n bestUrl: { httpUrl: httpUrl({ protocol: /^https$/ }) },\n})\n```\n\n## `integer`\n\nAllows only integers (positive and negative).\n\n```ts\nimport { integer } from '@regle/rules';\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: { integer },\n})\n```\n\n## `ipv4Address`\n\nValidates IPv4 addresses in dotted decimal notation *127.0.0.1*.\n\n```ts\nimport { ipv4Address } from '@regle/rules';\n\nconst { r$ } = useRegle({ address: '' }, {\n address: { ipv4Address },\n})\n```\n\n## `literal`\n\nValidates literal values.\n\n### Note\n\nThis rule does not need `required` to be set, it will assert the value is set.\n\n```ts\nimport { literal } from '@regle/rules';\n\nconst { r$ } = useRegle({ value: '' }, {\n value: { literal: literal('foo') },\n})\n```\n\n## `lowercase`\n\nValidates lowercase strings.\n\n```ts\nimport { lowercase } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { lowercase },\n})\n```\n\n## `macAddress`\n\n_**Params**_\n - `separator?: string | Ref<string> | () => string`\n\nValidates MAC addresses. Call as a function to specify a custom separator (e.g., ':' or an empty string for 00ff1122334455).\n\n```ts\n\nimport { macAddress } from '@regle/rules';\n\nconst maxCount = ref(6);\n\nconst { r$ } = useRegle({ address: '' }, {\n address: {\n macAddress,\n // or\n macAddress: macAddress('-')\n },\n})\n```\n\n## `maxFileSize`\n\nRequires a value to be a file with a maximum size.\n\n```ts\nimport { maxFileSize } from '@regle/rules';\n\nconst { r$ } = useRegle({ file: null as File | null }, {\n file: { maxFileSize: maxFileSize(10_000_000) }, // 10 MB\n})\n```\n\n## `maxLength`\n\n_**Params**_\n - `max: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\n_**Works with**_\n - `Array | Record | string | number`\n\nRequires the input value to have a maximum specified length, inclusive. Works with arrays, objects and strings.\n\n```ts\nimport { maxLength } from '@regle/rules';\n\nconst maxValue = ref(6);\n\nconst { r$ } = useRegle({ name: '' }, {\n name: {\n maxLength: maxLength(6),\n maxLength: maxLength(maxValue),\n maxLength: maxLength(() => maxValue.value)\n },\n})\n```\n\n## `maxValue`\n\n_**Params**_\n - `min: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\n Requires a field to have a specified maximum numeric value.\n\n```ts\nimport { maxValue } from '@regle/rules';\n\nconst maxCount = ref(6);\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: {\n maxValue: maxValue(6),\n maxValue: maxValue(maxCount, {allowEqual: false}),\n maxValue: maxValue(() => maxCount.value)\n },\n})\n```\n\n## `minFileSize`\n\nRequires a value to be a file with a minimum size.\n\n```ts\nimport { minFileSize } from '@regle/rules';\n\nconst { r$ } = useRegle({ file: null as File | null }, {\n file: { minFileSize: minFileSize(1_000_000) }, // 1 MB\n})\n```\n\n## `minLength`\n\n_**Params**_\n - `min: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\n_**Works with**_\n - `Array | Record | string | number`\n\nRequires the input value to have a minimum specified length, inclusive. Works with arrays, objects and strings.\n\n```ts\nimport { minLength } from '@regle/rules';\n\nconst minValue = ref(6);\n\nconst { r$ } = useRegle({ name: '' }, {\n name: {\n minLength: minLength(6),\n minLength: minLength(minValue),\n minLength: minLength(() => minValue.value)\n },\n})\n```\n\n## `minValue`\n\n_**Params**_\n - `min: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\n_**Works with**_\n - `number`\n\nRequires a field to have a specified minimum numeric value.\n\n```ts\nimport { minValue } from '@regle/rules';\n\nconst minCount = ref(6);\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: {\n minValue: minValue(6),\n minValue: minValue(minCount, {allowEqual: false}),\n minValue: minValue(() => minCount.value)\n },\n})\n```\n\n## `nativeEnum`\n\nValidate against a native Typescript enum value. Similar to Zod's `nativeEnum`\n\n```ts\nimport { nativeEnum } from '@regle/rules';\n\nenum Foo {\n Bar, Baz\n}\n\nconst { r$ } = useRegle({ type: '' }, {\n type: { nativeEnum: nativeEnum(Foo) },\n})\n```\n\n## `number`\n\nRequires a value to be a native number type. Mainly used for typing.\n\n```ts\nimport { number } from '@regle/rules';\n\nconst rules = {\n count: { number },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `numeric`\n\nAllows only numeric values (including numeric strings).\n\n```ts\nimport { numeric } from '@regle/rules';\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: { numeric },\n})\n```\n\n## `oneOf`\n\nAllow only one of the values from a fixed Array of possible entries.\n\n_**Params**_\n - `options: MaybeRefOrGetter<Array<string | number>>`\n\n```ts\nimport { oneOf } from '@regle/rules';\n\nconst { r$ } = useRegle({ aliment: 'Fish' }, {\n aliment: {\n oneOf: oneOf(['Fish', 'Meat', 'Bone'])\n },\n})\n```\n\n## `regex`\n\n_**Params**_\n- `regexps: MaybeRefOrGetter<RegExp | RegExp[]>`\n\nChecks if the value matches one or more regular expressions.\n\n```ts\nimport { regex } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: {\n regex: regex(/^foo/),\n regex: regex([/^bar/, /baz$/]),\n },\n})\n```\n\n## `required`\n\nRequires non-empty data. Checks for empty arrays and strings containing only whitespaces.\n\n```ts\nimport {required} from '@regle/rules';\n\nconst {r$} = useRegle({name: ''}, {\n name: {required},\n})\n```\n\n## `requiredIf`\n\n_**Params**_\n - `condition: Ref<unknown> | unknown | () => unknown` - the property to base the `required` validator on.\n\nRequires non-empty data, only if provided data property, ref, or a function resolves to `true`.\n\n```ts\nimport { requiredIf } from '@regle/rules';\n\nconst form = ref({ name: '', condition: false });\n\nconst conditionRef = ref(false);\n\nconst { r$ } = useRegle(form, {\n name: {\n required: requiredIf(() => form.value.condition),\n required: requiredIf(conditionRef),\n },\n})\n```\n\n## `requiredUnless`\n\n_**Params**_\n - `condition: Ref<unknown> | unknown | () => unknown` - the property to base the `required` validator on.\n\nRequires non-empty data, only if provided data property, ref, or a function resolves to `false`.\n\n```ts\nimport { requiredUnless } from '@regle/rules';\n\nconst form = ref({ name: '', condition: false });\n\nconst conditionRef = ref(false);\n\nconst { r$ } = useRegle(form, {\n name: {\n required: requiredUnless(() => form.value.condition),\n required: requiredUnless(conditionRef)\n },\n})\n```\n\n## `sameAs`\n\n_**Params**_\n * `target: unknown`\n\nChecks if the value matches the specified property or ref.\n\n```ts\nimport { sameAs } from '@regle/rules';\n\nconst form = ref({\n password: '',\n confirmPassword: '',\n});\n\nconst { r$ } = useRegle(form, {\n confirmPassword: {\n sameAs: sameAs(() => form.value.password),\n }\n})\n```\n\n## `startsWith`\n\n_**Params**_\n- `start: Ref<string> | string | () => string`\n\nChecks if the string starts with the specified substring.\n\n```ts\nimport { startsWith } from '@regle/rules';\n\nconst { r$ } = useRegle({ bestLib: '' }, {\n bestLib: {\n startsWith: startsWith('regle')\n },\n})\n```\n\n## `string`\n\nRequires a value to be a native string type. Mainly used for typing\n\n```ts\nimport {type InferInput} from '@regle/core';\nimport { string } from '@regle/rules';\n\nconst rules = {\n firstName: { string },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `type`\n\nDefine the input type of a rule. No runtime validation. \nOverride any input type set by other rules.\n\n```ts\nimport {type InferInput} from '@regle/core';\nimport { type } from '@regle/rules';\n\nconst rules = {\n firstName: { type: type<string>() },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `uppercase`\n\nValidates uppercase strings.\n\n```ts\nimport { uppercase } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { uppercase },\n})\n```\n\n## `url`\n\n_**Params**_\n- `options?: {protocol?: RegExp}`\n\nValidates URLs.\n\n```ts\nimport { url } from '@regle/rules';\n\nconst { r$ } = useRegle({ bestUrl: '' }, {\n bestUrl: { url },\n // or with custom protocol validation\n bestUrl: { url: url({ protocol: /^https?$/ }) },\n})\n```"
|
|
142
|
+
"content": "# Built-in rules\n\nAll built-in rules are available through the `@regle/rules` package.\n\nDon't forget to install it if you haven't:\n\n::: code-group\n\n```sh [pnpm]\npnpm add @regle/rules\n```\n\n```sh [npm]\nnpm install @regle/rules\n```\n\n```sh [yarn]\nyarn add @regle/rules\n```\n\n```sh [bun]\nbun add @regle/rules\n```\n\n:::\n\n:::tip\nEvery built-in rule will check if the value of the field is set before checking if it's valid.\n\nThis allow to have rules even if the field is not required.\n:::\n\n## `alpha`\n\n_**Params**_\n - `allowSymbols?: MaybeRefOrGetter<boolean>`\n\nAllows only alphabetic characters.\n\n```ts\nimport { alpha } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { \n alpha,\n // or\n alpha: alpha({ allowSymbols: true }),\n },\n})\n```\n\n## `alphaNum`\n\n_**Params**_\n - `allowSymbols?: MaybeRefOrGetter<boolean>`\n\nAllows only alphanumeric characters.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { alphaNum } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { \n alphaNum,\n // or\n alphaNum: alphaNum({ allowSymbols: true }),\n },\n});\n```\n\n## `atLeastOne`\n\n_**Params**_\n - `keys?: MaybeRefOrGetter<string[]>` - Optional list of keys to check. If not provided, checks if the object has at least one filled property.\n\n_**Works with**_\n - `Record | object`\n\nChecks if at least one key is filled in the object. Useful for object-level validation with `$self`.\n\n```ts\nimport { atLeastOne } from '@regle/rules';\n\nconst { r$ } = useRegle({ user: { firstName: '', lastName: '' } }, {\n user: {\n $self: {\n // Check if any property is filled\n atLeastOne,\n // or check specific keys\n atLeastOne: atLeastOne(['firstName', 'lastName']),\n },\n },\n})\n```\n\n## `between`\n\n_**Params**_\n - `min: Ref<number> | number | () => number`\n - `max: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\nChecks if a number is in specified bounds. `min` and `max` are both inclusive.\n\n```ts\nimport { between } from '@regle/rules';\n\nconst maxCount = ref(6);\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: {\n between: between(1, 6),\n between: between(1, maxCount, {allowEqual: false}),\n between: between(() => maxCount.value, 10)\n },\n})\n```\n\n## `boolean`\n\nRequires a value to be a native boolean type. Mainly used for typing.\n\n```ts\nimport {type InferInput} from '@regle/core';\nimport { boolean } from '@regle/rules';\n\nconst rules = {\n checkbox: { boolean },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `checked`\n\nRequires a boolean value to be `true`. This is useful for checkbox inputs.\n\n### Note\n\nThis rule does not need `required` to be set, it will assert the value is set.\n\n```ts\nimport { checked } from '@regle/rules';\n\nconst { r$ } = useRegle({ confirm: false }, {\n confirm: { checked },\n})\n```\n\n## `contains`\n\n_**Params**_\n- `contain: Ref<string> | string | () => string`\n\nChecks if the string contains the specified substring.\n\n```ts\nimport { contains } from '@regle/rules';\n\nconst { r$ } = useRegle({ bestLib: '' }, {\n bestLib: {\n contains: contains('regle')\n },\n})\n```\n\n## `date`\n\nRequires a value to be a native Date constructor. Mainly used for typing.\n\n```ts\nimport {type InferInput} from '@regle/core';\nimport { date } from '@regle/rules';\n\nconst rules = {\n birthday: { date },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `dateAfter`\n_**Params**_\n - `after: Ref<string | Date> | string | Date | () => string | Date`\n - `options?: {allowEqual?: boolean}`\n\nChecks if the date is after the given parameter.\n\n```ts\nimport { dateAfter } from '@regle/rules';\n\nconst today = ref(new Date());\n\nconst { r$ } = useRegle({ birthday: null as Date | null }, {\n birthday: {\n dateAfter: dateAfter(today),\n // or\n dateAfter: dateAfter(today, { allowEqual: false }),\n },\n})\n```\n\n## `dateBefore`\n_**Params**_\n - `before: Ref<string | Date> | string | Date | () => string | Date`\n - `options?: {allowEqual?: boolean}`\n\nChecks if the date is before the given parameter.\n\n```ts\nimport { dateBefore } from '@regle/rules';\n\nconst today = ref(new Date());\n\nconst { r$ } = useRegle({ birthday: null as Date | null }, {\n birthday: {\n dateBefore: dateBefore(today),\n // or\n dateBefore: dateBefore(today, { allowEqual: false }),\n },\n})\n```\n\n## `dateBetween`\n\n_**Params**_\n - `before: Ref<string | Date> | string | Date | () => string | Date`\n - `after: Ref<string | Date> | string | Date | () => string | Date`\n - `options?: {allowEqual?: boolean}`\n\nChecks if the date falls between the specified bounds.\n\n```ts\nimport { dateBetween } from '@regle/rules';\n\nconst before = ref(new Date());\nconst after = ref(new Date(2030, 3, 1));\n\nconst { r$ } = useRegle({ birthday: null as Date | null }, {\n birthday: {\n dateBetween: dateBetween(before, after),\n // or\n dateBetween: dateBetween(before, after, { allowEqual: false }),\n },\n})\n```\n\n## `decimal`\n\nAllows positive and negative decimal numbers.\n\n```ts\nimport { decimal } from '@regle/rules';\n\nconst { r$ } = useRegle({ price: 0 }, {\n price: { decimal },\n})\n```\n\n## `email`\n\nValidates email addresses. Always verify on the server to ensure the address is real and not already in use.\n\n```ts\nimport { email } from '@regle/rules';\n\nconst { r$ } = useRegle({ email: '' }, {\n email: { email },\n})\n```\n\n## `emoji`\n\nValidates emojis.\n\n```ts\nimport { emoji } from '@regle/rules';\n\nconst { r$ } = useRegle({ emoji: '' }, {\n emoji: { emoji },\n})\n```\n\n## `endsWith`\n\n_**Params**_\n- `end: Ref<string> | string | () => string`\n\nChecks if the string ends with the specified substring.\n\n```ts\nimport { endsWith } from '@regle/rules';\n\nconst { r$ } = useRegle({ firstName: '' }, {\n firstName: { endsWith: endsWith('foo') },\n})\n```\n\n## `exactDigits`\n_**Params**_\n - `count: Ref<number> | number | () => number`\n\nRequires the input value to have a strict specified number of digits.\n\n```ts\nimport { exactDigits } from '@regle/rules';\n\nconst exactValue = ref(6);\n\nconst { r$ } = useRegle({ digits: '' }, {\n digits: {\n exactDigits: exactDigits(6),\n // or with ref\n exactDigits: exactDigits(exactValue),\n // or with getter\n exactDigits: exactDigits(() => exactValue.value)\n },\n})\n```\n\n## `exactLength`\n\n_**Params**_\n - `count: Ref<number> | number | () => number`\n\nRequires the input value to have a strict specified length, inclusive. Works with arrays, objects and strings.\n\n```ts\nimport { exactLength } from '@regle/rules';\n\nconst exactValue = ref(6);\n\nconst { r$ } = useRegle({ name: '' }, {\n name: {\n exactLength: exactLength(6),\n exactLength: exactLength(exactValue),\n exactLength: exactLength(() => exactValue.value)\n },\n})\n```\n\n## `exactValue`\n\n_**Params**_\n - `count: Ref<number> | number | () => number`\n\nRequires a field to have a strict numeric value.\n\n```ts\nimport { exactValue } from '@regle/rules';\n\nconst exactCount = ref(6);\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: {\n exactValue: exactValue(6),\n exactValue: exactValue(exactCount),\n exactValue: exactValue(() => exactCount.value)\n },\n})\n```\n\n## `file`\n\nRequires a value to be a native File constructor. Mainly used for typing.\n\n```ts\nimport { file } from '@regle/rules';\n\nconst rules = {\n file: { file },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `fileType`\n\nRequires a value to be a file with a specific type.\n\n```ts\nimport { fileType } from '@regle/rules';\n\nconst { r$ } = useRegle({ file: null as File | null }, {\n file: { fileType: fileType(['image/png', 'image/jpeg']) },\n})\n```\n\n## `hexadecimal`\n\nValidates hexadecimal values.\n\n```ts\nimport { hexadecimal } from '@regle/rules';\n\nconst { r$ } = useRegle({ hexadecimal: '' }, {\n hexadecimal: { hexadecimal },\n})\n```\n\n## `hostname`\n\nValidates hostnames.\n\n```ts\nimport { hostname } from '@regle/rules';\n\nconst { r$ } = useRegle({ siteHost: '' }, {\n siteHost: { hostname },\n})\n```\n\n## `httpUrl`\n\n_**Params**_\n- `options?: {protocol?: RegExp}`\n\nValidates HTTP URLs.\n\n```ts\nimport { httpUrl } from '@regle/rules';\n\nconst { r$ } = useRegle({ bestUrl: '' }, {\n bestUrl: { httpUrl },\n // or with custom protocol validation\n bestUrl: { httpUrl: httpUrl({ protocol: /^https$/ }) },\n})\n```\n\n## `integer`\n\nAllows only integers (positive and negative).\n\n```ts\nimport { integer } from '@regle/rules';\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: { integer },\n})\n```\n\n## `ipv4Address`\n\nValidates IPv4 addresses in dotted decimal notation *127.0.0.1*.\n\n```ts\nimport { ipv4Address } from '@regle/rules';\n\nconst { r$ } = useRegle({ address: '' }, {\n address: { ipv4Address },\n})\n```\n\n## `literal`\n\nValidates literal values.\n\n### Note\n\nThis rule does not need `required` to be set, it will assert the value is set.\n\n```ts\nimport { literal } from '@regle/rules';\n\nconst { r$ } = useRegle({ value: '' }, {\n value: { literal: literal('foo') },\n})\n```\n\n## `lowercase`\n\nValidates lowercase strings.\n\n```ts\nimport { lowercase } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { lowercase },\n})\n```\n\n## `macAddress`\n\n_**Params**_\n - `separator?: string | Ref<string> | () => string`\n\nValidates MAC addresses. Call as a function to specify a custom separator (e.g., ':' or an empty string for 00ff1122334455).\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { macAddress } from '@regle/rules';\n\nconst { r$ } = useRegle({ address: '' }, {\n address: {\n macAddress,\n // or\n macAddress: macAddress('-')\n },\n});\n```\n\n## `maxFileSize`\n\nRequires a value to be a file with a maximum size.\n\n```ts\nimport { maxFileSize } from '@regle/rules';\n\nconst { r$ } = useRegle({ file: null as File | null }, {\n file: { maxFileSize: maxFileSize(10_000_000) }, // 10 MB\n})\n```\n\n## `maxLength`\n\n_**Params**_\n - `max: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\n_**Works with**_\n - `Array | Record | string | number`\n\nRequires the input value to have a maximum specified length, inclusive. Works with arrays, objects and strings.\n\n```ts\nimport { maxLength } from '@regle/rules';\n\nconst maxValue = ref(6);\n\nconst { r$ } = useRegle({ name: '' }, {\n name: {\n maxLength: maxLength(6),\n maxLength: maxLength(maxValue),\n maxLength: maxLength(() => maxValue.value)\n },\n})\n```\n\n## `maxValue`\n\n_**Params**_\n - `min: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\n Requires a field to have a specified maximum numeric value.\n\n```ts\nimport { maxValue } from '@regle/rules';\n\nconst maxCount = ref(6);\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: {\n maxValue: maxValue(6),\n maxValue: maxValue(maxCount, {allowEqual: false}),\n maxValue: maxValue(() => maxCount.value)\n },\n})\n```\n\n## `minFileSize`\n\nRequires a value to be a file with a minimum size.\n\n```ts\nimport { minFileSize } from '@regle/rules';\n\nconst { r$ } = useRegle({ file: null as File | null }, {\n file: { minFileSize: minFileSize(1_000_000) }, // 1 MB\n})\n```\n\n## `minLength`\n\n_**Params**_\n - `min: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\n_**Works with**_\n - `Array | Record | string | number`\n\nRequires the input value to have a minimum specified length, inclusive. Works with arrays, objects and strings.\n\n```ts\nimport { minLength } from '@regle/rules';\n\nconst minValue = ref(6);\n\nconst { r$ } = useRegle({ name: '' }, {\n name: {\n minLength: minLength(6),\n minLength: minLength(minValue),\n minLength: minLength(() => minValue.value)\n },\n})\n```\n\n## `minValue`\n\n_**Params**_\n - `min: Ref<number> | number | () => number`\n - `options?: {allowEqual?: boolean}`\n\n_**Works with**_\n - `number`\n\nRequires a field to have a specified minimum numeric value.\n\n```ts\nimport { minValue } from '@regle/rules';\n\nconst minCount = ref(6);\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: {\n minValue: minValue(6),\n minValue: minValue(minCount, {allowEqual: false}),\n minValue: minValue(() => minCount.value)\n },\n})\n```\n\n## `nativeEnum`\n\nValidate against a native Typescript enum value. Similar to Zod's `nativeEnum`\n\n```ts\nimport { nativeEnum } from '@regle/rules';\n\nenum Foo {\n Bar, Baz\n}\n\nconst { r$ } = useRegle({ type: '' }, {\n type: { nativeEnum: nativeEnum(Foo) },\n})\n```\n\n## `number`\n\nRequires a value to be a native number type. Mainly used for typing.\n\n```ts\nimport { number } from '@regle/rules';\n\nconst rules = {\n count: { number },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `numeric`\n\nAllows only numeric values (including numeric strings).\n\n```ts\nimport { numeric } from '@regle/rules';\n\nconst { r$ } = useRegle({ count: 0 }, {\n count: { numeric },\n})\n```\n\n## `oneOf`\n\nAllow only one of the values from a fixed Array of possible entries.\n\n_**Params**_\n - `options: MaybeRefOrGetter<Array<string | number>>`\n\n```ts\nimport { oneOf } from '@regle/rules';\n\nconst { r$ } = useRegle({ aliment: 'Fish' }, {\n aliment: {\n oneOf: oneOf(['Fish', 'Meat', 'Bone'])\n },\n})\n```\n\n## `regex`\n\n_**Params**_\n- `regexps: MaybeRefOrGetter<RegExp | RegExp[]>`\n\nChecks if the value matches one or more regular expressions.\n\n```ts\nimport { regex } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: {\n regex: regex(/^foo/),\n regex: regex([/^bar/, /baz$/]),\n },\n})\n```\n\n## `required`\n\nRequires non-empty data. Checks for empty arrays and strings containing only whitespaces.\n\n```ts\nimport {required} from '@regle/rules';\n\nconst {r$} = useRegle({name: ''}, {\n name: {required},\n})\n```\n\n## `requiredIf`\n\n_**Params**_\n - `condition: Ref<unknown> | unknown | () => unknown` - the property to base the `required` validator on.\n\nRequires non-empty data, only if provided data property, ref, or a function resolves to `true`.\n\n```ts\nimport { requiredIf } from '@regle/rules';\n\nconst form = ref({ name: '', condition: false });\n\nconst conditionRef = ref(false);\n\nconst { r$ } = useRegle(form, {\n name: {\n required: requiredIf(() => form.value.condition),\n required: requiredIf(conditionRef),\n },\n})\n```\n\n## `requiredUnless`\n\n_**Params**_\n - `condition: Ref<unknown> | unknown | () => unknown` - the property to base the `required` validator on.\n\nRequires non-empty data, only if provided data property, ref, or a function resolves to `false`.\n\n```ts\nimport { requiredUnless } from '@regle/rules';\n\nconst form = ref({ name: '', condition: false });\n\nconst conditionRef = ref(false);\n\nconst { r$ } = useRegle(form, {\n name: {\n required: requiredUnless(() => form.value.condition),\n required: requiredUnless(conditionRef)\n },\n})\n```\n\n## `sameAs`\n\n_**Params**_\n * `target: unknown`\n\nChecks if the value matches the specified property or ref.\n\n```ts\nimport { sameAs } from '@regle/rules';\n\nconst form = ref({\n password: '',\n confirmPassword: '',\n});\n\nconst { r$ } = useRegle(form, {\n confirmPassword: {\n sameAs: sameAs(() => form.value.password),\n }\n})\n```\n\n## `startsWith`\n\n_**Params**_\n- `start: Ref<string> | string | () => string`\n\nChecks if the string starts with the specified substring.\n\n```ts\nimport { startsWith } from '@regle/rules';\n\nconst { r$ } = useRegle({ bestLib: '' }, {\n bestLib: {\n startsWith: startsWith('regle')\n },\n})\n```\n\n## `string`\n\nRequires a value to be a native string type. Mainly used for typing\n\n```ts\nimport {type InferInput} from '@regle/core';\nimport { string } from '@regle/rules';\n\nconst rules = {\n firstName: { string },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `type`\n\nDefine the input type of a rule. No runtime validation. \nOverride any input type set by other rules.\n\n```ts\nimport {type InferInput} from '@regle/core';\nimport { type } from '@regle/rules';\n\nconst rules = {\n firstName: { type: type<string>() },\n}\n\nconst state = ref<InferInput<typeof rules>>({});\n```\n\n## `uppercase`\n\nValidates uppercase strings.\n\n```ts\nimport { uppercase } from '@regle/rules';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { uppercase },\n})\n```\n\n## `url`\n\n_**Params**_\n- `options?: {protocol?: RegExp}`\n\nValidates URLs.\n\n```ts\nimport { url } from '@regle/rules';\n\nconst { r$ } = useRegle({ bestUrl: '' }, {\n bestUrl: { url },\n // or with custom protocol validation\n bestUrl: { url: url({ protocol: /^https?$/ }) },\n})\n```"
|
|
143
143
|
},
|
|
144
144
|
{
|
|
145
145
|
"id": "core-concepts-rules-index",
|
|
@@ -167,7 +167,7 @@ var docs_data_default = {
|
|
|
167
167
|
"title": "Rules operators",
|
|
168
168
|
"category": "rules",
|
|
169
169
|
"path": "core-concepts/rules/rules-operators.md",
|
|
170
|
-
"content": "# Rules operators\n\nRegle provides tools to combine and operate on different rules. It includes the following built-in operators, available in `@regle/rules`:\n\n- `and`\n- `or`\n- `xor`\n- `not`\n- `applyIf`\n- `assignIf`\n- `pipe`\n\nThese operators work with any rules you provide, but combining rules with incompatible input types may lead to errors.\n\n:::tip\nAll operators are compatible with wrappers\n:::\n\n## `and`\n\nThe `and` operator combines multiple rules and validates successfully only if all provided rules are valid.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { and, startsWith, endsWith, withMessage } from '@regle/rules';\n\nconst { r$ } = useRegle(\n { regex: '' },\n {\n regex: {\n myError: withMessage(\n and(startsWith('^'), endsWith('$')),\n ({ $params: [start, end] }) =>\n `Regex should start with \"${start}\" and end with \"${end}\"`\n ),\n },\n }\n);\n```\n\nResult: \n\n## `or`\n\nThe `or` operator validates successfully if at least one of the provided rules is valid.\n\n```ts twoslash\nimport { useRegle } from '@regle/core';\nimport { or, startsWith, endsWith, withMessage } from '@regle/rules';\n\nconst { r$ } = useRegle(\n { regex: '' },\n {\n regex: {\n myError: withMessage(\n or(startsWith('^'), endsWith('$')),\n ({ $params: [start, end] }) =>\n `Field should start with \"${start}\" or end with \"${end}\"`\n ),\n },\n }\n);\n```\n\nResult: \n\n## `xor`\n\nThe `xor` operator (exclusive or) validates successfully if **exactly one** of the provided rules is valid. It fails when none or more than one rule passes.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { xor, contains, withMessage } from '@regle/rules';\n\nconst { r$ } = useRegle(\n { code: '' },\n {\n code: {\n myError: withMessage(\n xor(contains('A'), contains('B')),\n ({ $params: [charA, charB] }) =>\n `Field should contain either \"${charA}\" or \"${charB}\", but not both`\n ),\n },\n }\n);\n```\n\nResult: \n\n## `not`\n\nThe `not` operator passes when the provided rule fails and fails when the rule passes. It can be combined with other rules.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { not, required, sameAs, withMessage } from '@regle/rules';\nimport { ref } from 'vue';\n\nconst form = ref({ oldPassword: '', newPassword: '' });\nconst { r$ } = useRegle(form, {\n oldPassword: {\n required,\n },\n newPassword: {\n notEqual: withMessage(\n not(sameAs(() => form.value.oldPassword)),\n 'Your
|
|
170
|
+
"content": "# Rules operators\n\nRegle provides tools to combine and operate on different rules. It includes the following built-in operators, available in `@regle/rules`:\n\n- `and`\n- `or`\n- `xor`\n- `not`\n- `applyIf`\n- `assignIf`\n- `pipe`\n\nThese operators work with any rules you provide, but combining rules with incompatible input types may lead to errors.\n\n:::tip\nAll operators are compatible with wrappers\n:::\n\n## `and`\n\nThe `and` operator combines multiple rules and validates successfully only if all provided rules are valid.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { and, startsWith, endsWith, withMessage } from '@regle/rules';\n\nconst { r$ } = useRegle(\n { regex: '' },\n {\n regex: {\n myError: withMessage(\n and(startsWith('^'), endsWith('$')),\n ({ $params: [start, end] }) =>\n `Regex should start with \"${start}\" and end with \"${end}\"`\n ),\n },\n }\n);\n```\n\nResult: \n\n## `or`\n\nThe `or` operator validates successfully if at least one of the provided rules is valid.\n\n```ts twoslash\nimport { useRegle } from '@regle/core';\nimport { or, startsWith, endsWith, withMessage } from '@regle/rules';\n\nconst { r$ } = useRegle(\n { regex: '' },\n {\n regex: {\n myError: withMessage(\n or(startsWith('^'), endsWith('$')),\n ({ $params: [start, end] }) =>\n `Field should start with \"${start}\" or end with \"${end}\"`\n ),\n },\n }\n);\n```\n\nResult: \n\n## `xor`\n\nThe `xor` operator (exclusive or) validates successfully if **exactly one** of the provided rules is valid. It fails when none or more than one rule passes.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { xor, contains, withMessage } from '@regle/rules';\n\nconst { r$ } = useRegle(\n { code: '' },\n {\n code: {\n myError: withMessage(\n xor(contains('A'), contains('B')),\n ({ $params: [charA, charB] }) =>\n `Field should contain either \"${charA}\" or \"${charB}\", but not both`\n ),\n },\n }\n);\n```\n\nResult: \n\n## `not`\n\nThe `not` operator passes when the provided rule fails and fails when the rule passes. It can be combined with other rules.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { not, required, sameAs, withMessage } from '@regle/rules';\nimport { ref } from 'vue';\n\nconst form = ref({ oldPassword: '', newPassword: '' });\nconst { r$ } = useRegle(form, {\n oldPassword: {\n required,\n },\n newPassword: {\n notEqual: withMessage(\n not(sameAs(() => form.value.oldPassword)),\n 'Your passwords must be different'\n ),\n },\n});\n```\n\nResult: \n\n## `applyIf`\n\nThe `applyIf` operator is similar to `requiredIf`, but it can be used with any rule. It simplifies conditional rule declarations.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { minLength, applyIf } from '@regle/rules';\nimport { ref } from 'vue';\n\nconst condition = ref(false);\n\nconst { r$ } = useRegle({name: ''}, {\n name: {\n minLength: applyIf(condition, minLength(6))\n },\n});\n```\n\nResult:\n\n## `assignIf`\n\nThe `assignIf` is a shorthand for conditional destructuring assignment.\nIt allows to apply multiple rules to a field conditionally.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { required, email, minLength, assignIf } from '@regle/rules';\nimport { ref } from 'vue';\n\nconst condition = ref(false);\n\nconst { r$ } = useRegle(ref({ name: '', email: '' }), {\n name: assignIf(condition, { required, minLength: minLength(4) }),\n email: { email },\n});\n```\n\nResult: \n\n## `pipe`\n\nThe `pipe` operator chains multiple rules together sequentially. Each rule only runs if all previous rules have passed. This is useful when you want to validate in a specific order and avoid running expensive validations (like async checks) until simpler ones pass.\n\n```ts\nimport { useRegle } from '@regle/core';\nimport { pipe, required, minLength, email } from '@regle/rules';\n\nconst { r$ } = useRegle(\n { email: '' },\n {\n email: pipe(required, minLength(5), email),\n }\n);\n// minLength only runs if required passes\n// email only runs if both required and minLength pass\n```\n\nResult: \n\n:::tip When to use `pipe` vs `and`\n- Use **`and`** when all rules should run simultaneously and you want all errors at once\n- Use **`pipe`** when rules should run sequentially and later rules depend on earlier ones passing (e.g., don't check email format until the field has enough characters)\n:::\n\nThe `pipe` operator also works with async rules. Subsequent rules will wait for async validators to complete before running:\n\n```ts\nimport { pipe, required, withAsync } from '@regle/rules';\n\nconst checkEmailAvailable = withAsync(async (value) => {\n const response = await fetch(`/api/check-email?email=${value}`);\n return response.ok;\n});\n\nconst { r$ } = useRegle(\n { email: '' },\n {\n email: pipe(required, email, checkEmailAvailable),\n }\n);\n// checkEmailAvailable only runs after required and email pass\n```\n\n### Debouncing async validators\n\nWhen using `pipe` with async validators, you can configure a debounce delay to prevent too many API calls while the user is typing. Use the array syntax with an options object as the second argument:\n\n```ts\nimport { pipe, required, email, withAsync } from '@regle/rules';\n\nconst checkEmailAvailable = withAsync(async (value) => {\n const response = await fetch(`/api/check-email?email=${value}`);\n return response.ok;\n});\n\nconst { r$ } = useRegle(\n { email: '' },\n {\n email: pipe(\n [required, email, checkEmailAvailable],\n { debounce: 300 } // Wait 300ms after last input before running async validators\n ),\n }\n);\n```\n\nResult:\n\nThe debounce option only affects async validators in the pipe. Synchronous validators (`required`, `email` in the example above) run immediately, while the async validator (`checkEmailAvailable`) will be debounced.\n\n:::info Default debounce\nWhen using `pipe` with async validators, the default debounce delay is **200ms**. You can override this by passing a custom `debounce` value in the options.\n:::"
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
"id": "core-concepts-rules-rules-properties",
|
|
@@ -251,21 +251,21 @@ var docs_data_default = {
|
|
|
251
251
|
"title": "Regle MCP server",
|
|
252
252
|
"category": "integrations",
|
|
253
253
|
"path": "integrations/mcp-server.md",
|
|
254
|
-
"content": "# MCP Server\n\nRegle offers an MCP server that can be used to get documentation and autocomplete in your favorite AI assistant editor.\n\nThe MCP server provides the following features:\n\n- Create form validation rules\n- Search documentation\n- Get precise information on any rule\n- Create custom rules\n- API information on every Regle helper\n\n## Cursor\n\n<a href=\"https://cursor.com/en-US/install-mcp?name=regle&config=eyJjb21tYW5kIjoibnB4IEByZWdsZS9tY3Atc2VydmVyIn0%3D\">\n <div class=\"light-only\">\n <img src=\"https://cursor.com/deeplink/mcp-install-dark.svg\" alt=\"Install MCP Server\" />\n </div>\n <div class=\"dark-only\">\n <img src=\"https://cursor.com/deeplink/mcp-install-light.svg\" alt=\"Install MCP Server\" />\n </div>\n</a>\n\nOr add to your `.cursor/mcp.json`\n```json\n{\n \"mcpServers\": {\n \"regle\": {\n \"command\": \"npx\",\n \"args\": [\"@regle/mcp-server\"]\n }\n }\n}\n```\n\n## Claude Code\n\nFor Claude Code, run the following command:\n\n```bash\nclaude mcp add regle --scope project '{\"command\":\"npx\",\"args\":[\"-y\",\"@regle/mcp-server\"]}'\n```"
|
|
254
|
+
"content": "# MCP Server\n\n[MCP (Model Context Protocol)](https://modelcontextprotocol.io/) is an open standard that enables AI assistants to interact with external tools and data sources. \n\nRegle offers an MCP server that can be used to get documentation and autocomplete in your favorite AI assistant editor. This allows your AI assistant to understand Regle's API and help you write validation rules more effectively.\n\nThe MCP server provides the following features:\n\n- Create form validation rules\n- Search documentation\n- Get precise information on any rule\n- Create custom rules\n- API information on every Regle helper\n\n## Cursor\n\n<a href=\"https://cursor.com/en-US/install-mcp?name=regle&config=eyJjb21tYW5kIjoibnB4IEByZWdsZS9tY3Atc2VydmVyIn0%3D\">\n <div class=\"light-only\">\n <img src=\"https://cursor.com/deeplink/mcp-install-dark.svg\" alt=\"Install MCP Server\" />\n </div>\n <div class=\"dark-only\">\n <img src=\"https://cursor.com/deeplink/mcp-install-light.svg\" alt=\"Install MCP Server\" />\n </div>\n</a>\n\nOr add to your `.cursor/mcp.json`\n```json\n{\n \"mcpServers\": {\n \"regle\": {\n \"command\": \"npx\",\n \"args\": [\"@regle/mcp-server\"]\n }\n }\n}\n```\n\n## Claude Code\n\nFor Claude Code, run the following command:\n\n```bash\nclaude mcp add regle --scope project '{\"command\":\"npx\",\"args\":[\"-y\",\"@regle/mcp-server\"]}'\n```"
|
|
255
255
|
},
|
|
256
256
|
{
|
|
257
257
|
"id": "integrations-nuxt",
|
|
258
258
|
"title": "Nuxt",
|
|
259
259
|
"category": "integrations",
|
|
260
260
|
"path": "integrations/nuxt.md",
|
|
261
|
-
"content": "# Nuxt <span data-title=\"nuxt\"></span>\n\nAdding the Nuxt module enables auto-imports for selected exports.\n\nRun the following command in your Nuxt application:\n\n```bash\nnpx nuxi module add regle\n```\n\nOr do it manually\n\n:::code-group\n<!-- ```bash [nuxt]\nnpx nuxi module add regle\n``` -->\n```sh [pnpm]\npnpm add @regle/core @regle/rules @regle/nuxt\n```\n\n```sh [npm]\nnpm install @regle/core @regle/rules @regle/nuxt\n```\n\n```sh [yarn]\nyarn add @regle/core @regle/rules @regle/nuxt\n```\n\n```sh [bun]\nbun add @regle/core @regle/rules @regle/nuxt\n```\n:::\n\nYou can then declare the module inside your `nuxt.config.ts`.\n\n```ts [nuxt.config.ts]\nexport default defineNuxtConfig({\n modules: ['@regle/nuxt']\n})\n```\n\n## `setupFile`\n\nThe Regle Nuxt module allow you to define a global configuration plugin to provide all your forms with the same translations, options and custom rules.\n\n```ts [nuxt.config.ts]\nexport default defineNuxtConfig({\n modules: ['@regle/nuxt'],\n regle: {\n setupFile: '~/regle-config.ts'\n }\n})\n```\n\n```ts [app/regle-config.ts]\nimport { defineRegleNuxtPlugin } from '@regle/nuxt/setup';\nimport { defineRegleConfig } from '@regle/core';\nimport { required, withMessage } from '@regle/rules';\n\nexport default defineRegleNuxtPlugin(() => {\n return defineRegleConfig({\n rules: () => {\n const {t} = useI18n();\n\n return {\n required: withMessage(required, t('general.required')),\n customRule: myCustomRule,\n }\n },\n });\n});\n\n```\n\nThis will inject the
|
|
261
|
+
"content": "# Nuxt <span data-title=\"nuxt\"></span>\n\nAdding the Nuxt module enables auto-imports for selected exports.\n\nRun the following command in your Nuxt application:\n\n```bash\nnpx nuxi module add regle\n```\n\nOr do it manually\n\n:::code-group\n<!-- ```bash [nuxt]\nnpx nuxi module add regle\n``` -->\n```sh [pnpm]\npnpm add @regle/core @regle/rules @regle/nuxt\n```\n\n```sh [npm]\nnpm install @regle/core @regle/rules @regle/nuxt\n```\n\n```sh [yarn]\nyarn add @regle/core @regle/rules @regle/nuxt\n```\n\n```sh [bun]\nbun add @regle/core @regle/rules @regle/nuxt\n```\n:::\n\nYou can then declare the module inside your `nuxt.config.ts`.\n\n```ts [nuxt.config.ts]\nexport default defineNuxtConfig({\n modules: ['@regle/nuxt']\n})\n```\n\n## `setupFile`\n\nThe Regle Nuxt module allow you to define a global configuration plugin to provide all your forms with the same translations, options and custom rules.\n\n```ts [nuxt.config.ts]\nexport default defineNuxtConfig({\n modules: ['@regle/nuxt'],\n regle: {\n setupFile: '~/regle-config.ts'\n }\n})\n```\n\n```ts [app/regle-config.ts]\nimport { defineRegleNuxtPlugin } from '@regle/nuxt/setup';\nimport { defineRegleConfig } from '@regle/core';\nimport { required, withMessage } from '@regle/rules';\n\nexport default defineRegleNuxtPlugin(() => {\n return defineRegleConfig({\n rules: () => {\n const {t} = useI18n();\n\n return {\n required: withMessage(required, t('general.required')),\n customRule: myCustomRule,\n }\n },\n });\n});\n\n```\n\nThis will inject the following composables to your auto-imports and `#imports`, loaded with your custom error messages and rules: \n\n- `useRegle` \n- `inferRules` \n- `useCollectScope` \n- `useScopedRegle` \n- `type RegleFieldStatus`\n\n```vue [app.vue] {2}\n\n```\n\n## No options\n\nIf no setup file is provided, the following auto-imports will be added to your app.\n\n- `@regle/core`\n - useRegle \n - inferRules\n - createRule\n - defineRegleConfig\n - extendRegleConfig\n - createVariant\n - narrowVariant\n - useScopedRegle\n - useCollectScope\n \n- `@regle/rules` Note: Built-in rules are not auto-injected to minimize the risk of name conflicts.\n - withAsync\n - withMessage\n - withParams\n - withTooltip\n \n- `@regle/schemas` (if present)\n - useRegleSchema\n - inferSchema\n - withDeps\n - defineRegleSchemaConfig"
|
|
262
262
|
},
|
|
263
263
|
{
|
|
264
264
|
"id": "integrations-schemas-libraries",
|
|
265
265
|
"title": "Schemas libraries",
|
|
266
266
|
"category": "integrations",
|
|
267
267
|
"path": "integrations/schemas-libraries.md",
|
|
268
|
-
"content": "# Schemas libraries (Zod, Valibot, ...)\n\nRegle supports the [Standard Schema Spec](https://standardschema.dev/).\n\nThis means any Standard Schema compliant RPC library can be used with Regle.\n\nOfficial list of supported libraries:\n\n- Zod [docs](https://zod.dev/) <span data-title=\"zod\"></span> `3.24+`. \n- Valibot [docs](https://valibot.dev/) <span data-title=\"valibot\"></span> `1+`.\n- ArkType [docs](https://arktype.io/) <span data-title=\"arktype\"></span> `2+`\n- Any library following the [Standard Schema Spec](https://standardschema.dev/) \n\n::: code-group\n```sh [pnpm]\npnpm add @regle/schemas\n```\n\n```sh [npm]\nnpm install @regle/schemas\n```\n\n```sh [yarn]\nyarn add @regle/schemas\n```\n\n```sh [bun]\nbun add @regle/schemas\n```\n:::\n\n## Usage\n\nInstead of using the core `useRegle`, use `useRegleSchema` export from `@regle/schemas`.\n\n:::code-group\n```ts [Zod]\nimport { useRegleSchema } from '@regle/schemas';\nimport { z } from 'zod';\n\nconst { r$ } = useRegleSchema({ name: '' }, z.object({\n name: z.string().min(1)\n}))\n```\n\n```ts [Valibot]\nimport { useRegleSchema } from '@regle/schemas';\nimport * as v from 'valibot';\n\nconst { r$ } = useRegleSchema({ name: '' }, v.object({\n name: v.pipe(v.string(), v.minLength(3))\n}))\n```\n\n```ts [ArkType]\nimport { useRegleSchema } from '@regle/schemas';\nimport { type } from 'arktype';\n\nconst { r$ } = useRegleSchema({ name: '' }, type({\n name: \"string > 1\"\n}))\n```\n\n:::\n\n:::warning\nLimitations from the core behaviour\n\nUsing schema libraries uses a different mechanism than the core \"rules\" one. Regle will parse the entire tree instead of doing it per-field. Than means that properties or methods are not available in nested values:\n\n- `$validate` (only at root)\n- `$pending` (only at root)\n\nOne other limitation is you won't have access to any children `$rules`, so checking if a field is required with `xx.$rules.required.active` is not possible with schemas.\n:::\n\n## Computed schema\n\nYou can also have a computed schema that can be based on other state values.\n\n:::warning\nWhen doing refinements or transform, Vue can't track what the schema depends on because you're in a function callback. \n\nSame way as `withParams` from `@regle/rules`, you can use the `withDeps` helper to force dependencies on any schema\n:::\n\n:::code-group\n\n```ts [Zod]\nimport { useRegleSchema, inferSchema, withDeps } from '@regle/schemas';\nimport { z } from 'zod';\nimport { ref, computed } from 'vue';\n\ntype Form = {\n firstName?: string;\n lastName?: string\n}\n\nconst form = ref<Form>({ firstName: '', lastName: '' })\n\nconst schema = computed(() =>\n inferSchema(form, z.object({\n firstName: z.string(),\n /** \n * Important to keep track of the depency change\n * Without it, the validator wouldn't run if `firstName` changed\n */\n lastName: withDeps(\n z.string().refine((v) => v !== form.value.firstName, {\n message: \"Last name can't be equal to first name\",\n }),\n [() => form.value.firstName]\n ),\n }))\n);\n\nconst { r$ } = useRegleSchema(form, schema);\n\n```\n```ts [Valibot]\nimport { useRegleSchema, inferSchema, withDeps} from '@regle/schemas';\nimport * as v from 'valibot';\nimport { ref, computed } from 'vue';\n\ntype Form = {\n firstName?: string;\n lastName?: string\n}\n\nconst form = ref<Form>({ firstName: '', lastName: '' })\n\nconst schema = computed(() => \n inferSchema(form, v.object({\n firstName: v.string(),\n /** \n * Important to keep track of the depency change\n * Without it, the validator wouldn't run if `firstName` changed\n */\n lastName: withDeps(\n v.pipe(\n v.string(),\n v.check((v) => v !== form.value.firstName, \"Last name can't be equal to first name\")\n ),\n [() => form.value.firstName]\n ),\n }))\n)\n\nconst { r$ } = useRegleSchema(form, schema);\n\n```\n\n:::\n\n## `syncState`\n\nBy default, Regle doesn't allow any transforms on the state. \n\nModifiers like `default`, `catch` or `transform` will not impact the validation.\n\nIf you want to allow the schema to update your form state you can use the `syncState` option. \nThe state will only be
|
|
268
|
+
"content": "# Schemas libraries (Zod, Valibot, ...)\n\nRegle supports the [Standard Schema Spec](https://standardschema.dev/).\n\nThis means any Standard Schema compliant RPC library can be used with Regle.\n\nOfficial list of supported libraries:\n\n- Zod [docs](https://zod.dev/) <span data-title=\"zod\"></span> `3.24+`. \n- Valibot [docs](https://valibot.dev/) <span data-title=\"valibot\"></span> `1+`.\n- ArkType [docs](https://arktype.io/) <span data-title=\"arktype\"></span> `2+`\n- Any library following the [Standard Schema Spec](https://standardschema.dev/) \n\n::: code-group\n```sh [pnpm]\npnpm add @regle/schemas\n```\n\n```sh [npm]\nnpm install @regle/schemas\n```\n\n```sh [yarn]\nyarn add @regle/schemas\n```\n\n```sh [bun]\nbun add @regle/schemas\n```\n:::\n\n## Usage\n\nInstead of using the core `useRegle`, use `useRegleSchema` export from `@regle/schemas`.\n\n:::code-group\n```ts [Zod]\nimport { useRegleSchema } from '@regle/schemas';\nimport { z } from 'zod';\n\nconst { r$ } = useRegleSchema({ name: '' }, z.object({\n name: z.string().min(1)\n}))\n```\n\n```ts [Valibot]\nimport { useRegleSchema } from '@regle/schemas';\nimport * as v from 'valibot';\n\nconst { r$ } = useRegleSchema({ name: '' }, v.object({\n name: v.pipe(v.string(), v.minLength(3))\n}))\n```\n\n```ts [ArkType]\nimport { useRegleSchema } from '@regle/schemas';\nimport { type } from 'arktype';\n\nconst { r$ } = useRegleSchema({ name: '' }, type({\n name: \"string > 1\"\n}))\n```\n\n:::\n\n:::warning\nLimitations from the core behaviour\n\nUsing schema libraries uses a different mechanism than the core \"rules\" one. Regle will parse the entire tree instead of doing it per-field. Than means that properties or methods are not available in nested values:\n\n- `$validate` (only at root)\n- `$pending` (only at root)\n\nOne other limitation is you won't have access to any children `$rules`, so checking if a field is required with `xx.$rules.required.active` is not possible with schemas.\n:::\n\n## Computed schema\n\nYou can also have a computed schema that can be based on other state values.\n\n:::warning\nWhen doing refinements or transform, Vue can't track what the schema depends on because you're in a function callback. \n\nSame way as `withParams` from `@regle/rules`, you can use the `withDeps` helper to force dependencies on any schema\n:::\n\n:::code-group\n\n```ts [Zod]\nimport { useRegleSchema, inferSchema, withDeps } from '@regle/schemas';\nimport { z } from 'zod';\nimport { ref, computed } from 'vue';\n\ntype Form = {\n firstName?: string;\n lastName?: string\n}\n\nconst form = ref<Form>({ firstName: '', lastName: '' })\n\nconst schema = computed(() =>\n inferSchema(form, z.object({\n firstName: z.string(),\n /** \n * Important to keep track of the depency change\n * Without it, the validator wouldn't run if `firstName` changed\n */\n lastName: withDeps(\n z.string().refine((v) => v !== form.value.firstName, {\n message: \"Last name can't be equal to first name\",\n }),\n [() => form.value.firstName]\n ),\n }))\n);\n\nconst { r$ } = useRegleSchema(form, schema);\n\n```\n```ts [Valibot]\nimport { useRegleSchema, inferSchema, withDeps} from '@regle/schemas';\nimport * as v from 'valibot';\nimport { ref, computed } from 'vue';\n\ntype Form = {\n firstName?: string;\n lastName?: string\n}\n\nconst form = ref<Form>({ firstName: '', lastName: '' })\n\nconst schema = computed(() => \n inferSchema(form, v.object({\n firstName: v.string(),\n /** \n * Important to keep track of the depency change\n * Without it, the validator wouldn't run if `firstName` changed\n */\n lastName: withDeps(\n v.pipe(\n v.string(),\n v.check((v) => v !== form.value.firstName, \"Last name can't be equal to first name\")\n ),\n [() => form.value.firstName]\n ),\n }))\n)\n\nconst { r$ } = useRegleSchema(form, schema);\n\n```\n\n:::\n\n## `syncState`\n\nBy default, Regle doesn't allow any transforms on the state. \n\nModifiers like `default`, `catch` or `transform` will not impact the validation.\n\nIf you want to allow the schema to update your form state you can use the `syncState` option. \nThe state will only be patched is the parse is successful.\n\n```ts\ntype RegleSchemaBehaviourOptions = {\n syncState?: {\n /**\n * Applies every transform on every update to the state\n */\n onUpdate?: boolean;\n /**\n * Applies every transform only when calling `$validate`\n */\n onValidate?: boolean;\n };\n};\n```\n\nUsage:\n\n```vue\n\n```\n\n## Type safe output\n\nSimilar to the main `useRegle` composable, `r$.$validate` also returns a type-safe output using Zod type schema parser.\n\n:::code-group\n```ts [Zod]\nimport { useRegleSchema, inferSchema } from '@regle/schemas';\nimport { z } from 'zod';\nimport { ref, computed } from 'vue';\n\ntype Form = {\n firstName?: string;\n lastName?: string\n}\n\nconst form = ref<Form>({ firstName: '', lastName: '' })\n\nconst schema = computed(() => inferSchema(form, z.object({\n firstName: z.string().optional(),\n lastName: z.string().min(1).refine(v => v !== form.value.firstName, {\n message: \"Last name can't be equal to first name\"\n }),\n})))\n\nconst { r$ } = useRegleSchema(form, schema);\n\nasync function submit() {\n const { valid, data } = await r$.$validate();\n if (valid) {\n console.log(data);\n }\n}\n\n```\n\n```ts [Valibot]\nimport { useRegleSchema, inferSchema } from '@regle/schemas';\nimport * as v from 'valibot';\nimport { ref, computed } from 'vue';\n\ntype Form = {\n firstName?: string;\n lastName?: string\n}\n\nconst form = ref<Form>({ firstName: '', lastName: '' })\n\nconst schema = computed(() => {\n return inferSchema(form, v.object({\n firstName: v.optional(v.string()),\n lastName: v.pipe(\n v.string(),\n v.minLength(3),\n v.check((v) => v !== form.value.firstName, \"Last name can't be equal to first name\")\n )\n }))\n})\n\nconst { r$ } = useRegleSchema(form, schema);\n\nasync function submit() {\n const { valid, data } = await r$.$validate();\n if (valid) {\n console.log(data);\n }\n}\n\n```\n\n```ts [ArkType]\nimport { useRegleSchema, inferSchema } from '@regle/schemas';\nimport { type } from 'arktype';\nimport { ref, computed } from 'vue';\n\ntype Form = {\n firstName?: string;\n lastName?: string\n}\n\nconst form = ref<Form>({ firstName: '', lastName: '' })\n\nconst schema = computed(() => {\n return inferSchema(form, type({\n 'firstName?': 'string',\n lastName: 'string > 3',\n }).narrow((data, ctx) => {\n if (data.firstName !== data.lastName) {\n return true;\n }\n return ctx.reject({\n expected: 'different than firstName',\n path: ['lastName'],\n });\n }))\n})\n\nconst { r$ } = useRegleSchema(form, schema);\n\nasync function submit() {\n const { valid, data } = await r$.$validate();\n if (valid) {\n console.log(data);\n }\n}\n```\n:::"
|
|
269
269
|
},
|
|
270
270
|
{
|
|
271
271
|
"id": "introduction-comparisons",
|
|
@@ -279,14 +279,14 @@ var docs_data_default = {
|
|
|
279
279
|
"title": "Devtools",
|
|
280
280
|
"category": "introduction",
|
|
281
281
|
"path": "introduction/devtools.md",
|
|
282
|
-
"content": "# Regle Devtools\n\nRegle offers a devtools extension for [Vue Devtools](https://devtools.vuejs.org/) to help you debug your validation tree.\n\n\n\n## Installation\n\nTo enable devtools, you need to install the Regle plugin in your app.\n\n:::tip\nIf you use the `@regle/nuxt` module, the devtools will be automatically enabled.\n:::\n\n```ts [main.ts]\nimport { createApp } from 'vue';\nimport App from './App.vue';\nimport { RegleVuePlugin } from '@regle/core';\n\nconst app = createApp(App);\n\napp.use(RegleVuePlugin); // <--\n\napp.mount('#app');\n```\n\n## Usage\n\nRegle devtools can inspect every variation of `useRegle`:\n\n- `useRegle`\n- `useRules`\n- `useRegleSchema`\n- `useScopedRegle`\n- `useScopedRegleSchema`\n\nYou can inspect every nested properties and rules of the `r$` instance.\n\n:::warning\nRules details inspection is not available for `useRegleSchema`\n:::\n\n### Actions\n\nYou can perform actions on the `r$` instance by clicking on the actions buttons in the devtools.\n\n\n\n- Validate: Validate the `r$` instance (with `$validate` method)\n- Reset validation state: Reset the validation state of the `r$` instance (with `$reset` method)\n- Restore to original state: Restore the `r$` instance to the original state (with `$reset` method)\n\n## Providing custom `r$` ids to devtools\n\nBy default, the devtools will use a generic name to display the `r$` instance. \n\nYou can provide a custom name to the `useRegle` composable to display a more descriptive name in the devtools.\n\n```ts [App.vue]\nimport { useRegle } from '@regle/core';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { required }\n}, {\n id: 'my-form'\n});\n```\n\n## Devtools demo\n\nYou can go in any of the [
|
|
282
|
+
"content": "# Regle Devtools\n\nRegle offers a devtools extension for [Vue Devtools](https://devtools.vuejs.org/) to help you debug your validation tree.\n\n\n\n## Installation\n\nTo enable devtools, you need to install the Regle plugin in your app.\n\n:::tip\nIf you use the `@regle/nuxt` module, the devtools will be automatically enabled.\n:::\n\n```ts [main.ts]\nimport { createApp } from 'vue';\nimport App from './App.vue';\nimport { RegleVuePlugin } from '@regle/core';\n\nconst app = createApp(App);\n\napp.use(RegleVuePlugin); // <--\n\napp.mount('#app');\n```\n\n## Usage\n\nRegle devtools can inspect every variation of `useRegle`:\n\n- `useRegle`\n- `useRules`\n- `useRegleSchema`\n- `useScopedRegle`\n- `useScopedRegleSchema`\n\nYou can inspect every nested properties and rules of the `r$` instance.\n\n:::warning\nRules details inspection is not available for `useRegleSchema`\n:::\n\n### Actions\n\nYou can perform actions on the `r$` instance by clicking on the actions buttons in the devtools.\n\n\n\n- Validate: Validate the `r$` instance (with `$validate` method)\n- Reset validation state: Reset the validation state of the `r$` instance (with `$reset` method)\n- Restore to original state: Restore the `r$` instance to the original state (with `$reset` method)\n\n## Providing custom `r$` ids to devtools\n\nBy default, the devtools will use a generic name to display the `r$` instance. \n\nYou can provide a custom name to the `useRegle` composable to display a more descriptive name in the devtools.\n\n```ts [App.vue]\nimport { useRegle } from '@regle/core';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { required }\n}, {\n id: 'my-form'\n});\n```\n\n## Devtools demo\n\nYou can go in any of the [StackBlitz examples](/examples/index) and open the devtools by clicking on the <span data-title=\"vue\"></span> \"Open Devtools\" button in the bottom middle of the page.\n\n### Vite Devtools Integration\n\nRegle devtools also integrate cleanly with [Vite](https://vitejs.dev/) when you're running your app in development mode.\n\nYou should see the Regle panel show up automatically in the Vite devtools if you've installed the plugin correctly.\n\n<img src=\"/screenshots/vite-devtools.png\" alt=\"Vite Devtools with Regle panel\" width=\"100\"/>\n\nYou will see the Regle icon showing in the devtools. Just click on it!\n\n<img src=\"/screenshots/vite-devtools-regle.png\" alt=\"Vite Devtools with Regle panel\" />"
|
|
283
283
|
},
|
|
284
284
|
{
|
|
285
285
|
"id": "introduction-index",
|
|
286
286
|
"title": "Introduction",
|
|
287
287
|
"category": "introduction",
|
|
288
288
|
"path": "introduction/index.md",
|
|
289
|
-
"content": "# Introduction\n\n## What is Regle?\n\nIf you've ever built a forms and wrote repetitive validation logic, struggling with complex error states, or losing type safety along the way, Regle is the perfect solution.\n\nRegle is a type-safe, headless form validation library that lets you write validation rules that mirror your data structure. Think of it as the perfect evolution of Vuelidate, but with modern TypeScript support and a more intuitive API.\n\n## Why Choose Regle?\n\n- **🔒 Type Safe**: Full TypeScript inference means autocomplete everywhere and catch errors at compile time\n- **🌳 Model-Based**: Your validation tree matches your data model—no mental gymnastics required \n- **🔌 Headless**: Works with any UI framework, CSS library, or design system\n- **🔍 Devtools**: Built-in Vue devtools
|
|
289
|
+
"content": "# Introduction\n\n## What is Regle?\n\nIf you've ever built a forms and wrote repetitive validation logic, struggling with complex error states, or losing type safety along the way, Regle is the perfect solution.\n\nRegle is a type-safe, headless form validation library that lets you write validation rules that mirror your data structure. Think of it as the perfect evolution of Vuelidate, but with modern TypeScript support and a more intuitive API.\n\n## Why Choose Regle?\n\n- **🔒 Type Safe**: Full TypeScript inference means autocomplete everywhere and catch errors at compile time\n- **🌳 Model-Based**: Your validation tree matches your data model—no mental gymnastics required \n- **🔌 Headless**: Works with any UI framework, CSS library, or design system\n- **🔍 Devtools**: Built-in Vue devtools extension for easy debugging and testing.\n- **📦 Modular**: Use built-in rules or create custom ones that fit your exact needs\n- **⚡ Performance**: Efficient reactivity system that only updates what changed\n- **🛠 Developer Experience**: If you've used Vuelidate, you'll feel right at home\n\n## Basic example\n\nHere's a real form that you can copy and use right away:\n\nFrom `r$`, you can build any UI you want. The validation logic is completely separate from your presentation layer.\n\n**Live Result:**\n\n## What's Next?\n\nReady to dive deeper? Here's your learning path:\n\n1. **[Installation](/introduction/installation)** - Get Regle set up in your project\n2. **[Core Concepts](/core-concepts/)** - Understand how `useRegle` works\n3. **[Built-in Rules](/core-concepts/rules/built-in-rules)** - Explore all available validation rules\n4. **[Examples](/examples/simple)** - See Regle in action with real-world scenarios\n\n:::tip Coming from Vuelidate?\nRegle's API is intentionally similar to Vuelidate's. Check out our [comparison guide](/introduction/comparisons#vuelidate) to see what's changed and what's stayed the same.\n:::"
|
|
290
290
|
},
|
|
291
291
|
{
|
|
292
292
|
"id": "introduction-installation",
|
|
@@ -314,14 +314,14 @@ var docs_data_default = {
|
|
|
314
314
|
"title": "Type safe output",
|
|
315
315
|
"category": "typescript",
|
|
316
316
|
"path": "typescript/type-safe-output.md",
|
|
317
|
-
"content": "# Type safe output\n\nWhat would be the benefit of building a validation library without a type safe output?\n\nInspired by the `Zod` parse output type, `Regle` will also infer your validator types to know which properties are _**guaranteed**_ to be defined.\n\n## `$validate` \n\nUsing `r$.$validate` will asynchronously run and wait for all your validators to finish, and will return an object containing the status of your form.\n\n```ts\nconst { valid, data, errors, issues } = await r$.$validate();\n```\n\nIf your *_result_* is `true`, the **data** will be type safe.\n\nIt will check the rules to get the ones that ensure the value is set (`required`, `literal`, `checked`)\n\
|
|
317
|
+
"content": "# Type safe output\n\nWhat would be the benefit of building a validation library without a type safe output?\n\nInspired by the `Zod` parse output type, `Regle` will also infer your validator types to know which properties are _**guaranteed**_ to be defined.\n\n## `$validate` \n\nUsing `r$.$validate` will asynchronously run and wait for all your validators to finish, and will return an object containing the status of your form.\n\n```ts\nconst { valid, data, errors, issues } = await r$.$validate();\n```\n\nIf your *_result_* is `true`, the **data** will be type safe.\n\nIt will check the rules to get the ones that ensure the value is set (`required`, `literal`, `checked`)\n\nIt will not work with `requiredIf` or `requiredUnless`, because we can't know the condition at build time.\n\n```ts twoslash\nimport { useRegle } from '@regle/core';\nimport { ref, type Ref, computed } from 'vue';\nimport { required } from '@regle/rules';\n// ---cut---\ntype Form = {\n firstName?: string;\n lastName?: string;\n}\n\nconst form = ref<Form>({ firstName: '', lastName: '' })\n\nconst { r$ } = useRegle(form, {\n lastName: { required },\n});\n\nasync function submit() {\n const { valid, data, errors, issues } = await r$.$validate();\n\n if (valid) {\n console.log(data);\n \n }\n}\n```\n\n<br/>\n\n### `InferSafeOutput`\n\nYou can also statically infer the safe output from any `r$` instance.\n\n```ts twoslash\nimport { ref, type Ref, computed } from 'vue';\nimport { required } from '@regle/rules';\n// ---cut---\nimport { useRegle, InferSafeOutput } from '@regle/core';\ntype Form = {\n firstName?: string;\n lastName?: string;\n}\n\nconst form: Ref<Form> = ref({ firstName: '', lastName: '' })\n\nconst { r$ } = useRegle(form, {\n lastName: { required },\n});\n\ntype FormRequest = InferSafeOutput<typeof r$>;\n\n```"
|
|
318
318
|
},
|
|
319
319
|
{
|
|
320
320
|
"id": "typescript-typing-props",
|
|
321
321
|
"title": "Typing props",
|
|
322
322
|
"category": "typescript",
|
|
323
323
|
"path": "typescript/typing-props.md",
|
|
324
|
-
"content": "# Typing props\n\nForms often span multiple components, and splitting your logic across components is a common practice. Regle offers tools to help type your props correctly, ensuring type safety and improving developer experience.\n\nThe best way to manage a centralized form state with inferred types is by using a Pinia store. Learn more in the Usage with Pinia guide [explained here](/common-usage/usage-with-pinia).\n\nIf you cannot use Pinia, here are the alternative approaches.\n\n## Typing component props\n\nAs Regle's types are complex and based on both your state and your rules, it's hard to replicate manually.\n\n`@regle/core` exports all its utility types, it can be long to explain each one of them, so we'll show the simplest way to type your props.\n\nTo avoid juggling with complex generic types, you can declare your form in a composable inside a file outside your component, and use this composable to type your props.\n\n:::code-group\n\n```ts twoslash include useMyForm [useMyForm.ts]\nimport { useRegle } from '@regle/core';\nimport { email, maxValue, minLength, numeric, required } from '@regle/rules';\n\nexport function useMyForm() {\n return useRegle(\n { email: '', user: { firstName: '', lastName: '' } },\n {\n email: { required, email: email },\n user: {\n firstName: {\n required,\n minLength: minLength(6),\n },\n lastName: {\n minLength: minLength(6),\n },\n },\n }\n );\n}\n```\n\n```vue twoslash [Parent.vue]\n<template>\n <input v-model=\"r$.$value.email\" placeholder=\"age\" />\n <Child :regle=\"r$\" />\n</template>\n\n```\n\n```vue twoslash [Child.vue]\n<template>\n <ul>\n <li v-for=\"error of r$.$errors.email\" :key=\"error\">\n {{ error }}\n </li>\n </ul>\n</template>\n\n```\n:::\n\n:::tip\n`InferRegleRoot` also works with `@regle/schemas`\n:::\n\n### Manually typing your state and rules\n\nIf you happen to have no way of importing the type, you can
|
|
324
|
+
"content": "# Typing props\n\nForms often span multiple components, and splitting your logic across components is a common practice. Regle offers tools to help type your props correctly, ensuring type safety and improving developer experience.\n\nThe best way to manage a centralized form state with inferred types is by using a Pinia store. Learn more in the Usage with Pinia guide [explained here](/common-usage/usage-with-pinia).\n\nIf you cannot use Pinia, here are the alternative approaches.\n\n## Typing component props\n\nAs Regle's types are complex and based on both your state and your rules, it's hard to replicate manually.\n\n`@regle/core` exports all its utility types, it can be long to explain each one of them, so we'll show the simplest way to type your props.\n\nTo avoid juggling with complex generic types, you can declare your form in a composable inside a file outside your component, and use this composable to type your props.\n\n:::code-group\n\n```ts twoslash include useMyForm [useMyForm.ts]\nimport { useRegle } from '@regle/core';\nimport { email, maxValue, minLength, numeric, required } from '@regle/rules';\n\nexport function useMyForm() {\n return useRegle(\n { email: '', user: { firstName: '', lastName: '' } },\n {\n email: { required, email: email },\n user: {\n firstName: {\n required,\n minLength: minLength(6),\n },\n lastName: {\n minLength: minLength(6),\n },\n },\n }\n );\n}\n```\n\n```vue twoslash [Parent.vue]\n<template>\n <input v-model=\"r$.$value.email\" placeholder=\"age\" />\n <Child :regle=\"r$\" />\n</template>\n\n```\n\n```vue twoslash [Child.vue]\n<template>\n <ul>\n <li v-for=\"error of r$.$errors.email\" :key=\"error\">\n {{ error }}\n </li>\n </ul>\n</template>\n\n```\n:::\n\n:::tip\n`InferRegleRoot` also works with `@regle/schemas`\n:::\n\n### Manually typing your state and rules\n\nIf you happen to have no way of importing the type, you can still use `RegleRoot` type, that will allow you to manually type your state and rules.\n\n```vue [MyForm.vue]\n\n```\n\n:::warning\nWhile this can be useful, be warned that `r$` will be missing the rule properties.\n:::\n\n## Typing a field prop\n\nIt's possible that you have a `MyInput` like component that contains your business logic.\nYou may want to pass regle computed properties to this component to display useful information to the user.\n\nHere's how you can do it:\n\n:::code-group\n\n```vue [MyInput.vue]\n<template>\n <div class=\"my-input\">\n <input\n v-model=\"modelValue\"\n :class=\"{ valid: field.$correct, error: field.$error }\"\n :placeholder=\"placeholder\"\n />\n\n <ul v-if=\"field.$errors.length\">\n <li v-for=\"error of field.$errors\" :key=\"error\">\n {{ error }}\n </li>\n </ul>\n </div>\n</template>\n\n```\n\n```vue [myForm.vue]\n<template>\n <form>\n <MyInput v-model=\"r$.$value.name\" :field=\"r$.name\" placeholder=\"Type your name\" />\n <MyInput v-model=\"r$.$value.email\" :field=\"r$.email\" placeholder=\"Type your email\" />\n </form>\n</template>\n\n```\n:::\n\n## Typing a field prop with global configuration\n\n:::code-group\n\n```ts twoslash include config [config.ts]\n\nimport { withMessage } from '@regle/rules';\n// ---cut---\nimport { defineRegleConfig } from '@regle/core';\n\nexport const { useRegle: useCustomRegle } = defineRegleConfig({\n rules: () => ({\n strongPassword: withMessage(() => true, 'test')\n }),\n shortcuts: {\n fields: {\n $test: () => true\n }\n }\n});\n```\n\n```vue twoslash [MyPassword.vue]\n\n```\n\n:::\n\n## Enforcing rules for a specific component\n\nOn your common Input component, you can also enforce a rule to be present in the field.\n\n```vue twoslash [MyPassword.vue]\n\n```\n\n### For a custom configurations\n\n:::code-group\n\n```ts twoslash include config [config.ts]\n\nimport { withMessage } from '@regle/rules';\n// ---cut---\nimport { defineRegleConfig } from '@regle/core';\n\nexport const { useRegle: useCustomRegle } = defineRegleConfig({\n rules: () => ({\n strongPassword: withMessage(() => true, 'test')\n }),\n shortcuts: {\n fields: {\n $test: () => true\n }\n }\n});\n```\n\n```vue twoslash [MyPassword.vue]\n\n```\n\n:::"
|
|
325
325
|
},
|
|
326
326
|
{
|
|
327
327
|
"id": "typescript-typing-rules",
|
|
@@ -820,7 +820,7 @@ var docs_data_default = {
|
|
|
820
820
|
"optional": true
|
|
821
821
|
}
|
|
822
822
|
],
|
|
823
|
-
"returnType": "
|
|
823
|
+
"returnType": "TRulesDelc",
|
|
824
824
|
"example": "import { required, email, minLength, assignIf } from '@regle/rules';\n\nconst condition = ref(false);\n\nconst { r$ } = useRegle(ref({ name: '', email: '' }), {\n name: assignIf(condition, { required, minLength: minLength(4) }),\n email: { email },\n});",
|
|
825
825
|
"tags": { "see": "://reglejs.dev/core-concepts/rules/rules-operators#assignif Documentation" }
|
|
826
826
|
},
|
|
@@ -1934,7 +1934,7 @@ function searchApi(query) {
|
|
|
1934
1934
|
return results;
|
|
1935
1935
|
}
|
|
1936
1936
|
|
|
1937
|
-
var version = "1.18.
|
|
1937
|
+
var version = "1.18.3";
|
|
1938
1938
|
|
|
1939
1939
|
let posthogClient = null;
|
|
1940
1940
|
posthogClient = new PostHog("phc_kqgJoylCpKkGkkRGxb4MyN2mViehoQcUFEGwVkk4l8E", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@regle/mcp-server",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.3",
|
|
4
4
|
"description": "MCP Server for Regle",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@modelcontextprotocol/sdk": "1.
|
|
48
|
+
"@modelcontextprotocol/sdk": "1.26.0",
|
|
49
49
|
"posthog-node": "5.24.1",
|
|
50
50
|
"zod": "4.3.6"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@types/node": "24.
|
|
53
|
+
"@types/node": "24.10.10",
|
|
54
54
|
"dotenv": "17.2.3",
|
|
55
55
|
"tsdown": "0.20.1",
|
|
56
56
|
"tsx": "4.21.0",
|