@gobing-ai/ts-rule-engine 0.3.16 → 0.3.18
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/engine.d.ts.map +1 -1
- package/dist/engine.js +1 -0
- package/dist/evaluators/file-utils.d.ts +14 -1
- package/dist/evaluators/file-utils.d.ts.map +1 -1
- package/dist/evaluators/file-utils.js +20 -3
- package/dist/events.d.ts +8 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/persistence/schema.d.ts +1 -0
- package/dist/persistence/schema.d.ts.map +1 -1
- package/dist/persistence/schema.js +1 -0
- package/package.json +5 -5
- package/src/engine.ts +1 -0
- package/src/evaluators/file-utils.ts +19 -3
- package/src/events.ts +14 -2
- package/src/persistence/schema.ts +1 -0
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAIH,KAAK,oBAAoB,EAE5B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAqB,cAAc,EAAE,GAAG,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGhH,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAC9B,+DAA+D;IAC/D,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,mCAAmC;IACnC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IACpC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,4EAA4E;AAC5E,qBAAa,UAAU;IACnB,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAE9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqC;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;gBAElD,OAAO,GAAE,iBAAsB;IAW3C,wCAAwC;IACxC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,IAAI;IAI/D;;;;;;;OAOG;IACG,QAAQ,CACV,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAC3C,OAAO,CAAC,gBAAgB,CAAC;IAI5B;;;;;;;;;;;;;;;;;;OAkBG;IACG,iBAAiB,CACnB,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,OAAgB,EAC5B,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAC3C,OAAO,CAAC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAIH,KAAK,oBAAoB,EAE5B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAqB,cAAc,EAAE,GAAG,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGhH,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAC9B,+DAA+D;IAC/D,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,mCAAmC;IACnC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IACpC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,4EAA4E;AAC5E,qBAAa,UAAU;IACnB,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAE9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqC;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;gBAElD,OAAO,GAAE,iBAAsB;IAW3C,wCAAwC;IACxC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,IAAI;IAI/D;;;;;;;OAOG;IACG,QAAQ,CACV,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAC3C,OAAO,CAAC,gBAAgB,CAAC;IAI5B;;;;;;;;;;;;;;;;;;OAkBG;IACG,iBAAiB,CACnB,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,OAAgB,EAC5B,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAC3C,OAAO,CAAC,gBAAgB,CAAC;IAmK5B;;;;;;;OAOG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,EAAE,EAAE,MAAM,UAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAG1G"}
|
package/dist/engine.js
CHANGED
|
@@ -64,7 +64,20 @@ export declare function scanFiles(options: ScanFilesOptions): Promise<ScannedFil
|
|
|
64
64
|
export declare function relativeToWorkdir(workdir: string, path: string): string;
|
|
65
65
|
/** Return parent directory for a workdir-relative path. */
|
|
66
66
|
export declare function relativeParent(path: string): string;
|
|
67
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* Return true when a path matches any supplied pattern.
|
|
69
|
+
*
|
|
70
|
+
* Each pattern is matched in two passes, most-specific first:
|
|
71
|
+
* 1. If it contains a glob metachar (`*`), try anchored {@link matchesGlob} —
|
|
72
|
+
* so `packages/**\/*.ts` resolves segment-by-segment instead of collapsing
|
|
73
|
+
* to a bare fragment (the latter silently matched nothing, leaving every
|
|
74
|
+
* glob-scoped loose-mode rule scanning zero files).
|
|
75
|
+
* 2. Otherwise (or if the glob did not match), fall back to the legacy
|
|
76
|
+
* fragment/suffix substring test, where stars are stripped — preserving
|
|
77
|
+
* bare fragments like `.ts`, `src/`, `/tests/` that loose-mode evaluators
|
|
78
|
+
* have always accepted, and keeping unanchored patterns like `*.ts`
|
|
79
|
+
* (→ suffix `.ts`) matching nested paths.
|
|
80
|
+
*/
|
|
68
81
|
export declare function matchesAny(path: string, patterns: string[] | undefined): boolean;
|
|
69
82
|
/**
|
|
70
83
|
* Segment-aware glob matching with `**` (any depth) and `*` (single segment).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/evaluators/file-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,gBAAgB,IAAI,UAAU,EACnC,cAAc,EAIjB,MAAM,uBAAuB,CAAC;AAE/B,yCAAyC;AACzC,MAAM,WAAW,sBAAsB;IACnC,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,0BAA0B;IAC1B,EAAE,CAAC,EAAE,UAAU,CAAC;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,aAAgF,CAAC;AAE9G,qFAAqF;AACrF,wBAAsB,aAAa,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAWtF;AAED,gDAAgD;AAChD,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,iBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnH;AAED,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IACxB,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC5B;AAED,8EAA8E;AAC9E,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC7B,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;;OAQG;IACH,SAAS,EAAE,aAAa,CAAC;IACzB,0BAA0B;IAC1B,EAAE,CAAC,EAAE,UAAU,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAWjF;AAeD,sDAAsD;AACtD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED
|
|
1
|
+
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/evaluators/file-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -55,13 +55,30 @@ export function relativeParent(path) {
|
|
|
55
55
|
const parent = dirnamePath(path);
|
|
56
56
|
return parent === '.' ? '' : parent;
|
|
57
57
|
}
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Return true when a path matches any supplied pattern.
|
|
60
|
+
*
|
|
61
|
+
* Each pattern is matched in two passes, most-specific first:
|
|
62
|
+
* 1. If it contains a glob metachar (`*`), try anchored {@link matchesGlob} —
|
|
63
|
+
* so `packages/**\/*.ts` resolves segment-by-segment instead of collapsing
|
|
64
|
+
* to a bare fragment (the latter silently matched nothing, leaving every
|
|
65
|
+
* glob-scoped loose-mode rule scanning zero files).
|
|
66
|
+
* 2. Otherwise (or if the glob did not match), fall back to the legacy
|
|
67
|
+
* fragment/suffix substring test, where stars are stripped — preserving
|
|
68
|
+
* bare fragments like `.ts`, `src/`, `/tests/` that loose-mode evaluators
|
|
69
|
+
* have always accepted, and keeping unanchored patterns like `*.ts`
|
|
70
|
+
* (→ suffix `.ts`) matching nested paths.
|
|
71
|
+
*/
|
|
59
72
|
export function matchesAny(path, patterns) {
|
|
60
73
|
if (patterns === undefined || patterns.length === 0)
|
|
61
74
|
return true;
|
|
75
|
+
const normalizedPath = path.replaceAll('\\', '/');
|
|
62
76
|
return patterns.some((pattern) => {
|
|
63
|
-
const
|
|
64
|
-
|
|
77
|
+
const normalized = pattern.replaceAll('\\', '/');
|
|
78
|
+
if (normalized.includes('*') && matchesGlob(normalizedPath, normalized))
|
|
79
|
+
return true;
|
|
80
|
+
const clean = normalized.replaceAll('**/', '').replaceAll('*', '');
|
|
81
|
+
return clean.length === 0 || normalizedPath.includes(clean) || normalizedPath.endsWith(clean);
|
|
65
82
|
});
|
|
66
83
|
}
|
|
67
84
|
/**
|
package/dist/events.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ConstraintFinding } from './types';
|
|
1
2
|
/** Typed event map for rule-engine run observability. All events prefixed `rule.`. */
|
|
2
3
|
export type RuleEngineEvents = {
|
|
3
4
|
/** Emitted before the first rule is evaluated. */
|
|
@@ -11,11 +12,17 @@ export type RuleEngineEvents = {
|
|
|
11
12
|
index: number;
|
|
12
13
|
total: number;
|
|
13
14
|
}) => void;
|
|
14
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Emitted after a single rule evaluation finishes successfully.
|
|
17
|
+
* `findings` is the count; `details` carries the actual finding objects so
|
|
18
|
+
* progress subscribers can render per-rule detail inline without waiting
|
|
19
|
+
* for the aggregate result.
|
|
20
|
+
*/
|
|
15
21
|
'rule.eval.done': (data: {
|
|
16
22
|
ruleId: string;
|
|
17
23
|
findings: number;
|
|
18
24
|
durationMs: number;
|
|
25
|
+
details: ConstraintFinding[];
|
|
19
26
|
}) => void;
|
|
20
27
|
/** Emitted when a rule evaluator throws (in addition to the `kind:'error'` finding). */
|
|
21
28
|
'rule.eval.error': (data: {
|
package/dist/events.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,kDAAkD;IAClD,gBAAgB,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnE,uEAAuE;IACvE,iBAAiB,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACpF
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,kDAAkD;IAClD,gBAAgB,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnE,uEAAuE;IACvE,iBAAiB,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACpF;;;;;OAKG;IACH,gBAAgB,EAAE,CAAC,IAAI,EAAE;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,iBAAiB,EAAE,CAAC;KAChC,KAAK,IAAI,CAAC;IACX,wFAAwF;IACxF,iBAAiB,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrE,qEAAqE;IACrE,eAAe,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CACnH,CAAC"}
|
|
@@ -7,5 +7,6 @@
|
|
|
7
7
|
* unit. Timestamps are TEXT (ISO 8601) for portability across SQLite drivers
|
|
8
8
|
* including D1.
|
|
9
9
|
*/
|
|
10
|
+
/** DDL for the rule-engine persistence tables (`rule_runs`, `rule_eval_runs`). */
|
|
10
11
|
export declare const RULE_ENGINE_SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS rule_runs (\n id TEXT PRIMARY KEY,\n preset TEXT,\n source_kind TEXT NOT NULL,\n source_value TEXT,\n status TEXT NOT NULL DEFAULT 'running',\n rule_count INTEGER NOT NULL DEFAULT 0,\n finding_count INTEGER NOT NULL DEFAULT 0,\n fix_count INTEGER NOT NULL DEFAULT 0,\n applied_fix_count INTEGER NOT NULL DEFAULT 0,\n fail_on TEXT,\n stop_on_first TEXT,\n fix_mode TEXT NOT NULL DEFAULT 'none',\n dry_run INTEGER NOT NULL DEFAULT 0,\n started_at TEXT NOT NULL,\n completed_at TEXT,\n duration_ms INTEGER,\n metadata_json TEXT NOT NULL DEFAULT '{}',\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS rule_eval_runs (\n id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL REFERENCES rule_runs(id),\n rule_id TEXT NOT NULL,\n severity TEXT NOT NULL,\n evaluator TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'running',\n finding_count INTEGER NOT NULL DEFAULT 0,\n fix_count INTEGER NOT NULL DEFAULT 0,\n duration_ms INTEGER,\n error TEXT,\n findings_json TEXT,\n fixes_json TEXT,\n started_at TEXT NOT NULL,\n completed_at TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_rule_eval_runs_run_id ON rule_eval_runs (run_id);\n";
|
|
11
12
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/persistence/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,sBAAsB,4zCA2ClC,CAAC"}
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/persistence/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,kFAAkF;AAClF,eAAO,MAAM,sBAAsB,4zCA2ClC,CAAC"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* unit. Timestamps are TEXT (ISO 8601) for portability across SQLite drivers
|
|
8
8
|
* including D1.
|
|
9
9
|
*/
|
|
10
|
+
/** DDL for the rule-engine persistence tables (`rule_runs`, `rule_eval_runs`). */
|
|
10
11
|
export const RULE_ENGINE_SCHEMA_SQL = `
|
|
11
12
|
CREATE TABLE IF NOT EXISTS rule_runs (
|
|
12
13
|
id TEXT PRIMARY KEY,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/ts-rule-engine",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.18",
|
|
4
4
|
"description": "@gobing-ai/ts-rule-engine — Constraint rule schemas, loading, evaluation, and result formatting.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
"release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-rule-engine-v<version> && git push --tags' && exit 1"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@gobing-ai/ts-ai-runner": "^0.3.
|
|
53
|
-
"@gobing-ai/ts-infra": "^0.3.
|
|
54
|
-
"@gobing-ai/ts-runtime": "^0.3.
|
|
55
|
-
"@gobing-ai/ts-db": "^0.3.
|
|
52
|
+
"@gobing-ai/ts-ai-runner": "^0.3.18",
|
|
53
|
+
"@gobing-ai/ts-infra": "^0.3.18",
|
|
54
|
+
"@gobing-ai/ts-runtime": "^0.3.18",
|
|
55
|
+
"@gobing-ai/ts-db": "^0.3.18",
|
|
56
56
|
"yaml": "^2.7.0",
|
|
57
57
|
"zod": "^4.1.0"
|
|
58
58
|
},
|
package/src/engine.ts
CHANGED
|
@@ -124,12 +124,28 @@ export function relativeParent(path: string): string {
|
|
|
124
124
|
return parent === '.' ? '' : parent;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* Return true when a path matches any supplied pattern.
|
|
129
|
+
*
|
|
130
|
+
* Each pattern is matched in two passes, most-specific first:
|
|
131
|
+
* 1. If it contains a glob metachar (`*`), try anchored {@link matchesGlob} —
|
|
132
|
+
* so `packages/**\/*.ts` resolves segment-by-segment instead of collapsing
|
|
133
|
+
* to a bare fragment (the latter silently matched nothing, leaving every
|
|
134
|
+
* glob-scoped loose-mode rule scanning zero files).
|
|
135
|
+
* 2. Otherwise (or if the glob did not match), fall back to the legacy
|
|
136
|
+
* fragment/suffix substring test, where stars are stripped — preserving
|
|
137
|
+
* bare fragments like `.ts`, `src/`, `/tests/` that loose-mode evaluators
|
|
138
|
+
* have always accepted, and keeping unanchored patterns like `*.ts`
|
|
139
|
+
* (→ suffix `.ts`) matching nested paths.
|
|
140
|
+
*/
|
|
128
141
|
export function matchesAny(path: string, patterns: string[] | undefined): boolean {
|
|
129
142
|
if (patterns === undefined || patterns.length === 0) return true;
|
|
143
|
+
const normalizedPath = path.replaceAll('\\', '/');
|
|
130
144
|
return patterns.some((pattern) => {
|
|
131
|
-
const
|
|
132
|
-
|
|
145
|
+
const normalized = pattern.replaceAll('\\', '/');
|
|
146
|
+
if (normalized.includes('*') && matchesGlob(normalizedPath, normalized)) return true;
|
|
147
|
+
const clean = normalized.replaceAll('**/', '').replaceAll('*', '');
|
|
148
|
+
return clean.length === 0 || normalizedPath.includes(clean) || normalizedPath.endsWith(clean);
|
|
133
149
|
});
|
|
134
150
|
}
|
|
135
151
|
|
package/src/events.ts
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
+
import type { ConstraintFinding } from './types';
|
|
2
|
+
|
|
1
3
|
/** Typed event map for rule-engine run observability. All events prefixed `rule.`. */
|
|
2
4
|
export type RuleEngineEvents = {
|
|
3
5
|
/** Emitted before the first rule is evaluated. */
|
|
4
6
|
'rule.run.start': (data: { rules: number; total: number }) => void;
|
|
5
7
|
/** Emitted immediately before a single rule's evaluator is invoked. */
|
|
6
8
|
'rule.eval.start': (data: { ruleId: string; index: number; total: number }) => void;
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Emitted after a single rule evaluation finishes successfully.
|
|
11
|
+
* `findings` is the count; `details` carries the actual finding objects so
|
|
12
|
+
* progress subscribers can render per-rule detail inline without waiting
|
|
13
|
+
* for the aggregate result.
|
|
14
|
+
*/
|
|
15
|
+
'rule.eval.done': (data: {
|
|
16
|
+
ruleId: string;
|
|
17
|
+
findings: number;
|
|
18
|
+
durationMs: number;
|
|
19
|
+
details: ConstraintFinding[];
|
|
20
|
+
}) => void;
|
|
9
21
|
/** Emitted when a rule evaluator throws (in addition to the `kind:'error'` finding). */
|
|
10
22
|
'rule.eval.error': (data: { ruleId: string; error: string }) => void;
|
|
11
23
|
/** Emitted after the last rule finishes (or was short-circuited). */
|