@harness-engineering/eslint-plugin 0.1.1 → 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.
Files changed (62) hide show
  1. package/README.md +8 -0
  2. package/dist/index.d.ts +113 -23
  3. package/dist/index.js +929 -43
  4. package/package.json +8 -7
  5. package/dist/configs/index.d.ts +0 -5
  6. package/dist/configs/index.d.ts.map +0 -1
  7. package/dist/configs/index.js +0 -8
  8. package/dist/configs/index.js.map +0 -1
  9. package/dist/configs/recommended.d.ts +0 -4
  10. package/dist/configs/recommended.d.ts.map +0 -1
  11. package/dist/configs/recommended.js +0 -16
  12. package/dist/configs/recommended.js.map +0 -1
  13. package/dist/configs/strict.d.ts +0 -4
  14. package/dist/configs/strict.d.ts.map +0 -1
  15. package/dist/configs/strict.js +0 -16
  16. package/dist/configs/strict.js.map +0 -1
  17. package/dist/index.d.ts.map +0 -1
  18. package/dist/index.js.map +0 -1
  19. package/dist/rules/enforce-doc-exports.d.ts +0 -12
  20. package/dist/rules/enforce-doc-exports.d.ts.map +0 -1
  21. package/dist/rules/enforce-doc-exports.js +0 -78
  22. package/dist/rules/enforce-doc-exports.js.map +0 -1
  23. package/dist/rules/index.d.ts +0 -21
  24. package/dist/rules/index.d.ts.map +0 -1
  25. package/dist/rules/index.js +0 -14
  26. package/dist/rules/index.js.map +0 -1
  27. package/dist/rules/no-circular-deps.d.ts +0 -20
  28. package/dist/rules/no-circular-deps.d.ts.map +0 -1
  29. package/dist/rules/no-circular-deps.js +0 -110
  30. package/dist/rules/no-circular-deps.js.map +0 -1
  31. package/dist/rules/no-forbidden-imports.d.ts +0 -6
  32. package/dist/rules/no-forbidden-imports.d.ts.map +0 -1
  33. package/dist/rules/no-forbidden-imports.js +0 -58
  34. package/dist/rules/no-forbidden-imports.js.map +0 -1
  35. package/dist/rules/no-layer-violation.d.ts +0 -6
  36. package/dist/rules/no-layer-violation.d.ts.map +0 -1
  37. package/dist/rules/no-layer-violation.js +0 -62
  38. package/dist/rules/no-layer-violation.js.map +0 -1
  39. package/dist/rules/require-boundary-schema.d.ts +0 -6
  40. package/dist/rules/require-boundary-schema.d.ts.map +0 -1
  41. package/dist/rules/require-boundary-schema.js +0 -53
  42. package/dist/rules/require-boundary-schema.js.map +0 -1
  43. package/dist/utils/ast-helpers.d.ts +0 -14
  44. package/dist/utils/ast-helpers.d.ts.map +0 -1
  45. package/dist/utils/ast-helpers.js +0 -94
  46. package/dist/utils/ast-helpers.js.map +0 -1
  47. package/dist/utils/config-loader.d.ts +0 -10
  48. package/dist/utils/config-loader.d.ts.map +0 -1
  49. package/dist/utils/config-loader.js +0 -56
  50. package/dist/utils/config-loader.js.map +0 -1
  51. package/dist/utils/index.d.ts +0 -5
  52. package/dist/utils/index.d.ts.map +0 -1
  53. package/dist/utils/index.js +0 -6
  54. package/dist/utils/index.js.map +0 -1
  55. package/dist/utils/path-utils.d.ts +0 -24
  56. package/dist/utils/path-utils.d.ts.map +0 -1
  57. package/dist/utils/path-utils.js +0 -62
  58. package/dist/utils/path-utils.js.map +0 -1
  59. package/dist/utils/schema.d.ts +0 -117
  60. package/dist/utils/schema.d.ts.map +0 -1
  61. package/dist/utils/schema.js +0 -34
  62. package/dist/utils/schema.js.map +0 -1
@@ -1,53 +0,0 @@
1
- // src/rules/require-boundary-schema.ts
2
- import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
3
- import { getConfig } from '../utils/config-loader';
4
- import { matchesPattern, normalizePath } from '../utils/path-utils';
5
- import { hasZodValidation } from '../utils/ast-helpers';
6
- const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/harness-engineering/eslint-plugin/blob/main/docs/rules/${name}.md`);
7
- export default createRule({
8
- name: 'require-boundary-schema',
9
- meta: {
10
- type: 'problem',
11
- docs: {
12
- description: 'Require Zod schema validation at API boundaries',
13
- },
14
- messages: {
15
- missingSchema: 'Exported function "{{name}}" at API boundary must validate input with Zod schema',
16
- },
17
- schema: [],
18
- },
19
- defaultOptions: [],
20
- create(context) {
21
- const config = getConfig(context.filename);
22
- if (!config?.boundaries?.requireSchema?.length) {
23
- return {}; // No-op if no boundaries configured
24
- }
25
- const filePath = normalizePath(context.filename);
26
- // Check if file matches any boundary pattern
27
- const isBoundaryFile = config.boundaries.requireSchema.some((pattern) => matchesPattern(filePath, pattern));
28
- if (!isBoundaryFile) {
29
- return {}; // Not a boundary file
30
- }
31
- return {
32
- ExportNamedDeclaration(node) {
33
- const decl = node.declaration;
34
- // Only check function declarations
35
- if (!decl || decl.type !== AST_NODE_TYPES.FunctionDeclaration) {
36
- return;
37
- }
38
- const fn = decl;
39
- if (!fn.id || !fn.body)
40
- return;
41
- // Check if function has Zod validation
42
- if (!hasZodValidation(fn.body)) {
43
- context.report({
44
- node: fn,
45
- messageId: 'missingSchema',
46
- data: { name: fn.id.name },
47
- });
48
- }
49
- },
50
- };
51
- },
52
- });
53
- //# sourceMappingURL=require-boundary-schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"require-boundary-schema.js","sourceRoot":"","sources":["../../src/rules/require-boundary-schema.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAiB,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CACxC,CAAC,IAAI,EAAE,EAAE,CAAC,6EAA6E,IAAI,KAAK,CACjG,CAAC;AAIF,eAAe,UAAU,CAAiB;IACxC,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,iDAAiD;SAC/D;QACD,QAAQ,EAAE;YACR,aAAa,EACX,kFAAkF;SACrF;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;YAC/C,OAAO,EAAE,CAAC,CAAC,oCAAoC;QACjD,CAAC;QAED,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEjD,6CAA6C;QAC7C,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CACtE,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAClC,CAAC;QAEF,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO,EAAE,CAAC,CAAC,sBAAsB;QACnC,CAAC;QAED,OAAO;YACL,sBAAsB,CAAC,IAAqC;gBAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;gBAE9B,mCAAmC;gBACnC,IAAI,CAAC,IAAI,IAAK,IAAI,CAAC,IAAuB,KAAK,cAAc,CAAC,mBAAmB,EAAE,CAAC;oBAClF,OAAO;gBACT,CAAC;gBAED,MAAM,EAAE,GAAG,IAAoC,CAAC;gBAChD,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI;oBAAE,OAAO;gBAE/B,uCAAuC;gBACvC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/B,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,EAAE;wBACR,SAAS,EAAE,eAAe;wBAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE;qBAC3B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -1,14 +0,0 @@
1
- import { type TSESTree } from '@typescript-eslint/utils';
2
- /**
3
- * Check if a node has a preceding JSDoc comment
4
- */
5
- export declare function hasJSDocComment(node: TSESTree.Node, sourceCode: string): boolean;
6
- /**
7
- * Check if a function body contains Zod validation (.parse or .safeParse)
8
- */
9
- export declare function hasZodValidation(body: TSESTree.BlockStatement): boolean;
10
- /**
11
- * Check if a node is marked with @internal
12
- */
13
- export declare function isMarkedInternal(node: TSESTree.Node, sourceCode: string): boolean;
14
- //# sourceMappingURL=ast-helpers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ast-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/ast-helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzE;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CA+BhF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,cAAc,GAAG,OAAO,CA+CvE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAYjF"}
@@ -1,94 +0,0 @@
1
- // src/utils/ast-helpers.ts
2
- import { AST_NODE_TYPES } from '@typescript-eslint/utils';
3
- /**
4
- * Check if a node has a preceding JSDoc comment
5
- */
6
- export function hasJSDocComment(node, sourceCode) {
7
- if (!node.range)
8
- return false;
9
- // Get text before the node
10
- const textBefore = sourceCode.slice(0, node.range[0]);
11
- const lines = textBefore.split('\n');
12
- // Look backwards for /** ... */
13
- let foundJSDoc = false;
14
- for (let i = lines.length - 1; i >= 0; i--) {
15
- const line = lines[i]?.trim() ?? '';
16
- // Empty line or whitespace - keep looking
17
- if (line === '')
18
- continue;
19
- // Found JSDoc end
20
- if (line.endsWith('*/')) {
21
- // Check if it's JSDoc (starts with /**)
22
- const startIdx = textBefore.lastIndexOf('/**');
23
- const endIdx = textBefore.lastIndexOf('*/');
24
- if (startIdx !== -1 && endIdx > startIdx) {
25
- foundJSDoc = true;
26
- }
27
- break;
28
- }
29
- // Found something else - no JSDoc
30
- break;
31
- }
32
- return foundJSDoc;
33
- }
34
- /**
35
- * Check if a function body contains Zod validation (.parse or .safeParse)
36
- */
37
- export function hasZodValidation(body) {
38
- let found = false;
39
- // Keys to skip to avoid circular references
40
- const skipKeys = new Set(['parent', 'loc', 'range', 'tokens', 'comments']);
41
- function visit(node) {
42
- if (found)
43
- return;
44
- if (node.type === AST_NODE_TYPES.CallExpression &&
45
- node.callee.type ===
46
- AST_NODE_TYPES.MemberExpression) {
47
- const prop = node.callee.property;
48
- const propType = prop.type;
49
- if (propType === AST_NODE_TYPES.Identifier &&
50
- (prop.name === 'parse' ||
51
- prop.name === 'safeParse')) {
52
- found = true;
53
- return;
54
- }
55
- }
56
- // Recursively visit children
57
- for (const key of Object.keys(node)) {
58
- if (skipKeys.has(key))
59
- continue;
60
- const value = node[key];
61
- if (value && typeof value === 'object') {
62
- if (Array.isArray(value)) {
63
- for (const item of value) {
64
- if (item && typeof item === 'object' && 'type' in item) {
65
- visit(item);
66
- }
67
- }
68
- }
69
- else if ('type' in value) {
70
- visit(value);
71
- }
72
- }
73
- }
74
- }
75
- visit(body);
76
- return found;
77
- }
78
- /**
79
- * Check if a node is marked with @internal
80
- */
81
- export function isMarkedInternal(node, sourceCode) {
82
- if (!node.range)
83
- return false;
84
- const textBefore = sourceCode.slice(0, node.range[0]);
85
- const lastComment = textBefore.lastIndexOf('/**');
86
- if (lastComment === -1)
87
- return false;
88
- const commentEnd = textBefore.lastIndexOf('*/');
89
- if (commentEnd === -1 || commentEnd < lastComment)
90
- return false;
91
- const comment = textBefore.slice(lastComment, commentEnd + 2);
92
- return comment.includes('@internal');
93
- }
94
- //# sourceMappingURL=ast-helpers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ast-helpers.js","sourceRoot":"","sources":["../../src/utils/ast-helpers.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,OAAO,EAAE,cAAc,EAAiB,MAAM,0BAA0B,CAAC;AAEzE;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAmB,EAAE,UAAkB;IACrE,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAE9B,2BAA2B;IAC3B,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAErC,gCAAgC;IAChC,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAEpC,0CAA0C;QAC1C,IAAI,IAAI,KAAK,EAAE;YAAE,SAAS;QAE1B,kBAAkB;QAClB,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,wCAAwC;YACxC,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;gBACzC,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;YACD,MAAM;QACR,CAAC;QAED,kCAAkC;QAClC,MAAM;IACR,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAA6B;IAC5D,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;IAE3E,SAAS,KAAK,CAAC,IAAmB;QAChC,IAAI,KAAK;YAAE,OAAO;QAElB,IACG,IAAI,CAAC,IAAuB,KAAK,cAAc,CAAC,cAAc;YAC7D,IAAgC,CAAC,MAAM,CAAC,IAAuB;gBAC/D,cAAc,CAAC,gBAAgB,EACjC,CAAC;YACD,MAAM,IAAI,GAAK,IAAgC,CAAC,MAAoC,CAAC,QAAQ,CAAC;YAC9F,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAsB,CAAC;YAC7C,IACE,QAAQ,KAAK,cAAc,CAAC,UAAU;gBACtC,CAAE,IAA4B,CAAC,IAAI,KAAK,OAAO;oBAC5C,IAA4B,CAAC,IAAI,KAAK,WAAW,CAAC,EACrD,CAAC;gBACD,KAAK,GAAG,IAAI,CAAC;gBACb,OAAO;YACT,CAAC;QACH,CAAC;QAED,6BAA6B;QAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAEhC,MAAM,KAAK,GAAI,IAA2C,CAAC,GAAG,CAAC,CAAC;YAChE,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;wBACzB,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;4BACvD,KAAK,CAAC,IAAqB,CAAC,CAAC;wBAC/B,CAAC;oBACH,CAAC;gBACH,CAAC;qBAAM,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;oBAC3B,KAAK,CAAC,KAAsB,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAmB,EAAE,UAAkB;IACtE,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAE9B,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,WAAW,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAErC,MAAM,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,UAAU,GAAG,WAAW;QAAE,OAAO,KAAK,CAAC;IAEhE,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;IAC9D,OAAO,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACvC,CAAC"}
@@ -1,10 +0,0 @@
1
- import { type HarnessConfig } from './schema';
2
- /**
3
- * Load and validate config, with caching
4
- */
5
- export declare function getConfig(filePath: string): HarnessConfig | null;
6
- /**
7
- * Clear the config cache (for testing)
8
- */
9
- export declare function clearConfigCache(): void;
10
- //# sourceMappingURL=config-loader.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAwBnE;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAuBhE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC"}
@@ -1,56 +0,0 @@
1
- // src/utils/config-loader.ts
2
- import * as fs from 'fs';
3
- import * as path from 'path';
4
- import { HarnessConfigSchema } from './schema';
5
- const CONFIG_FILENAME = 'harness.config.json';
6
- let cachedConfig = null;
7
- let cachedConfigPath = null;
8
- /**
9
- * Find harness.config.json by walking up from the given directory
10
- */
11
- function findConfigFile(startDir) {
12
- let currentDir = path.resolve(startDir);
13
- const root = path.parse(currentDir).root;
14
- while (currentDir !== root) {
15
- const configPath = path.join(currentDir, CONFIG_FILENAME);
16
- if (fs.existsSync(configPath)) {
17
- return configPath;
18
- }
19
- currentDir = path.dirname(currentDir);
20
- }
21
- return null;
22
- }
23
- /**
24
- * Load and validate config, with caching
25
- */
26
- export function getConfig(filePath) {
27
- const configPath = findConfigFile(path.dirname(filePath));
28
- if (!configPath) {
29
- return null;
30
- }
31
- // Return cached config if same path
32
- if (cachedConfigPath === configPath && cachedConfig) {
33
- return cachedConfig;
34
- }
35
- try {
36
- const content = fs.readFileSync(configPath, 'utf-8');
37
- const parsed = HarnessConfigSchema.safeParse(JSON.parse(content));
38
- if (!parsed.success) {
39
- return null;
40
- }
41
- cachedConfig = parsed.data;
42
- cachedConfigPath = configPath;
43
- return cachedConfig;
44
- }
45
- catch {
46
- return null;
47
- }
48
- }
49
- /**
50
- * Clear the config cache (for testing)
51
- */
52
- export function clearConfigCache() {
53
- cachedConfig = null;
54
- cachedConfigPath = null;
55
- }
56
- //# sourceMappingURL=config-loader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAsB,MAAM,UAAU,CAAC;AAEnE,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,IAAI,YAAY,GAAyB,IAAI,CAAC;AAC9C,IAAI,gBAAgB,GAAkB,IAAI,CAAC;AAE3C;;GAEG;AACH,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;IAEzC,OAAO,UAAU,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAC1D,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oCAAoC;IACpC,IAAI,gBAAgB,KAAK,UAAU,IAAI,YAAY,EAAE,CAAC;QACpD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;QAC3B,gBAAgB,GAAG,UAAU,CAAC;QAC9B,OAAO,YAAY,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,YAAY,GAAG,IAAI,CAAC;IACpB,gBAAgB,GAAG,IAAI,CAAC;AAC1B,CAAC"}
@@ -1,5 +0,0 @@
1
- export * from './schema';
2
- export * from './config-loader';
3
- export * from './path-utils';
4
- export * from './ast-helpers';
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
@@ -1,6 +0,0 @@
1
- // src/utils/index.ts
2
- export * from './schema';
3
- export * from './config-loader';
4
- export * from './path-utils';
5
- export * from './ast-helpers';
6
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
@@ -1,24 +0,0 @@
1
- import type { Layer } from './schema';
2
- /**
3
- * Resolve an import path relative to the importing file
4
- * Returns path relative to project root (assumes /project/ prefix)
5
- */
6
- export declare function resolveImportPath(importPath: string, importingFile: string): string;
7
- /**
8
- * Check if a file path matches a glob pattern
9
- */
10
- export declare function matchesPattern(filePath: string, pattern: string): boolean;
11
- /**
12
- * Find which layer a file belongs to
13
- */
14
- export declare function getLayerForFile(filePath: string, layers: Layer[]): string | null;
15
- /**
16
- * Get layer definition by name
17
- */
18
- export declare function getLayerByName(name: string, layers: Layer[]): Layer | undefined;
19
- /**
20
- * Normalize a file path to project-relative format
21
- * Extracts path from /any/path/src/... to src/...
22
- */
23
- export declare function normalizePath(filePath: string): string;
24
- //# sourceMappingURL=path-utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAmBnF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAMzE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,GAAG,IAAI,CAOhF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,SAAS,CAE/E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMtD"}
@@ -1,62 +0,0 @@
1
- // src/utils/path-utils.ts
2
- import * as path from 'path';
3
- import { minimatch } from 'minimatch';
4
- /**
5
- * Resolve an import path relative to the importing file
6
- * Returns path relative to project root (assumes /project/ prefix)
7
- */
8
- export function resolveImportPath(importPath, importingFile) {
9
- // External/absolute imports stay as-is
10
- if (!importPath.startsWith('.')) {
11
- return importPath;
12
- }
13
- // Resolve relative to importing file's directory
14
- const importingDir = path.dirname(importingFile);
15
- const resolved = path.resolve(importingDir, importPath);
16
- // Extract path relative to project root
17
- // Assumes paths like /project/src/... or /path/to/project/src/...
18
- const srcIndex = resolved.indexOf('/src/');
19
- if (srcIndex !== -1) {
20
- return resolved.slice(srcIndex + 1); // Remove leading /
21
- }
22
- // Fallback: return as-is if no src/ found
23
- return importPath;
24
- }
25
- /**
26
- * Check if a file path matches a glob pattern
27
- */
28
- export function matchesPattern(filePath, pattern) {
29
- // Normalize path separators
30
- const normalizedPath = filePath.replace(/\\/g, '/');
31
- const normalizedPattern = pattern.replace(/\\/g, '/');
32
- return minimatch(normalizedPath, normalizedPattern, { matchBase: false });
33
- }
34
- /**
35
- * Find which layer a file belongs to
36
- */
37
- export function getLayerForFile(filePath, layers) {
38
- for (const layer of layers) {
39
- if (matchesPattern(filePath, layer.pattern)) {
40
- return layer.name;
41
- }
42
- }
43
- return null;
44
- }
45
- /**
46
- * Get layer definition by name
47
- */
48
- export function getLayerByName(name, layers) {
49
- return layers.find((l) => l.name === name);
50
- }
51
- /**
52
- * Normalize a file path to project-relative format
53
- * Extracts path from /any/path/src/... to src/...
54
- */
55
- export function normalizePath(filePath) {
56
- const srcIndex = filePath.indexOf('/src/');
57
- if (srcIndex !== -1) {
58
- return filePath.slice(srcIndex + 1);
59
- }
60
- return filePath;
61
- }
62
- //# sourceMappingURL=path-utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,aAAqB;IACzE,uCAAuC;IACvC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,iDAAiD;IACjD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAExD,wCAAwC;IACxC,kEAAkE;IAClE,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB;IAC1D,CAAC;IAED,0CAA0C;IAC1C,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAe;IAC9D,4BAA4B;IAC5B,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEtD,OAAO,SAAS,CAAC,cAAc,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,MAAe;IAC/D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,MAAe;IAC1D,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -1,117 +0,0 @@
1
- import { z } from 'zod';
2
- /**
3
- * Layer definition for architectural boundaries
4
- */
5
- export declare const LayerSchema: z.ZodObject<{
6
- name: z.ZodString;
7
- pattern: z.ZodString;
8
- allowedDependencies: z.ZodArray<z.ZodString, "many">;
9
- }, "strip", z.ZodTypeAny, {
10
- name: string;
11
- pattern: string;
12
- allowedDependencies: string[];
13
- }, {
14
- name: string;
15
- pattern: string;
16
- allowedDependencies: string[];
17
- }>;
18
- /**
19
- * Forbidden import rule
20
- */
21
- export declare const ForbiddenImportSchema: z.ZodObject<{
22
- from: z.ZodString;
23
- disallow: z.ZodArray<z.ZodString, "many">;
24
- message: z.ZodOptional<z.ZodString>;
25
- }, "strip", z.ZodTypeAny, {
26
- from: string;
27
- disallow: string[];
28
- message?: string | undefined;
29
- }, {
30
- from: string;
31
- disallow: string[];
32
- message?: string | undefined;
33
- }>;
34
- /**
35
- * Boundary validation config
36
- */
37
- export declare const BoundaryConfigSchema: z.ZodObject<{
38
- requireSchema: z.ZodArray<z.ZodString, "many">;
39
- }, "strip", z.ZodTypeAny, {
40
- requireSchema: string[];
41
- }, {
42
- requireSchema: string[];
43
- }>;
44
- /**
45
- * Complete harness.config.json schema
46
- * Duplicated from @harness-engineering/cli to avoid circular dependency
47
- */
48
- export declare const HarnessConfigSchema: z.ZodObject<{
49
- version: z.ZodLiteral<1>;
50
- layers: z.ZodOptional<z.ZodArray<z.ZodObject<{
51
- name: z.ZodString;
52
- pattern: z.ZodString;
53
- allowedDependencies: z.ZodArray<z.ZodString, "many">;
54
- }, "strip", z.ZodTypeAny, {
55
- name: string;
56
- pattern: string;
57
- allowedDependencies: string[];
58
- }, {
59
- name: string;
60
- pattern: string;
61
- allowedDependencies: string[];
62
- }>, "many">>;
63
- forbiddenImports: z.ZodOptional<z.ZodArray<z.ZodObject<{
64
- from: z.ZodString;
65
- disallow: z.ZodArray<z.ZodString, "many">;
66
- message: z.ZodOptional<z.ZodString>;
67
- }, "strip", z.ZodTypeAny, {
68
- from: string;
69
- disallow: string[];
70
- message?: string | undefined;
71
- }, {
72
- from: string;
73
- disallow: string[];
74
- message?: string | undefined;
75
- }>, "many">>;
76
- boundaries: z.ZodOptional<z.ZodObject<{
77
- requireSchema: z.ZodArray<z.ZodString, "many">;
78
- }, "strip", z.ZodTypeAny, {
79
- requireSchema: string[];
80
- }, {
81
- requireSchema: string[];
82
- }>>;
83
- }, "strip", z.ZodTypeAny, {
84
- version: 1;
85
- layers?: {
86
- name: string;
87
- pattern: string;
88
- allowedDependencies: string[];
89
- }[] | undefined;
90
- forbiddenImports?: {
91
- from: string;
92
- disallow: string[];
93
- message?: string | undefined;
94
- }[] | undefined;
95
- boundaries?: {
96
- requireSchema: string[];
97
- } | undefined;
98
- }, {
99
- version: 1;
100
- layers?: {
101
- name: string;
102
- pattern: string;
103
- allowedDependencies: string[];
104
- }[] | undefined;
105
- forbiddenImports?: {
106
- from: string;
107
- disallow: string[];
108
- message?: string | undefined;
109
- }[] | undefined;
110
- boundaries?: {
111
- requireSchema: string[];
112
- } | undefined;
113
- }>;
114
- export type HarnessConfig = z.infer<typeof HarnessConfigSchema>;
115
- export type Layer = z.infer<typeof LayerSchema>;
116
- export type ForbiddenImport = z.infer<typeof ForbiddenImportSchema>;
117
- //# sourceMappingURL=schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;EAItB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;EAIhC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;EAE/B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAChD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -1,34 +0,0 @@
1
- import { z } from 'zod';
2
- /**
3
- * Layer definition for architectural boundaries
4
- */
5
- export const LayerSchema = z.object({
6
- name: z.string(),
7
- pattern: z.string(),
8
- allowedDependencies: z.array(z.string()),
9
- });
10
- /**
11
- * Forbidden import rule
12
- */
13
- export const ForbiddenImportSchema = z.object({
14
- from: z.string(),
15
- disallow: z.array(z.string()),
16
- message: z.string().optional(),
17
- });
18
- /**
19
- * Boundary validation config
20
- */
21
- export const BoundaryConfigSchema = z.object({
22
- requireSchema: z.array(z.string()),
23
- });
24
- /**
25
- * Complete harness.config.json schema
26
- * Duplicated from @harness-engineering/cli to avoid circular dependency
27
- */
28
- export const HarnessConfigSchema = z.object({
29
- version: z.literal(1),
30
- layers: z.array(LayerSchema).optional(),
31
- forbiddenImports: z.array(ForbiddenImportSchema).optional(),
32
- boundaries: BoundaryConfigSchema.optional(),
33
- });
34
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CACzC,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CACnC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE;IACvC,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE;IAC3D,UAAU,EAAE,oBAAoB,CAAC,QAAQ,EAAE;CAC5C,CAAC,CAAC"}