@ankhorage/rules 0.2.0
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/dist/cli/commands/config/validate.d.ts +6 -0
- package/dist/cli/commands/config/validate.d.ts.map +1 -0
- package/dist/cli/commands/config/validate.js +25 -0
- package/dist/cli/commands/config/validate.js.map +1 -0
- package/dist/cli/createRulesRuntimeProvider.d.ts +4 -0
- package/dist/cli/createRulesRuntimeProvider.d.ts.map +1 -0
- package/dist/cli/createRulesRuntimeProvider.js +29 -0
- package/dist/cli/createRulesRuntimeProvider.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/standalone.d.ts +6 -0
- package/dist/cli/standalone.d.ts.map +1 -0
- package/dist/cli/standalone.js +43 -0
- package/dist/cli/standalone.js.map +1 -0
- package/dist/constants/rules.d.ts +5 -0
- package/dist/constants/rules.d.ts.map +1 -0
- package/dist/constants/rules.js +6 -0
- package/dist/constants/rules.js.map +1 -0
- package/dist/features/configuration/adapters/filesystem/readRulesConfigSourceAsync.d.ts +3 -0
- package/dist/features/configuration/adapters/filesystem/readRulesConfigSourceAsync.d.ts.map +1 -0
- package/dist/features/configuration/adapters/filesystem/readRulesConfigSourceAsync.js +6 -0
- package/dist/features/configuration/adapters/filesystem/readRulesConfigSourceAsync.js.map +1 -0
- package/dist/features/configuration/adapters/filesystem/writeRulesConfigAsync.d.ts +4 -0
- package/dist/features/configuration/adapters/filesystem/writeRulesConfigAsync.d.ts.map +1 -0
- package/dist/features/configuration/adapters/filesystem/writeRulesConfigAsync.js +19 -0
- package/dist/features/configuration/adapters/filesystem/writeRulesConfigAsync.js.map +1 -0
- package/dist/features/configuration/application/validateRulesConfigFileAsync.d.ts +4 -0
- package/dist/features/configuration/application/validateRulesConfigFileAsync.d.ts.map +1 -0
- package/dist/features/configuration/application/validateRulesConfigFileAsync.js +27 -0
- package/dist/features/configuration/application/validateRulesConfigFileAsync.js.map +1 -0
- package/dist/features/configuration/composition/readRulesConfigAsync.d.ts +4 -0
- package/dist/features/configuration/composition/readRulesConfigAsync.d.ts.map +1 -0
- package/dist/features/configuration/composition/readRulesConfigAsync.js +7 -0
- package/dist/features/configuration/composition/readRulesConfigAsync.js.map +1 -0
- package/dist/features/configuration/domain/validateRulesConfig.d.ts +4 -0
- package/dist/features/configuration/domain/validateRulesConfig.d.ts.map +1 -0
- package/dist/features/configuration/domain/validateRulesConfig.js +159 -0
- package/dist/features/configuration/domain/validateRulesConfig.js.map +1 -0
- package/dist/features/evaluation/domain/createRuleRegistry.d.ts +4 -0
- package/dist/features/evaluation/domain/createRuleRegistry.d.ts.map +1 -0
- package/dist/features/evaluation/domain/createRuleRegistry.js +36 -0
- package/dist/features/evaluation/domain/createRuleRegistry.js.map +1 -0
- package/dist/features/evaluation/domain/evaluateConfiguredRules.d.ts +4 -0
- package/dist/features/evaluation/domain/evaluateConfiguredRules.d.ts.map +1 -0
- package/dist/features/evaluation/domain/evaluateConfiguredRules.js +52 -0
- package/dist/features/evaluation/domain/evaluateConfiguredRules.js.map +1 -0
- package/dist/features/evaluation/domain/evaluateRules.d.ts +4 -0
- package/dist/features/evaluation/domain/evaluateRules.d.ts.map +1 -0
- package/dist/features/evaluation/domain/evaluateRules.js +53 -0
- package/dist/features/evaluation/domain/evaluateRules.js.map +1 -0
- package/dist/features/evaluation/domain/resolveRulesStatus.d.ts +4 -0
- package/dist/features/evaluation/domain/resolveRulesStatus.d.ts.map +1 -0
- package/dist/features/evaluation/domain/resolveRulesStatus.js +12 -0
- package/dist/features/evaluation/domain/resolveRulesStatus.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/types/rules.d.ts +121 -0
- package/dist/types/rules.d.ts.map +1 -0
- package/dist/types/rules.js +2 -0
- package/dist/types/rules.js.map +1 -0
- package/dist/utils/compareRuleEntityIds.d.ts +7 -0
- package/dist/utils/compareRuleEntityIds.d.ts.map +1 -0
- package/dist/utils/compareRuleEntityIds.js +9 -0
- package/dist/utils/compareRuleEntityIds.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateRulesConfig.js","sourceRoot":"","sources":["../../../../src/features/configuration/domain/validateRulesConfig.ts"],"names":[],"mappings":"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","sourcesContent":["import { isRecord } from '@ankhorage/utility/object';\n\nimport type {\n JsonValue,\n RulesConfig,\n RulesConfigDiagnostic,\n RulesConfigRule,\n RulesConfigValidationOptions,\n RulesConfigValidationResult,\n RuleSeverity,\n} from '../../../types/rules.js';\n\n/*** Validate canonical rules.json data, optionally against a concrete rule registry. */\nexport function validateRulesConfig<TContext>(\n value: unknown,\n options: RulesConfigValidationOptions<TContext> = {},\n): RulesConfigValidationResult {\n const structuralResult = validateRulesConfigStructure(value);\n if (structuralResult.config === null) return structuralResult;\n\n const diagnostics = validateConfiguredRules(structuralResult.config, options);\n return {\n config: diagnostics.length === 0 ? structuralResult.config : null,\n diagnostics,\n };\n}\n\n/*** Validate the JSON-only shape before any provider-specific interpretation occurs. */\nfunction validateRulesConfigStructure(value: unknown): RulesConfigValidationResult {\n if (!isRecord(value)) return invalidConfig('rules.json must contain an object.');\n if (value.version !== 1) return invalidConfig('rules.json \"version\" must be 1.', 'version');\n if (!Array.isArray(value.rules)) {\n return invalidConfig('rules.json \"rules\" must be an array.', 'rules');\n }\n\n const ruleResults = value.rules.map((rule, index) => validateRulesConfigRule(rule, index));\n const diagnostics = ruleResults.flatMap((result) => result.diagnostics);\n if (diagnostics.length > 0) return { config: null, diagnostics };\n\n const rules = ruleResults.flatMap((result) => (result.rule === null ? [] : [result.rule]));\n const duplicateIds = findDuplicateRuleIds(rules);\n if (duplicateIds.length > 0) {\n return {\n config: null,\n diagnostics: duplicateIds.map((id) => ({\n code: 'invalid-rule-id',\n message: `rules.json configures rule \"${id}\" more than once.`,\n path: 'rules',\n ruleId: id,\n })),\n };\n }\n\n return { config: { version: 1, rules }, diagnostics: [] };\n}\n\n/*** Validate one serialized rule selection while retaining its original options exactly. */\nfunction validateRulesConfigRule(\n value: unknown,\n index: number,\n): {\n readonly diagnostics: readonly RulesConfigDiagnostic[];\n readonly rule: RulesConfigRule | null;\n} {\n const path = `rules[${index}]`;\n if (!isRecord(value)) {\n return invalidRuleField('invalid-config', path, 'must be an object.');\n }\n if (!isNonEmptyString(value.id)) {\n return invalidRuleField('invalid-rule-id', `${path}.id`, 'must define a non-empty \"id\".');\n }\n if (typeof value.enabled !== 'boolean') {\n return invalidRuleField(\n 'invalid-config',\n `${path}.enabled`,\n 'must define boolean \"enabled\".',\n value.id,\n );\n }\n if (value.severity !== undefined && !isRuleSeverity(value.severity)) {\n return invalidRuleField(\n 'invalid-severity',\n `${path}.severity`,\n 'has an invalid \"severity\".',\n value.id,\n );\n }\n if (value.options !== undefined && !isJsonValue(value.options)) {\n return invalidRuleField(\n 'invalid-options',\n `${path}.options`,\n 'has non-serializable \"options\".',\n value.id,\n );\n }\n\n return {\n diagnostics: [],\n rule: {\n id: value.id,\n enabled: value.enabled,\n ...(value.severity === undefined ? {} : { severity: value.severity }),\n ...(value.options === undefined ? {} : { options: value.options }),\n },\n };\n}\n\n/*** Apply optional registry and capability knowledge without creating provider-specific engine paths. */\nfunction validateConfiguredRules<TContext>(\n config: RulesConfig,\n options: RulesConfigValidationOptions<TContext>,\n): readonly RulesConfigDiagnostic[] {\n const { registry } = options;\n if (registry === undefined) return [];\n\n const availableCapabilities = new Set(options.capabilities ?? []);\n return config.rules.reduce<RulesConfigDiagnostic[]>((diagnostics, configuredRule, index) => {\n if (!configuredRule.enabled) return diagnostics;\n const rule = registry.ruleById.get(configuredRule.id);\n if (rule === undefined) {\n return [\n ...diagnostics,\n {\n code: 'unknown-rule' as const,\n message: `rules.json configures unknown rule \"${configuredRule.id}\".`,\n path: `rules[${index}].id`,\n ruleId: configuredRule.id,\n },\n ];\n }\n\n const missingCapabilities =\n options.capabilities === undefined\n ? []\n : (rule.requiredCapabilities ?? []).filter(\n (capability) => !availableCapabilities.has(capability),\n );\n const capabilityDiagnostics = missingCapabilities.map((capability) => ({\n code: 'missing-capability' as const,\n message: `Rule \"${rule.id}\" requires unavailable capability \"${capability}\".`,\n path: `rules[${index}]`,\n ruleId: rule.id,\n }));\n const optionDiagnostics = (rule.validateOptions?.(configuredRule.options) ?? []).map(\n (diagnostic) => ({\n code: 'invalid-options' as const,\n message: `Rule \"${rule.id}\": ${diagnostic.message}`,\n ruleId: rule.id,\n ...(diagnostic.path === undefined\n ? {}\n : { path: `rules[${index}].options.${diagnostic.path}` }),\n }),\n );\n return [...diagnostics, ...capabilityDiagnostics, ...optionDiagnostics];\n }, []);\n}\n\n/*** Create a consistent structural configuration diagnostic. */\nfunction invalidConfig(message: string, path?: string): RulesConfigValidationResult {\n return {\n config: null,\n diagnostics: [{ code: 'invalid-config', message, ...(path === undefined ? {} : { path }) }],\n };\n}\n\n/*** Create a field-specific diagnostic for one invalid configured rule. */\nfunction invalidRuleField(\n code: RulesConfigDiagnostic['code'],\n path: string,\n detail: string,\n ruleId?: string,\n): { readonly diagnostics: readonly RulesConfigDiagnostic[]; readonly rule: null } {\n return {\n rule: null,\n diagnostics: [\n {\n code,\n message: `rules.json ${path} ${detail}`,\n path,\n ...(ruleId === undefined ? {} : { ruleId }),\n },\n ],\n };\n}\n\n/*** Find duplicate explicit rule selections without relying on object-key ordering. */\nfunction findDuplicateRuleIds(rules: readonly RulesConfigRule[]): readonly string[] {\n const seen = new Set<string>();\n return rules.flatMap((rule) => {\n if (seen.has(rule.id)) return [rule.id];\n seen.add(rule.id);\n return [];\n });\n}\n\n/*** Determine whether a value is a supported generic severity. */\nfunction isRuleSeverity(value: unknown): value is RuleSeverity {\n return value === 'error' || value === 'info' || value === 'warning';\n}\n\n/*** Determine whether a value can be preserved losslessly in JSON configuration. */\nfunction isJsonValue(value: unknown): value is JsonValue {\n if (value === null || typeof value === 'boolean' || typeof value === 'string') return true;\n if (typeof value === 'number') return Number.isFinite(value);\n if (Array.isArray(value)) return value.every(isJsonValue);\n return isRecord(value) && Object.values(value).every(isJsonValue);\n}\n\n/*** Determine whether a raw configuration field is a non-empty identifier. */\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RuleRegistry, RuleSet } from '../../../types/rules.js';
|
|
2
|
+
/*** Create a deterministic registry from independently owned RuleSets. */
|
|
3
|
+
export declare function createRuleRegistry<TContext>(ruleSets: readonly RuleSet<TContext>[]): RuleRegistry<TContext>;
|
|
4
|
+
//# sourceMappingURL=createRuleRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createRuleRegistry.d.ts","sourceRoot":"","sources":["../../../../src/features/evaluation/domain/createRuleRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,YAAY,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAG3E,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,QAAQ,EACzC,QAAQ,EAAE,SAAS,OAAO,CAAC,QAAQ,CAAC,EAAE,GACrC,YAAY,CAAC,QAAQ,CAAC,CAWxB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { compareRuleEntityIds } from '../../../utils/compareRuleEntityIds.js';
|
|
2
|
+
/*** Create a deterministic registry from independently owned RuleSets. */
|
|
3
|
+
export function createRuleRegistry(ruleSets) {
|
|
4
|
+
const sortedRuleSets = [...ruleSets].sort(compareRuleEntityIds);
|
|
5
|
+
assertUniqueRuleSetIds(sortedRuleSets);
|
|
6
|
+
const rules = sortedRuleSets.flatMap((ruleSet) => ruleSet.rules).sort(compareRuleEntityIds);
|
|
7
|
+
assertUniqueRuleIds(rules);
|
|
8
|
+
return {
|
|
9
|
+
ruleSets: sortedRuleSets,
|
|
10
|
+
rules,
|
|
11
|
+
ruleById: new Map(rules.map((rule) => [rule.id, rule])),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/*** Reject ambiguous provider composition before evaluating a registry. */
|
|
15
|
+
function assertUniqueRuleSetIds(ruleSets) {
|
|
16
|
+
const duplicateId = findDuplicateId(ruleSets.map((ruleSet) => ruleSet.id));
|
|
17
|
+
if (duplicateId !== null)
|
|
18
|
+
throw new Error(`Duplicate RuleSet ID: ${duplicateId}`);
|
|
19
|
+
}
|
|
20
|
+
/*** Reject multiple providers that claim the same public rule identifier. */
|
|
21
|
+
function assertUniqueRuleIds(rules) {
|
|
22
|
+
const duplicateId = findDuplicateId(rules.map((rule) => rule.id));
|
|
23
|
+
if (duplicateId !== null)
|
|
24
|
+
throw new Error(`Duplicate rule ID: ${duplicateId}`);
|
|
25
|
+
}
|
|
26
|
+
/*** Find the first duplicate in an already deterministic sequence of identifiers. */
|
|
27
|
+
function findDuplicateId(ids) {
|
|
28
|
+
const seen = new Set();
|
|
29
|
+
for (const id of ids) {
|
|
30
|
+
if (seen.has(id))
|
|
31
|
+
return id;
|
|
32
|
+
seen.add(id);
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=createRuleRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createRuleRegistry.js","sourceRoot":"","sources":["../../../../src/features/evaluation/domain/createRuleRegistry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,0EAA0E;AAC1E,MAAM,UAAU,kBAAkB,CAChC,QAAsC;IAEtC,MAAM,cAAc,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAChE,sBAAsB,CAAC,cAAc,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC5F,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAE3B,OAAO;QACL,QAAQ,EAAE,cAAc;QACxB,KAAK;QACL,QAAQ,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;KACxD,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,SAAS,sBAAsB,CAAW,QAAsC;IAC9E,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3E,IAAI,WAAW,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,WAAW,EAAE,CAAC,CAAC;AACpF,CAAC;AAED,6EAA6E;AAC7E,SAAS,mBAAmB,CAAW,KAAgC;IACrE,MAAM,WAAW,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,IAAI,WAAW,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,WAAW,EAAE,CAAC,CAAC;AACjF,CAAC;AAED,qFAAqF;AACrF,SAAS,eAAe,CAAC,GAAsB;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { Rule, RuleRegistry, RuleSet } from '../../../types/rules.js';\nimport { compareRuleEntityIds } from '../../../utils/compareRuleEntityIds.js';\n\n/*** Create a deterministic registry from independently owned RuleSets. */\nexport function createRuleRegistry<TContext>(\n ruleSets: readonly RuleSet<TContext>[],\n): RuleRegistry<TContext> {\n const sortedRuleSets = [...ruleSets].sort(compareRuleEntityIds);\n assertUniqueRuleSetIds(sortedRuleSets);\n const rules = sortedRuleSets.flatMap((ruleSet) => ruleSet.rules).sort(compareRuleEntityIds);\n assertUniqueRuleIds(rules);\n\n return {\n ruleSets: sortedRuleSets,\n rules,\n ruleById: new Map(rules.map((rule) => [rule.id, rule])),\n };\n}\n\n/*** Reject ambiguous provider composition before evaluating a registry. */\nfunction assertUniqueRuleSetIds<TContext>(ruleSets: readonly RuleSet<TContext>[]): void {\n const duplicateId = findDuplicateId(ruleSets.map((ruleSet) => ruleSet.id));\n if (duplicateId !== null) throw new Error(`Duplicate RuleSet ID: ${duplicateId}`);\n}\n\n/*** Reject multiple providers that claim the same public rule identifier. */\nfunction assertUniqueRuleIds<TContext>(rules: readonly Rule<TContext>[]): void {\n const duplicateId = findDuplicateId(rules.map((rule) => rule.id));\n if (duplicateId !== null) throw new Error(`Duplicate rule ID: ${duplicateId}`);\n}\n\n/*** Find the first duplicate in an already deterministic sequence of identifiers. */\nfunction findDuplicateId(ids: readonly string[]): string | null {\n const seen = new Set<string>();\n for (const id of ids) {\n if (seen.has(id)) return id;\n seen.add(id);\n }\n return null;\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { EvaluateConfiguredRulesOptions, RuleEvaluationResult, RuleRegistry, RulesConfig } from '../../../types/rules.js';
|
|
2
|
+
/*** Resolve a configured Rule registry and evaluate its enabled rules without provider branches. */
|
|
3
|
+
export declare function evaluateConfiguredRules<TContext>(context: TContext, config: RulesConfig, registry: RuleRegistry<TContext>, options?: EvaluateConfiguredRulesOptions): RuleEvaluationResult;
|
|
4
|
+
//# sourceMappingURL=evaluateConfiguredRules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluateConfiguredRules.d.ts","sourceRoot":"","sources":["../../../../src/features/evaluation/domain/evaluateConfiguredRules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAE9B,oBAAoB,EAEpB,YAAY,EACZ,WAAW,EAEZ,MAAM,yBAAyB,CAAC;AAIjC,oGAAoG;AACpG,wBAAgB,uBAAuB,CAAC,QAAQ,EAC9C,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,EAChC,OAAO,GAAE,8BAAmC,GAC3C,oBAAoB,CA6BtB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { validateRulesConfig } from '../../configuration/domain/validateRulesConfig.js';
|
|
2
|
+
import { evaluateRules } from './evaluateRules.js';
|
|
3
|
+
/*** Resolve a configured Rule registry and evaluate its enabled rules without provider branches. */
|
|
4
|
+
export function evaluateConfiguredRules(context, config, registry, options = {}) {
|
|
5
|
+
const validation = validateRulesConfig(config, {
|
|
6
|
+
registry,
|
|
7
|
+
capabilities: options.capabilities,
|
|
8
|
+
});
|
|
9
|
+
if (validation.config === null) {
|
|
10
|
+
return {
|
|
11
|
+
findings: [],
|
|
12
|
+
diagnostics: validation.diagnostics.map(toEvaluationDiagnostic),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const enabledConfigurations = validation.config.rules.filter((rule) => rule.enabled);
|
|
16
|
+
const optionsByRuleId = new Map(enabledConfigurations.map((rule) => [rule.id, rule.options]));
|
|
17
|
+
const selectedRules = enabledConfigurations.flatMap((configuredRule) => {
|
|
18
|
+
const rule = registry.ruleById.get(configuredRule.id);
|
|
19
|
+
return rule === undefined ? [] : [rule];
|
|
20
|
+
});
|
|
21
|
+
const result = evaluateRules(context, selectedRules, {
|
|
22
|
+
capabilities: options.capabilities,
|
|
23
|
+
optionsByRuleId,
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
diagnostics: result.diagnostics,
|
|
27
|
+
findings: applyConfiguredSeverities(result.findings, validation.config),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/*** Translate config validation failures into the evaluator's portable diagnostic shape. */
|
|
31
|
+
function toEvaluationDiagnostic(diagnostic) {
|
|
32
|
+
return {
|
|
33
|
+
code: diagnostic.code === 'missing-capability'
|
|
34
|
+
? 'missing-capability'
|
|
35
|
+
: diagnostic.code === 'unknown-rule'
|
|
36
|
+
? 'unknown-rule'
|
|
37
|
+
: diagnostic.code === 'invalid-options'
|
|
38
|
+
? 'invalid-options'
|
|
39
|
+
: 'invalid-config',
|
|
40
|
+
ruleId: diagnostic.ruleId ?? 'rules.config',
|
|
41
|
+
message: diagnostic.message,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/*** Apply configured severity overrides after providers have produced neutral findings. */
|
|
45
|
+
function applyConfiguredSeverities(findings, config) {
|
|
46
|
+
const severityByRuleId = new Map(config.rules.map((rule) => [rule.id, rule.severity]));
|
|
47
|
+
return findings.map((finding) => ({
|
|
48
|
+
...finding,
|
|
49
|
+
severity: severityByRuleId.get(finding.ruleId) ?? finding.severity,
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=evaluateConfiguredRules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluateConfiguredRules.js","sourceRoot":"","sources":["../../../../src/features/evaluation/domain/evaluateConfiguredRules.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mDAAmD,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,oGAAoG;AACpG,MAAM,UAAU,uBAAuB,CACrC,OAAiB,EACjB,MAAmB,EACnB,QAAgC,EAChC,UAA0C,EAAE;IAE5C,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,EAAE;QAC7C,QAAQ;QACR,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CAAC;IACH,IAAI,UAAU,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO;YACL,QAAQ,EAAE,EAAE;YACZ,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,sBAAsB,CAAC;SAChE,CAAC;IACJ,CAAC;IAED,MAAM,qBAAqB,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrF,MAAM,eAAe,GAAG,IAAI,GAAG,CAC7B,qBAAqB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAU,CAAC,CACtE,CAAC;IACF,MAAM,aAAa,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,EAAE;QACrE,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE;QACnD,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,eAAe;KAChB,CAAC,CAAC;IAEH,OAAO;QACL,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,QAAQ,EAAE,yBAAyB,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC;KACxE,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,SAAS,sBAAsB,CAAC,UAAiC;IAC/D,OAAO;QACL,IAAI,EACF,UAAU,CAAC,IAAI,KAAK,oBAAoB;YACtC,CAAC,CAAC,oBAAoB;YACtB,CAAC,CAAC,UAAU,CAAC,IAAI,KAAK,cAAc;gBAClC,CAAC,CAAC,cAAc;gBAChB,CAAC,CAAC,UAAU,CAAC,IAAI,KAAK,iBAAiB;oBACrC,CAAC,CAAC,iBAAiB;oBACnB,CAAC,CAAC,gBAAgB;QAC1B,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,cAAc;QAC3C,OAAO,EAAE,UAAU,CAAC,OAAO;KAC5B,CAAC;AACJ,CAAC;AAED,2FAA2F;AAC3F,SAAS,yBAAyB,CAChC,QAAgC,EAChC,MAAmB;IAEnB,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAU,CAAC,CAAC,CAAC;IAChG,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAChC,GAAG,OAAO;QACV,QAAQ,EAAE,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ;KACnE,CAAC,CAAC,CAAC;AACN,CAAC","sourcesContent":["import type {\n EvaluateConfiguredRulesOptions,\n RuleEvaluationDiagnostic,\n RuleEvaluationResult,\n RuleFinding,\n RuleRegistry,\n RulesConfig,\n RulesConfigDiagnostic,\n} from '../../../types/rules.js';\nimport { validateRulesConfig } from '../../configuration/domain/validateRulesConfig.js';\nimport { evaluateRules } from './evaluateRules.js';\n\n/*** Resolve a configured Rule registry and evaluate its enabled rules without provider branches. */\nexport function evaluateConfiguredRules<TContext>(\n context: TContext,\n config: RulesConfig,\n registry: RuleRegistry<TContext>,\n options: EvaluateConfiguredRulesOptions = {},\n): RuleEvaluationResult {\n const validation = validateRulesConfig(config, {\n registry,\n capabilities: options.capabilities,\n });\n if (validation.config === null) {\n return {\n findings: [],\n diagnostics: validation.diagnostics.map(toEvaluationDiagnostic),\n };\n }\n\n const enabledConfigurations = validation.config.rules.filter((rule) => rule.enabled);\n const optionsByRuleId = new Map(\n enabledConfigurations.map((rule) => [rule.id, rule.options] as const),\n );\n const selectedRules = enabledConfigurations.flatMap((configuredRule) => {\n const rule = registry.ruleById.get(configuredRule.id);\n return rule === undefined ? [] : [rule];\n });\n const result = evaluateRules(context, selectedRules, {\n capabilities: options.capabilities,\n optionsByRuleId,\n });\n\n return {\n diagnostics: result.diagnostics,\n findings: applyConfiguredSeverities(result.findings, validation.config),\n };\n}\n\n/*** Translate config validation failures into the evaluator's portable diagnostic shape. */\nfunction toEvaluationDiagnostic(diagnostic: RulesConfigDiagnostic): RuleEvaluationDiagnostic {\n return {\n code:\n diagnostic.code === 'missing-capability'\n ? 'missing-capability'\n : diagnostic.code === 'unknown-rule'\n ? 'unknown-rule'\n : diagnostic.code === 'invalid-options'\n ? 'invalid-options'\n : 'invalid-config',\n ruleId: diagnostic.ruleId ?? 'rules.config',\n message: diagnostic.message,\n };\n}\n\n/*** Apply configured severity overrides after providers have produced neutral findings. */\nfunction applyConfiguredSeverities(\n findings: readonly RuleFinding[],\n config: RulesConfig,\n): readonly RuleFinding[] {\n const severityByRuleId = new Map(config.rules.map((rule) => [rule.id, rule.severity] as const));\n return findings.map((finding) => ({\n ...finding,\n severity: severityByRuleId.get(finding.ruleId) ?? finding.severity,\n }));\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { EvaluateRulesOptions, Rule, RuleEvaluationResult } from '../../../types/rules.js';
|
|
2
|
+
/*** Evaluate unrelated rules in deterministic identifier order through one generic mechanism. */
|
|
3
|
+
export declare function evaluateRules<TContext>(context: TContext, rules: readonly Rule<TContext>[], options?: EvaluateRulesOptions): RuleEvaluationResult;
|
|
4
|
+
//# sourceMappingURL=evaluateRules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluateRules.d.ts","sourceRoot":"","sources":["../../../../src/features/evaluation/domain/evaluateRules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,IAAI,EAEJ,oBAAoB,EAGrB,MAAM,yBAAyB,CAAC;AAGjC,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,QAAQ,EACpC,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,SAAS,IAAI,CAAC,QAAQ,CAAC,EAAE,EAChC,OAAO,GAAE,oBAAyB,GACjC,oBAAoB,CAWtB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { compareRuleEntityIds } from '../../../utils/compareRuleEntityIds.js';
|
|
2
|
+
/*** Evaluate unrelated rules in deterministic identifier order through one generic mechanism. */
|
|
3
|
+
export function evaluateRules(context, rules, options = {}) {
|
|
4
|
+
const availableCapabilities = new Set(options.capabilities ?? []);
|
|
5
|
+
const orderedRules = [...rules].sort(compareRuleEntityIds);
|
|
6
|
+
const results = orderedRules.map((rule) => evaluateRule(context, rule, availableCapabilities, options));
|
|
7
|
+
return {
|
|
8
|
+
diagnostics: results.flatMap((result) => result.diagnostics),
|
|
9
|
+
findings: results.flatMap((result) => result.findings),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/*** Evaluate one rule only when its declared input capabilities are available. */
|
|
13
|
+
function evaluateRule(context, rule, availableCapabilities, options) {
|
|
14
|
+
const missingCapabilities = (rule.requiredCapabilities ?? []).filter((capability) => !availableCapabilities.has(capability));
|
|
15
|
+
if (missingCapabilities.length > 0) {
|
|
16
|
+
return {
|
|
17
|
+
findings: [],
|
|
18
|
+
diagnostics: missingCapabilities.map((capability) => ({
|
|
19
|
+
code: 'missing-capability',
|
|
20
|
+
ruleId: rule.id,
|
|
21
|
+
message: `Rule "${rule.id}" requires unavailable capability "${capability}".`,
|
|
22
|
+
})),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const ruleOptions = options.optionsByRuleId?.get(rule.id);
|
|
26
|
+
const optionDiagnostics = rule.validateOptions?.(ruleOptions) ?? [];
|
|
27
|
+
if (optionDiagnostics.length > 0) {
|
|
28
|
+
return {
|
|
29
|
+
findings: [],
|
|
30
|
+
diagnostics: optionDiagnostics.map((diagnostic) => ({
|
|
31
|
+
code: 'invalid-options',
|
|
32
|
+
ruleId: rule.id,
|
|
33
|
+
message: `Rule "${rule.id}": ${diagnostic.message}`,
|
|
34
|
+
})),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
diagnostics: [],
|
|
39
|
+
findings: rule
|
|
40
|
+
.evaluate({ context, options: ruleOptions })
|
|
41
|
+
.map((finding) => canonicalizeFinding(finding, rule.id, rule.defaultSeverity)),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/*** Preserve provider evidence while making identifier and severity engine-controlled facts. */
|
|
45
|
+
function canonicalizeFinding(finding, ruleId, severity) {
|
|
46
|
+
return {
|
|
47
|
+
...finding,
|
|
48
|
+
ruleId,
|
|
49
|
+
severity,
|
|
50
|
+
subjects: [...finding.subjects].sort(compareRuleEntityIds),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=evaluateRules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluateRules.js","sourceRoot":"","sources":["../../../../src/features/evaluation/domain/evaluateRules.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,iGAAiG;AACjG,MAAM,UAAU,aAAa,CAC3B,OAAiB,EACjB,KAAgC,EAChC,UAAgC,EAAE;IAElC,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IAClE,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACxC,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAC5D,CAAC;IAEF,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;QAC5D,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;KACvD,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,SAAS,YAAY,CACnB,OAAiB,EACjB,IAAoB,EACpB,qBAA0C,EAC1C,OAA6B;IAK7B,MAAM,mBAAmB,GAAG,CAAC,IAAI,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,MAAM,CAClE,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,CACvD,CAAC;IACF,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,QAAQ,EAAE,EAAE;YACZ,WAAW,EAAE,mBAAmB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;gBACpD,IAAI,EAAE,oBAAoB;gBAC1B,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,OAAO,EAAE,SAAS,IAAI,CAAC,EAAE,sCAAsC,UAAU,IAAI;aAC9E,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1D,MAAM,iBAAiB,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IACpE,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,OAAO;YACL,QAAQ,EAAE,EAAE;YACZ,WAAW,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;gBAClD,IAAI,EAAE,iBAAiB;gBACvB,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,OAAO,EAAE,SAAS,IAAI,CAAC,EAAE,MAAM,UAAU,CAAC,OAAO,EAAE;aACpD,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,IAAI;aACX,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;aAC3C,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;KACjF,CAAC;AACJ,CAAC;AAED,gGAAgG;AAChG,SAAS,mBAAmB,CAC1B,OAAoB,EACpB,MAAc,EACd,QAAsB;IAEtB,OAAO;QACL,GAAG,OAAO;QACV,MAAM;QACN,QAAQ;QACR,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC;KAC3D,CAAC;AACJ,CAAC","sourcesContent":["import type {\n EvaluateRulesOptions,\n Rule,\n RuleEvaluationDiagnostic,\n RuleEvaluationResult,\n RuleFinding,\n RuleSeverity,\n} from '../../../types/rules.js';\nimport { compareRuleEntityIds } from '../../../utils/compareRuleEntityIds.js';\n\n/*** Evaluate unrelated rules in deterministic identifier order through one generic mechanism. */\nexport function evaluateRules<TContext>(\n context: TContext,\n rules: readonly Rule<TContext>[],\n options: EvaluateRulesOptions = {},\n): RuleEvaluationResult {\n const availableCapabilities = new Set(options.capabilities ?? []);\n const orderedRules = [...rules].sort(compareRuleEntityIds);\n const results = orderedRules.map((rule) =>\n evaluateRule(context, rule, availableCapabilities, options),\n );\n\n return {\n diagnostics: results.flatMap((result) => result.diagnostics),\n findings: results.flatMap((result) => result.findings),\n };\n}\n\n/*** Evaluate one rule only when its declared input capabilities are available. */\nfunction evaluateRule<TContext>(\n context: TContext,\n rule: Rule<TContext>,\n availableCapabilities: ReadonlySet<string>,\n options: EvaluateRulesOptions,\n): {\n readonly diagnostics: readonly RuleEvaluationDiagnostic[];\n readonly findings: readonly RuleFinding[];\n} {\n const missingCapabilities = (rule.requiredCapabilities ?? []).filter(\n (capability) => !availableCapabilities.has(capability),\n );\n if (missingCapabilities.length > 0) {\n return {\n findings: [],\n diagnostics: missingCapabilities.map((capability) => ({\n code: 'missing-capability',\n ruleId: rule.id,\n message: `Rule \"${rule.id}\" requires unavailable capability \"${capability}\".`,\n })),\n };\n }\n\n const ruleOptions = options.optionsByRuleId?.get(rule.id);\n const optionDiagnostics = rule.validateOptions?.(ruleOptions) ?? [];\n if (optionDiagnostics.length > 0) {\n return {\n findings: [],\n diagnostics: optionDiagnostics.map((diagnostic) => ({\n code: 'invalid-options',\n ruleId: rule.id,\n message: `Rule \"${rule.id}\": ${diagnostic.message}`,\n })),\n };\n }\n\n return {\n diagnostics: [],\n findings: rule\n .evaluate({ context, options: ruleOptions })\n .map((finding) => canonicalizeFinding(finding, rule.id, rule.defaultSeverity)),\n };\n}\n\n/*** Preserve provider evidence while making identifier and severity engine-controlled facts. */\nfunction canonicalizeFinding(\n finding: RuleFinding,\n ruleId: string,\n severity: RuleSeverity,\n): RuleFinding {\n return {\n ...finding,\n ruleId,\n severity,\n subjects: [...finding.subjects].sort(compareRuleEntityIds),\n };\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RuleEvaluationResult, RulesStatusDescriptor } from '../../../types/rules.js';
|
|
2
|
+
/*** Summarize the complete Rules evaluation result without treating failed evaluation as canonical. */
|
|
3
|
+
export declare function resolveRulesStatus(result: Pick<RuleEvaluationResult, 'diagnostics' | 'findings'>): RulesStatusDescriptor;
|
|
4
|
+
//# sourceMappingURL=resolveRulesStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveRulesStatus.d.ts","sourceRoot":"","sources":["../../../../src/features/evaluation/domain/resolveRulesStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAE3F,uGAAuG;AACvG,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,aAAa,GAAG,UAAU,CAAC,GAC7D,qBAAqB,CAWvB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*** Summarize the complete Rules evaluation result without treating failed evaluation as canonical. */
|
|
2
|
+
export function resolveRulesStatus(result) {
|
|
3
|
+
if (result.diagnostics.length > 0 ||
|
|
4
|
+
result.findings.some((finding) => finding.severity === 'error')) {
|
|
5
|
+
return { status: 'invalid', color: 'red' };
|
|
6
|
+
}
|
|
7
|
+
if (result.findings.some((finding) => finding.severity === 'warning')) {
|
|
8
|
+
return { status: 'warnings', color: 'yellow' };
|
|
9
|
+
}
|
|
10
|
+
return { status: 'canonical', color: 'green' };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=resolveRulesStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveRulesStatus.js","sourceRoot":"","sources":["../../../../src/features/evaluation/domain/resolveRulesStatus.ts"],"names":[],"mappings":"AAEA,uGAAuG;AACvG,MAAM,UAAU,kBAAkB,CAChC,MAA8D;IAE9D,IACE,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QAC7B,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,EAC/D,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACjD,CAAC","sourcesContent":["import type { RuleEvaluationResult, RulesStatusDescriptor } from '../../../types/rules.js';\n\n/*** Summarize the complete Rules evaluation result without treating failed evaluation as canonical. */\nexport function resolveRulesStatus(\n result: Pick<RuleEvaluationResult, 'diagnostics' | 'findings'>,\n): RulesStatusDescriptor {\n if (\n result.diagnostics.length > 0 ||\n result.findings.some((finding) => finding.severity === 'error')\n ) {\n return { status: 'invalid', color: 'red' };\n }\n if (result.findings.some((finding) => finding.severity === 'warning')) {\n return { status: 'warnings', color: 'yellow' };\n }\n return { status: 'canonical', color: 'green' };\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { writeRulesConfigAsync } from './features/configuration/adapters/filesystem/writeRulesConfigAsync.js';
|
|
2
|
+
export { readRulesConfigAsync } from './features/configuration/composition/readRulesConfigAsync.js';
|
|
3
|
+
export { validateRulesConfig } from './features/configuration/domain/validateRulesConfig.js';
|
|
4
|
+
export { createRuleRegistry } from './features/evaluation/domain/createRuleRegistry.js';
|
|
5
|
+
export { evaluateConfiguredRules } from './features/evaluation/domain/evaluateConfiguredRules.js';
|
|
6
|
+
export { evaluateRules } from './features/evaluation/domain/evaluateRules.js';
|
|
7
|
+
export { resolveRulesStatus } from './features/evaluation/domain/resolveRulesStatus.js';
|
|
8
|
+
export type { EvaluateConfiguredRulesOptions, EvaluateRulesOptions, JsonValue, Rule, RuleCapability, RuleEvaluationDiagnostic, RuleEvaluationResult, RuleFinding, RuleOptionDiagnostic, RuleRegistry, RulesConfig, RulesConfigDiagnostic, RulesConfigReadResult, RulesConfigRule, RulesConfigValidationOptions, RulesConfigValidationResult, RuleSet, RuleSeverity, RuleSourceLocation, RulesStatusDescriptor, RuleSubject, } from './types/rules.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uEAAuE,CAAC;AAC9G,OAAO,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AACxF,YAAY,EACV,8BAA8B,EAC9B,oBAAoB,EACpB,SAAS,EACT,IAAI,EACJ,cAAc,EACd,wBAAwB,EACxB,oBAAoB,EACpB,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,4BAA4B,EAC5B,2BAA2B,EAC3B,OAAO,EACP,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,GACZ,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { writeRulesConfigAsync } from './features/configuration/adapters/filesystem/writeRulesConfigAsync.js';
|
|
2
|
+
export { readRulesConfigAsync } from './features/configuration/composition/readRulesConfigAsync.js';
|
|
3
|
+
export { validateRulesConfig } from './features/configuration/domain/validateRulesConfig.js';
|
|
4
|
+
export { createRuleRegistry } from './features/evaluation/domain/createRuleRegistry.js';
|
|
5
|
+
export { evaluateConfiguredRules } from './features/evaluation/domain/evaluateConfiguredRules.js';
|
|
6
|
+
export { evaluateRules } from './features/evaluation/domain/evaluateRules.js';
|
|
7
|
+
export { resolveRulesStatus } from './features/evaluation/domain/resolveRulesStatus.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uEAAuE,CAAC;AAC9G,OAAO,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC","sourcesContent":["export { writeRulesConfigAsync } from './features/configuration/adapters/filesystem/writeRulesConfigAsync.js';\nexport { readRulesConfigAsync } from './features/configuration/composition/readRulesConfigAsync.js';\nexport { validateRulesConfig } from './features/configuration/domain/validateRulesConfig.js';\nexport { createRuleRegistry } from './features/evaluation/domain/createRuleRegistry.js';\nexport { evaluateConfiguredRules } from './features/evaluation/domain/evaluateConfiguredRules.js';\nexport { evaluateRules } from './features/evaluation/domain/evaluateRules.js';\nexport { resolveRulesStatus } from './features/evaluation/domain/resolveRulesStatus.js';\nexport type {\n EvaluateConfiguredRulesOptions,\n EvaluateRulesOptions,\n JsonValue,\n Rule,\n RuleCapability,\n RuleEvaluationDiagnostic,\n RuleEvaluationResult,\n RuleFinding,\n RuleOptionDiagnostic,\n RuleRegistry,\n RulesConfig,\n RulesConfigDiagnostic,\n RulesConfigReadResult,\n RulesConfigRule,\n RulesConfigValidationOptions,\n RulesConfigValidationResult,\n RuleSet,\n RuleSeverity,\n RuleSourceLocation,\n RulesStatusDescriptor,\n RuleSubject,\n} from './types/rules.js';\n"]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*** A JSON value that can be stored in a portable Rules configuration or finding. */
|
|
2
|
+
export type JsonValue = boolean | null | number | string | readonly JsonValue[] | {
|
|
3
|
+
readonly [key: string]: JsonValue;
|
|
4
|
+
};
|
|
5
|
+
/*** A capability that a rule needs from the context supplied by its consumer. */
|
|
6
|
+
export type RuleCapability = string;
|
|
7
|
+
/*** The canonical impact levels used by every Rules provider. */
|
|
8
|
+
export type RuleSeverity = 'error' | 'info' | 'warning';
|
|
9
|
+
/*** An affected semantic subject reported independently of any presentation consumer. */
|
|
10
|
+
export interface RuleSubject {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly kind: string;
|
|
13
|
+
readonly path?: string;
|
|
14
|
+
}
|
|
15
|
+
/*** An optional source location supplied as factual evidence by a provider. */
|
|
16
|
+
export interface RuleSourceLocation {
|
|
17
|
+
readonly column?: number;
|
|
18
|
+
readonly endColumn?: number;
|
|
19
|
+
readonly endLine?: number;
|
|
20
|
+
readonly line: number;
|
|
21
|
+
readonly path: string;
|
|
22
|
+
}
|
|
23
|
+
/*** One serializable, consumer-neutral result produced by a rule. */
|
|
24
|
+
export interface RuleFinding<TEvidence extends JsonValue = JsonValue> {
|
|
25
|
+
readonly evidence: TEvidence;
|
|
26
|
+
readonly message: string;
|
|
27
|
+
readonly ruleId: string;
|
|
28
|
+
readonly severity: RuleSeverity;
|
|
29
|
+
readonly sourceLocation?: RuleSourceLocation;
|
|
30
|
+
readonly subjects: readonly RuleSubject[];
|
|
31
|
+
}
|
|
32
|
+
/*** A validation error returned by a provider for its own serializable options. */
|
|
33
|
+
export interface RuleOptionDiagnostic {
|
|
34
|
+
readonly code: string;
|
|
35
|
+
readonly message: string;
|
|
36
|
+
readonly path?: string;
|
|
37
|
+
}
|
|
38
|
+
/*** A deterministic, provider-owned policy unit evaluated by the generic engine. */
|
|
39
|
+
export interface Rule<TContext = unknown, TOptions extends JsonValue = JsonValue, TEvidence extends JsonValue = JsonValue> {
|
|
40
|
+
readonly defaultSeverity: RuleSeverity;
|
|
41
|
+
evaluate(input: {
|
|
42
|
+
readonly context: TContext;
|
|
43
|
+
readonly options: TOptions | undefined;
|
|
44
|
+
}): readonly RuleFinding<TEvidence>[];
|
|
45
|
+
readonly id: string;
|
|
46
|
+
readonly requiredCapabilities?: readonly RuleCapability[];
|
|
47
|
+
readonly summary: string;
|
|
48
|
+
validateOptions?(options: JsonValue | undefined): readonly RuleOptionDiagnostic[];
|
|
49
|
+
}
|
|
50
|
+
/*** A named collection of independently supplied rules that can compose with other providers. */
|
|
51
|
+
export interface RuleSet<TContext = unknown> {
|
|
52
|
+
readonly id: string;
|
|
53
|
+
readonly rules: readonly Rule<TContext>[];
|
|
54
|
+
}
|
|
55
|
+
/*** A registry that resolves rules without provider discovery or domain-specific branches. */
|
|
56
|
+
export interface RuleRegistry<TContext = unknown> {
|
|
57
|
+
readonly ruleSets: readonly RuleSet<TContext>[];
|
|
58
|
+
readonly rules: readonly Rule<TContext>[];
|
|
59
|
+
readonly ruleById: ReadonlyMap<string, Rule<TContext>>;
|
|
60
|
+
}
|
|
61
|
+
/*** One enabled/disabled rule selection with serializable provider options. */
|
|
62
|
+
export interface RulesConfigRule {
|
|
63
|
+
readonly enabled: boolean;
|
|
64
|
+
readonly id: string;
|
|
65
|
+
readonly options?: JsonValue;
|
|
66
|
+
readonly severity?: RuleSeverity;
|
|
67
|
+
}
|
|
68
|
+
/*** The canonical JSON-only configuration stored in a repository rules.json file. */
|
|
69
|
+
export interface RulesConfig {
|
|
70
|
+
readonly rules: readonly RulesConfigRule[];
|
|
71
|
+
readonly version: 1;
|
|
72
|
+
}
|
|
73
|
+
/*** A portable diagnostic emitted while parsing or applying a Rules configuration. */
|
|
74
|
+
export interface RulesConfigDiagnostic {
|
|
75
|
+
readonly code: 'invalid-config' | 'invalid-options' | 'invalid-rule-id' | 'invalid-severity' | 'missing-capability' | 'unknown-rule';
|
|
76
|
+
readonly message: string;
|
|
77
|
+
readonly path?: string;
|
|
78
|
+
readonly ruleId?: string;
|
|
79
|
+
}
|
|
80
|
+
/*** The result of validating a raw JSON configuration against optional provider knowledge. */
|
|
81
|
+
export interface RulesConfigValidationResult {
|
|
82
|
+
readonly config: RulesConfig | null;
|
|
83
|
+
readonly diagnostics: readonly RulesConfigDiagnostic[];
|
|
84
|
+
}
|
|
85
|
+
/*** Extra facts used to validate configured rule IDs, options, and required capabilities. */
|
|
86
|
+
export interface RulesConfigValidationOptions<TContext = unknown> {
|
|
87
|
+
readonly capabilities?: readonly RuleCapability[];
|
|
88
|
+
readonly registry?: RuleRegistry<TContext>;
|
|
89
|
+
}
|
|
90
|
+
/*** The result of reading a repository rules.json file without hiding parse failures. */
|
|
91
|
+
export interface RulesConfigReadResult {
|
|
92
|
+
readonly config: RulesConfig | null;
|
|
93
|
+
readonly diagnostics: readonly RulesConfigDiagnostic[];
|
|
94
|
+
readonly path: string;
|
|
95
|
+
}
|
|
96
|
+
/*** One execution diagnostic that explains why a configured rule could not run. */
|
|
97
|
+
export interface RuleEvaluationDiagnostic {
|
|
98
|
+
readonly code: 'invalid-config' | 'invalid-options' | 'missing-capability' | 'unknown-rule';
|
|
99
|
+
readonly message: string;
|
|
100
|
+
readonly ruleId: string;
|
|
101
|
+
}
|
|
102
|
+
/*** The deterministic generic result shared by every Rules consumer. */
|
|
103
|
+
export interface RuleEvaluationResult {
|
|
104
|
+
readonly diagnostics: readonly RuleEvaluationDiagnostic[];
|
|
105
|
+
readonly findings: readonly RuleFinding[];
|
|
106
|
+
}
|
|
107
|
+
/*** Direct evaluator inputs that are independent of any repository configuration format. */
|
|
108
|
+
export interface EvaluateRulesOptions {
|
|
109
|
+
readonly capabilities?: readonly RuleCapability[];
|
|
110
|
+
readonly optionsByRuleId?: ReadonlyMap<string, JsonValue | undefined>;
|
|
111
|
+
}
|
|
112
|
+
/*** Configured evaluator inputs that preserve the caller's explicit capability set. */
|
|
113
|
+
export interface EvaluateConfiguredRulesOptions {
|
|
114
|
+
readonly capabilities?: readonly RuleCapability[];
|
|
115
|
+
}
|
|
116
|
+
/*** A stable status summary suitable for consumer-specific presentation. */
|
|
117
|
+
export interface RulesStatusDescriptor {
|
|
118
|
+
readonly color: 'green' | 'red' | 'yellow';
|
|
119
|
+
readonly status: 'canonical' | 'invalid' | 'warnings';
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/types/rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/types/rules.ts"],"names":[],"mappings":"","sourcesContent":["/*** A JSON value that can be stored in a portable Rules configuration or finding. */\nexport type JsonValue =\n boolean | null | number | string | readonly JsonValue[] | { readonly [key: string]: JsonValue };\n\n/*** A capability that a rule needs from the context supplied by its consumer. */\nexport type RuleCapability = string;\n\n/*** The canonical impact levels used by every Rules provider. */\nexport type RuleSeverity = 'error' | 'info' | 'warning';\n\n/*** An affected semantic subject reported independently of any presentation consumer. */\nexport interface RuleSubject {\n readonly id: string;\n readonly kind: string;\n readonly path?: string;\n}\n\n/*** An optional source location supplied as factual evidence by a provider. */\nexport interface RuleSourceLocation {\n readonly column?: number;\n readonly endColumn?: number;\n readonly endLine?: number;\n readonly line: number;\n readonly path: string;\n}\n\n/*** One serializable, consumer-neutral result produced by a rule. */\nexport interface RuleFinding<TEvidence extends JsonValue = JsonValue> {\n readonly evidence: TEvidence;\n readonly message: string;\n readonly ruleId: string;\n readonly severity: RuleSeverity;\n readonly sourceLocation?: RuleSourceLocation;\n readonly subjects: readonly RuleSubject[];\n}\n\n/*** A validation error returned by a provider for its own serializable options. */\nexport interface RuleOptionDiagnostic {\n readonly code: string;\n readonly message: string;\n readonly path?: string;\n}\n\n/*** A deterministic, provider-owned policy unit evaluated by the generic engine. */\nexport interface Rule<\n TContext = unknown,\n TOptions extends JsonValue = JsonValue,\n TEvidence extends JsonValue = JsonValue,\n> {\n readonly defaultSeverity: RuleSeverity;\n evaluate(input: {\n readonly context: TContext;\n readonly options: TOptions | undefined;\n }): readonly RuleFinding<TEvidence>[];\n readonly id: string;\n readonly requiredCapabilities?: readonly RuleCapability[];\n readonly summary: string;\n validateOptions?(options: JsonValue | undefined): readonly RuleOptionDiagnostic[];\n}\n\n/*** A named collection of independently supplied rules that can compose with other providers. */\nexport interface RuleSet<TContext = unknown> {\n readonly id: string;\n readonly rules: readonly Rule<TContext>[];\n}\n\n/*** A registry that resolves rules without provider discovery or domain-specific branches. */\nexport interface RuleRegistry<TContext = unknown> {\n readonly ruleSets: readonly RuleSet<TContext>[];\n readonly rules: readonly Rule<TContext>[];\n readonly ruleById: ReadonlyMap<string, Rule<TContext>>;\n}\n\n/*** One enabled/disabled rule selection with serializable provider options. */\nexport interface RulesConfigRule {\n readonly enabled: boolean;\n readonly id: string;\n readonly options?: JsonValue;\n readonly severity?: RuleSeverity;\n}\n\n/*** The canonical JSON-only configuration stored in a repository rules.json file. */\nexport interface RulesConfig {\n readonly rules: readonly RulesConfigRule[];\n readonly version: 1;\n}\n\n/*** A portable diagnostic emitted while parsing or applying a Rules configuration. */\nexport interface RulesConfigDiagnostic {\n readonly code:\n | 'invalid-config'\n | 'invalid-options'\n | 'invalid-rule-id'\n | 'invalid-severity'\n | 'missing-capability'\n | 'unknown-rule';\n readonly message: string;\n readonly path?: string;\n readonly ruleId?: string;\n}\n\n/*** The result of validating a raw JSON configuration against optional provider knowledge. */\nexport interface RulesConfigValidationResult {\n readonly config: RulesConfig | null;\n readonly diagnostics: readonly RulesConfigDiagnostic[];\n}\n\n/*** Extra facts used to validate configured rule IDs, options, and required capabilities. */\nexport interface RulesConfigValidationOptions<TContext = unknown> {\n readonly capabilities?: readonly RuleCapability[];\n readonly registry?: RuleRegistry<TContext>;\n}\n\n/*** The result of reading a repository rules.json file without hiding parse failures. */\nexport interface RulesConfigReadResult {\n readonly config: RulesConfig | null;\n readonly diagnostics: readonly RulesConfigDiagnostic[];\n readonly path: string;\n}\n\n/*** One execution diagnostic that explains why a configured rule could not run. */\nexport interface RuleEvaluationDiagnostic {\n readonly code: 'invalid-config' | 'invalid-options' | 'missing-capability' | 'unknown-rule';\n readonly message: string;\n readonly ruleId: string;\n}\n\n/*** The deterministic generic result shared by every Rules consumer. */\nexport interface RuleEvaluationResult {\n readonly diagnostics: readonly RuleEvaluationDiagnostic[];\n readonly findings: readonly RuleFinding[];\n}\n\n/*** Direct evaluator inputs that are independent of any repository configuration format. */\nexport interface EvaluateRulesOptions {\n readonly capabilities?: readonly RuleCapability[];\n readonly optionsByRuleId?: ReadonlyMap<string, JsonValue | undefined>;\n}\n\n/*** Configured evaluator inputs that preserve the caller's explicit capability set. */\nexport interface EvaluateConfiguredRulesOptions {\n readonly capabilities?: readonly RuleCapability[];\n}\n\n/*** A stable status summary suitable for consumer-specific presentation. */\nexport interface RulesStatusDescriptor {\n readonly color: 'green' | 'red' | 'yellow';\n readonly status: 'canonical' | 'invalid' | 'warnings';\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/*** Compare Rules-domain entities by identifier using locale-independent code-unit ordering. */
|
|
2
|
+
export declare function compareRuleEntityIds(left: {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
}, right: {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
}): number;
|
|
7
|
+
//# sourceMappingURL=compareRuleEntityIds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compareRuleEntityIds.d.ts","sourceRoot":"","sources":["../../src/utils/compareRuleEntityIds.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,wBAAgB,oBAAoB,CAClC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAC7B,KAAK,EAAE;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B,MAAM,CAIR"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/*** Compare Rules-domain entities by identifier using locale-independent code-unit ordering. */
|
|
2
|
+
export function compareRuleEntityIds(left, right) {
|
|
3
|
+
if (left.id < right.id)
|
|
4
|
+
return -1;
|
|
5
|
+
if (left.id > right.id)
|
|
6
|
+
return 1;
|
|
7
|
+
return 0;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=compareRuleEntityIds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compareRuleEntityIds.js","sourceRoot":"","sources":["../../src/utils/compareRuleEntityIds.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,UAAU,oBAAoB,CAClC,IAA6B,EAC7B,KAA8B;IAE9B,IAAI,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC,CAAC;IAClC,IAAI,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["/*** Compare Rules-domain entities by identifier using locale-independent code-unit ordering. */\nexport function compareRuleEntityIds(\n left: { readonly id: string },\n right: { readonly id: string },\n): number {\n if (left.id < right.id) return -1;\n if (left.id > right.id) return 1;\n return 0;\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ankhorage/rules",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Domain-agnostic rule engine and JSON configuration for Ankhorage.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/ankhorage/rules.git"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/ankhorage/rules#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/ankhorage/rules/issues"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"CHANGELOG.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./cli": {
|
|
33
|
+
"types": "./dist/cli/index.d.ts",
|
|
34
|
+
"import": "./dist/cli/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"bin": {
|
|
39
|
+
"ankhorage-rules": "./dist/cli/standalone.js"
|
|
40
|
+
},
|
|
41
|
+
"ankh": {
|
|
42
|
+
"category": "rules",
|
|
43
|
+
"provider": "./dist/cli/index.js",
|
|
44
|
+
"capabilities": [
|
|
45
|
+
"rules.config.validate"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@ankhorage/ankh": "^0.10.4",
|
|
50
|
+
"@ankhorage/devtools": "^2.0.8",
|
|
51
|
+
"@ankhorage/paradox": "^0.2.6",
|
|
52
|
+
"@types/bun": "^1.4.2",
|
|
53
|
+
"@types/node": "^26.6.2",
|
|
54
|
+
"typescript": "~6.0.3"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@ankhorage/utility": "^1.9.0"
|
|
58
|
+
},
|
|
59
|
+
"packageManager": "bun@1.4.2",
|
|
60
|
+
"keywords": [
|
|
61
|
+
"ankhorage",
|
|
62
|
+
"rules",
|
|
63
|
+
"configuration",
|
|
64
|
+
"evaluation"
|
|
65
|
+
],
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "rm -rf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo && bun x tsc -p tsconfig.build.json",
|
|
68
|
+
"check-types": "bun x tsc --noEmit -p tsconfig.json",
|
|
69
|
+
"typecheck": "bun run check-types",
|
|
70
|
+
"test": "bun test",
|
|
71
|
+
"test:standalone": "bun run build && bun scripts/test-standalone.ts",
|
|
72
|
+
"docs": "bunx @ankhorage/paradox && ankhorage-prettier --write README.md paradox",
|
|
73
|
+
"changeset": "ankhorage-changeset",
|
|
74
|
+
"changeset:status": "ankhorage-changeset status --since=origin/main",
|
|
75
|
+
"version-packages": "ankhorage-changeset version",
|
|
76
|
+
"prepack": "bun run build",
|
|
77
|
+
"lint": "ankhorage-eslint . --max-warnings=0",
|
|
78
|
+
"lint:fix": "ankhorage-eslint . --fix --max-warnings=0",
|
|
79
|
+
"format": "ankhorage-prettier --write .",
|
|
80
|
+
"format:check": "ankhorage-prettier --check .",
|
|
81
|
+
"knip:check": "ankhorage-knip"
|
|
82
|
+
}
|
|
83
|
+
}
|