Skip to content

Commit

Permalink
Async with params working, withAsync, withParams with async rules
Browse files Browse the repository at this point in the history
  • Loading branch information
victorgarciaesgi committed Oct 6, 2023
1 parent 96affd4 commit a593731
Show file tree
Hide file tree
Showing 21 changed files with 381 additions and 422 deletions.
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,23 @@
"typecheck": "vue-tsc --noEmit",
"release": "bumpp && npm publish && git push --follow-tags"
},
"dependencies": {},
"devDependencies": {
"@types/prettier": "3.0.0",
"@typescript-eslint/eslint-plugin": "6.7.2",
"@typescript-eslint/parser": "6.7.2",
"@typescript-eslint/eslint-plugin": "6.7.4",
"@typescript-eslint/parser": "6.7.4",
"@vue/test-utils": "2.4.1",
"bumpp": "9.2.0",
"bun-types": "^1.0.3",
"changelogithub": "0.13.0",
"cross-env": "7.0.3",
"eslint": "8.50.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-vue": "9.17.0",
"prettier": "3.0.3",
"typescript": "5.2.2",
"vue": "3.3.4",
"vue-eslint-parser": "9.3.1",
"vue-tsc": "1.8.13",
"vue": "3.3.4"
"vue-tsc": "1.8.15",
"@total-typescript/ts-reset": "0.5.1"
},
"type": "module",
"main": "./dist/module.cjs",
Expand Down
10 changes: 4 additions & 6 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,22 @@
"typecheck": "tsc --noEmit",
"release": "bumpp && npm publish && git push --follow-tags"
},
"dependencies": {},
"devDependencies": {
"@types/prettier": "3.0.0",
"@typescript-eslint/eslint-plugin": "6.7.2",
"@typescript-eslint/parser": "6.7.2",
"@typescript-eslint/eslint-plugin": "6.7.4",
"@typescript-eslint/parser": "6.7.4",
"@vue/test-utils": "2.4.1",
"bumpp": "9.2.0",
"bun-types": "^1.0.3",
"changelogithub": "0.13.0",
"cross-env": "7.0.3",
"eslint": "8.50.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-vue": "9.17.0",
"prettier": "3.0.3",
"typescript": "5.2.2",
"vue": "3.3.4",
"vue-eslint-parser": "9.3.1",
"vue-tsc": "1.8.13",
"vue": "3.3.4"
"vue-tsc": "1.8.15"
},
"type": "module",
"main": "./src/index.ts",
Expand Down
6 changes: 2 additions & 4 deletions packages/core/src/core/defineCustomValidators.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AllRulesDeclarations, CustomRulesDeclarationTree } from '../types';
import { createUseFormComposable } from './useRegle';
import { createUseRegleComposable } from './useRegle';

/**
* Root function that allows you to define project-wise all your custom validators or overwrite default ones
Expand All @@ -11,9 +11,7 @@ import { createUseFormComposable } from './useRegle';
export function defineCustomValidators<TCustomRules extends Partial<AllRulesDeclarations>>(
customRules: () => TCustomRules
) {
const useRegle = createUseFormComposable<CustomRulesDeclarationTree>(
customRules as () => CustomRulesDeclarationTree
);
const useRegle = createUseRegleComposable<TCustomRules>(customRules);

return {
useRegle,
Expand Down
18 changes: 16 additions & 2 deletions packages/core/src/core/useRegle/guards/ruleDef.guards.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Ref, toRaw } from 'vue';
import { Ref } from 'vue';
import {
FormRuleDeclaration,
InlineRuleDeclaration,
RegleCollectionRuleDecl,
RegleFormPropertyType,
ReglePartialValidationTree,
Expand All @@ -25,10 +27,22 @@ export function isCollectionRulesDef(
return !!rule.value && '$each' in rule.value;
}

export function isValidatorRulesDef(rule: Ref<RegleFormPropertyType>): rule is Ref<RegleRuleDecl> {
export function isValidatorRulesDef(
rule: Ref<RegleFormPropertyType>
): rule is Ref<RegleRuleDecl<any, any>> {
return !!rule.value && isObject(rule.value);
}

export function isRuleDef(rule: unknown): rule is RegleRuleDefinition {
return isObject(rule) && '_validator' in rule;
}

export function isFormRuleDefinition(
rule: Ref<unknown>
): rule is Ref<RegleRuleDefinition<any, any>> {
return !(typeof rule.value === 'function');
}

export function isFormInline(rule: Ref<unknown>): rule is Ref<InlineRuleDeclaration<any>> {
return typeof rule.value === 'function';
}
8 changes: 6 additions & 2 deletions packages/core/src/core/useRegle/useRegle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '../../types';
import { useStateProperties } from './useStateProperties';

export function createUseFormComposable<TCustomRules extends CustomRulesDeclarationTree>(
export function createUseRegleComposable<TCustomRules extends Partial<AllRulesDeclarations>>(
customRules: () => TCustomRules
) {
function useRegle<
Expand All @@ -19,7 +19,11 @@ export function createUseFormComposable<TCustomRules extends CustomRulesDeclarat

const initialState = shallowRef(structuredClone(toRaw(state.value)));

const { $regle, errors } = useStateProperties(scopeRules, state, customRules);
const { $regle, errors } = useStateProperties(
scopeRules,
state,
customRules as () => CustomRulesDeclarationTree
);

return {
state,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { Ref, computed, reactive, ref, watch } from 'vue';
import { isEmpty } from '../../../helpers';
import {
CustomRulesDeclarationTree,
InlineRuleDeclaration,
InternalRuleType,
RegleRuleDefinition,
RegleRuleDefinitionProcessor,
RegleSoftRuleStatus,
} from '../../../types';
import { unwrapRuleParameters } from '../../createRule/unwrapRuleParameters';
import { isFormInline, isFormRuleDefinition } from '../guards';

export function createReactiveRuleStatus({
$dirty,
customMessages,
rule,
ruleKey,
state,
}: {
state: Ref<unknown>;
ruleKey: string;
rule: Ref<InlineRuleDeclaration<any>> | Ref<RegleRuleDefinition<any, any>>;
$dirty: Ref<boolean>;
customMessages: Partial<CustomRulesDeclarationTree>;
}) {
const $pending = ref(false);
const $valid = ref(true);

const $active = computed<boolean>(() => {
if (isFormInline(rule)) {
return true;
} else {
if (typeof rule.value.active === 'function') {
return rule.value.active(state.value, ...$params.value);
} else {
return rule.value.active;
}
}
});

const $message = computed<string>(() => {
let message = '';
const customMessageRule = customMessages[ruleKey]?.message;

if (customMessageRule) {
if (typeof customMessageRule === 'function') {
message = customMessageRule(state.value, ...$params.value);
} else {
message = customMessageRule;
}
}
if (isFormRuleDefinition(rule)) {
if (!(customMessageRule && !rule.value._patched)) {
if (typeof rule.value.message === 'function') {
message = rule.value.message(state.value, ...$params.value);
} else {
message = rule.value.message;
}
}
}

if (isEmpty(message)) {
message = 'Error';
console.warn(`No error message defined for ${ruleKey}`);
}

return message;
});

const $type = computed(() => {
if (isFormInline(rule)) {
return ruleKey;
} else {
return Object.values(InternalRuleType).includes(rule.value.type) ? ruleKey : rule.value.type;
}
});

const $validator = computed<RegleRuleDefinitionProcessor<any, any, boolean | Promise<boolean>>>(
() => {
if (isFormInline(rule)) {
return rule.value;
} else {
return rule.value.validator;
}
}
);

const $params = computed<any[]>(() => {
if (typeof rule.value === 'function') {
return [];
}
return unwrapRuleParameters(rule.value._params ?? []);
});

watch(
[state, $dirty, $params],
async () => {
const validator = $validator.value;
let ruleResult = false;
const resultOrPromise = validator(state.value, ...$params.value);

if (resultOrPromise instanceof Promise) {
if ($dirty.value) {
try {
$valid.value = true;
$pending.value = true;
const promiseResult = await resultOrPromise;
ruleResult = promiseResult;
} catch (e) {
ruleResult = false;
} finally {
$pending.value = false;
}
}
} else {
ruleResult = resultOrPromise;
}
$valid.value = ruleResult;
},
{ immediate: true, deep: true }
);

return reactive({
$message,
$active,
$pending,
$type,
$valid,
$validator,
...($params.value.length && { $params }),
}) satisfies RegleSoftRuleStatus;
}
Loading

0 comments on commit a593731

Please sign in to comment.