| const ChainedMap = require('./ChainedMap'); | 
| const ChainedSet = require('./ChainedSet'); | 
| const Orderable = require('./Orderable'); | 
| const Use = require('./Use'); | 
| const Resolve = require('./Resolve'); | 
|   | 
| function toArray(arr) { | 
|   return Array.isArray(arr) ? arr : [arr]; | 
| } | 
|   | 
| const Rule = Orderable( | 
|   class extends ChainedMap { | 
|     constructor(parent, name, ruleType = 'rule') { | 
|       super(parent); | 
|       this.name = name; | 
|       this.names = []; | 
|       this.ruleType = ruleType; | 
|       this.ruleTypes = []; | 
|   | 
|       let rule = this; | 
|       while (rule instanceof Rule) { | 
|         this.names.unshift(rule.name); | 
|         this.ruleTypes.unshift(rule.ruleType); | 
|         rule = rule.parent; | 
|       } | 
|   | 
|       this.uses = new ChainedMap(this); | 
|       this.include = new ChainedSet(this); | 
|       this.exclude = new ChainedSet(this); | 
|       this.rules = new ChainedMap(this); | 
|       this.oneOfs = new ChainedMap(this); | 
|       this.resolve = new Resolve(this); | 
|       this.extend([ | 
|         'enforce', | 
|         'issuer', | 
|         'parser', | 
|         'resource', | 
|         'resourceQuery', | 
|         'sideEffects', | 
|         'test', | 
|         'type', | 
|       ]); | 
|     } | 
|   | 
|     use(name) { | 
|       return this.uses.getOrCompute(name, () => new Use(this, name)); | 
|     } | 
|   | 
|     rule(name) { | 
|       return this.rules.getOrCompute(name, () => new Rule(this, name, 'rule')); | 
|     } | 
|   | 
|     oneOf(name) { | 
|       return this.oneOfs.getOrCompute( | 
|         name, | 
|         () => new Rule(this, name, 'oneOf'), | 
|       ); | 
|     } | 
|   | 
|     pre() { | 
|       return this.enforce('pre'); | 
|     } | 
|   | 
|     post() { | 
|       return this.enforce('post'); | 
|     } | 
|   | 
|     toConfig() { | 
|       const config = this.clean( | 
|         Object.assign(this.entries() || {}, { | 
|           include: this.include.values(), | 
|           exclude: this.exclude.values(), | 
|           rules: this.rules.values().map((rule) => rule.toConfig()), | 
|           oneOf: this.oneOfs.values().map((oneOf) => oneOf.toConfig()), | 
|           use: this.uses.values().map((use) => use.toConfig()), | 
|           resolve: this.resolve.toConfig(), | 
|         }), | 
|       ); | 
|   | 
|       Object.defineProperties(config, { | 
|         __ruleNames: { value: this.names }, | 
|         __ruleTypes: { value: this.ruleTypes }, | 
|       }); | 
|   | 
|       return config; | 
|     } | 
|   | 
|     merge(obj, omit = []) { | 
|       if (!omit.includes('include') && 'include' in obj) { | 
|         this.include.merge(toArray(obj.include)); | 
|       } | 
|   | 
|       if (!omit.includes('exclude') && 'exclude' in obj) { | 
|         this.exclude.merge(toArray(obj.exclude)); | 
|       } | 
|   | 
|       if (!omit.includes('use') && 'use' in obj) { | 
|         Object.keys(obj.use).forEach((name) => | 
|           this.use(name).merge(obj.use[name]), | 
|         ); | 
|       } | 
|   | 
|       if (!omit.includes('rules') && 'rules' in obj) { | 
|         Object.keys(obj.rules).forEach((name) => | 
|           this.rule(name).merge(obj.rules[name]), | 
|         ); | 
|       } | 
|   | 
|       if (!omit.includes('oneOf') && 'oneOf' in obj) { | 
|         Object.keys(obj.oneOf).forEach((name) => | 
|           this.oneOf(name).merge(obj.oneOf[name]), | 
|         ); | 
|       } | 
|   | 
|       if (!omit.includes('resolve') && 'resolve' in obj) { | 
|         this.resolve.merge(obj.resolve); | 
|       } | 
|   | 
|       if (!omit.includes('test') && 'test' in obj) { | 
|         this.test( | 
|           obj.test instanceof RegExp || typeof obj.test === 'function' | 
|             ? obj.test | 
|             : new RegExp(obj.test), | 
|         ); | 
|       } | 
|   | 
|       return super.merge(obj, [ | 
|         ...omit, | 
|         'include', | 
|         'exclude', | 
|         'use', | 
|         'rules', | 
|         'oneOf', | 
|         'resolve', | 
|         'test', | 
|       ]); | 
|     } | 
|   }, | 
| ); | 
|   | 
| module.exports = Rule; |