From a9070d997df4b143be8a60cbfdf2ce650d3005a0 Mon Sep 17 00:00:00 2001 From: ealush Date: Sat, 16 Jul 2022 01:15:16 +0300 Subject: [PATCH] documentation: add code comments to enforceEager --- packages/n4s/src/runtime/enforceEager.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/n4s/src/runtime/enforceEager.ts b/packages/n4s/src/runtime/enforceEager.ts index b9dda6070..13b9ac840 100644 --- a/packages/n4s/src/runtime/enforceEager.ts +++ b/packages/n4s/src/runtime/enforceEager.ts @@ -8,19 +8,30 @@ import { transformResult } from 'transformResult'; type IRules = n4s.IRules>; +// eslint-disable-next-line max-lines-per-function export default function enforceEager(value: RuleValue): IRules { const target = {} as IRules; + + // This condition is for when we don't have proxy support (ES5). + // In this case, we need to manually assign the rules to the target object on runtime. + // The follow up proxy block is used in case we do have proxy support, and we can assign each rule upon invocation. if (!isProxySupported()) { + // We iterate over each of the rules, and add them to the target object being return by enforce eachEnforceRule((ruleName: KBaseRules, ruleFn) => { + // We then wrap the rule with `genRuleCall` that adds the base enforce behavior target[ruleName] = genRuleCall(target, ruleFn, ruleName); }); return target; } + // We create a proxy intercepting access to the target object (which is empty). const proxy: IRules = new Proxy(target, { get: (_, ruleName: string) => { + // On property access, we identify if it is a rule or not. const rule = getRule(ruleName); + + // If it is a rule, we wrap it with `genRuleCall` that adds the base enforce behavior if (rule) { return genRuleCall(proxy, rule, ruleName); } @@ -29,12 +40,21 @@ export default function enforceEager(value: RuleValue): IRules { return proxy; + // This function is used to wrap a rule with the base enforce behavior + // It takes the target object, the rule function, and the rule name + // It then returns the rule, in a manner that can be used by enforce function genRuleCall(target: IRules, rule: RuleBase, ruleName: string) { return function ruleCall(...args: Args) { + // Order of operation: + // 1. Create a context with the value being enforced + // 2. Call the rule within the context, and pass over the arguments passed to it + // 3. Transform the result to the correct output format const transformedResult = ctx.run({ value }, () => transformResult(rule(value, ...args), ruleName, value, ...args) ); + // On rule failure (the result is false), we either throw an error + // or throw a string value if the rule has a message defined in it. invariant( transformedResult.pass, isNullish(transformedResult.message)