@harness-engineering/eslint-plugin 0.3.0 → 0.3.1

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/index.d.ts CHANGED
@@ -99,6 +99,9 @@ declare const plugin: {
99
99
  '@harness-engineering/no-forbidden-imports': string;
100
100
  '@harness-engineering/require-boundary-schema': string;
101
101
  '@harness-engineering/enforce-doc-exports': string;
102
+ '@harness-engineering/no-nested-loops-in-critical': string;
103
+ '@harness-engineering/no-sync-io-in-async': string;
104
+ '@harness-engineering/no-unbounded-array-chains': string;
102
105
  '@harness-engineering/no-unix-shell-command': string;
103
106
  '@harness-engineering/no-hardcoded-path-separator': string;
104
107
  '@harness-engineering/no-process-env-in-spawn': string;
@@ -115,6 +118,9 @@ declare const plugin: {
115
118
  '@harness-engineering/no-forbidden-imports': string;
116
119
  '@harness-engineering/require-boundary-schema': string;
117
120
  '@harness-engineering/enforce-doc-exports': string;
121
+ '@harness-engineering/no-nested-loops-in-critical': string;
122
+ '@harness-engineering/no-sync-io-in-async': string;
123
+ '@harness-engineering/no-unbounded-array-chains': string;
118
124
  '@harness-engineering/no-unix-shell-command': string;
119
125
  '@harness-engineering/no-hardcoded-path-separator': string;
120
126
  '@harness-engineering/no-process-env-in-spawn': string;
@@ -182,6 +188,9 @@ declare const configs: {
182
188
  '@harness-engineering/no-forbidden-imports': string;
183
189
  '@harness-engineering/require-boundary-schema': string;
184
190
  '@harness-engineering/enforce-doc-exports': string;
191
+ '@harness-engineering/no-nested-loops-in-critical': string;
192
+ '@harness-engineering/no-sync-io-in-async': string;
193
+ '@harness-engineering/no-unbounded-array-chains': string;
185
194
  '@harness-engineering/no-unix-shell-command': string;
186
195
  '@harness-engineering/no-hardcoded-path-separator': string;
187
196
  '@harness-engineering/no-process-env-in-spawn': string;
@@ -245,6 +254,9 @@ declare const configs: {
245
254
  '@harness-engineering/no-forbidden-imports': string;
246
255
  '@harness-engineering/require-boundary-schema': string;
247
256
  '@harness-engineering/enforce-doc-exports': string;
257
+ '@harness-engineering/no-nested-loops-in-critical': string;
258
+ '@harness-engineering/no-sync-io-in-async': string;
259
+ '@harness-engineering/no-unbounded-array-chains': string;
248
260
  '@harness-engineering/no-unix-shell-command': string;
249
261
  '@harness-engineering/no-hardcoded-path-separator': string;
250
262
  '@harness-engineering/no-process-env-in-spawn': string;
package/dist/index.js CHANGED
@@ -308,17 +308,27 @@ function getConfig(filePath) {
308
308
  return null;
309
309
  }
310
310
  }
311
+ function getConfigRoot(filePath) {
312
+ const configPath = findConfigFile(path2.dirname(filePath));
313
+ return configPath ? path2.dirname(configPath) : null;
314
+ }
311
315
 
312
316
  // src/utils/path-utils.ts
313
317
  import * as path3 from "path";
314
318
  import { minimatch } from "minimatch";
315
- function resolveImportPath(importPath, importingFile) {
319
+ function resolveImportPath(importPath, importingFile, projectRoot) {
316
320
  if (!importPath.startsWith(".")) {
317
321
  return importPath;
318
322
  }
319
323
  const importingDir = path3.dirname(importingFile);
320
324
  const resolved = path3.resolve(importingDir, importPath);
321
325
  const normalized = resolved.replace(/\\/g, "/");
326
+ if (projectRoot) {
327
+ const root = projectRoot.replace(/\\/g, "/").replace(/\/$/, "");
328
+ if (normalized.startsWith(root + "/")) {
329
+ return normalized.slice(root.length + 1);
330
+ }
331
+ }
322
332
  const srcIndex = normalized.indexOf("/src/");
323
333
  if (srcIndex !== -1) {
324
334
  return normalized.slice(srcIndex + 1);
@@ -341,8 +351,14 @@ function getLayerForFile(filePath, layers) {
341
351
  function getLayerByName(name, layers) {
342
352
  return layers.find((l) => l.name === name);
343
353
  }
344
- function normalizePath2(filePath) {
354
+ function normalizePath2(filePath, projectRoot) {
345
355
  const normalized = filePath.replace(/\\/g, "/");
356
+ if (projectRoot) {
357
+ const root = projectRoot.replace(/\\/g, "/").replace(/\/$/, "");
358
+ if (normalized.startsWith(root + "/")) {
359
+ return normalized.slice(root.length + 1);
360
+ }
361
+ }
346
362
  const srcIndex = normalized.indexOf("/src/");
347
363
  if (srcIndex !== -1) {
348
364
  return normalized.slice(srcIndex + 1);
@@ -370,9 +386,9 @@ function findViolatedRule(applicableRules, importPath, resolvedImport) {
370
386
  function buildForbiddenMessage(rule, importPath) {
371
387
  return rule.message ?? `Import "${importPath}" is forbidden in files matching "${rule.from}"`;
372
388
  }
373
- function checkImportDeclaration2(node, applicableRules, filename, report) {
389
+ function checkImportDeclaration2(node, applicableRules, filename, projectRoot, report) {
374
390
  const importPath = node.source.value;
375
- const resolvedImport = resolveImportPath(importPath, filename);
391
+ const resolvedImport = resolveImportPath(importPath, filename, projectRoot ?? void 0);
376
392
  const violatedRule = findViolatedRule(applicableRules, importPath, resolvedImport);
377
393
  if (violatedRule) {
378
394
  report({
@@ -400,7 +416,8 @@ var no_forbidden_imports_default = createRule3({
400
416
  if (!config?.forbiddenImports?.length) {
401
417
  return {};
402
418
  }
403
- const filePath = normalizePath2(context.filename);
419
+ const projectRoot = getConfigRoot(context.filename);
420
+ const filePath = normalizePath2(context.filename, projectRoot ?? void 0);
404
421
  const applicableRules = config.forbiddenImports.filter(
405
422
  (rule) => matchesPattern(filePath, rule.from)
406
423
  );
@@ -410,7 +427,7 @@ var no_forbidden_imports_default = createRule3({
410
427
  const report = context.report.bind(context);
411
428
  return {
412
429
  ImportDeclaration(node) {
413
- checkImportDeclaration2(node, applicableRules, context.filename, report);
430
+ checkImportDeclaration2(node, applicableRules, context.filename, projectRoot, report);
414
431
  }
415
432
  };
416
433
  }
@@ -424,13 +441,13 @@ var createRule4 = ESLintUtils4.RuleCreator(
424
441
  function isLayerViolation(importLayer, currentLayer, currentLayerDef) {
425
442
  return importLayer !== currentLayer && !currentLayerDef.allowedDependencies.includes(importLayer);
426
443
  }
427
- function resolveImportLayer(importPath, filename, layers) {
444
+ function resolveImportLayer(importPath, filename, layers, projectRoot) {
428
445
  if (!importPath.startsWith(".")) return null;
429
- const resolvedImport = resolveImportPath(importPath, filename);
446
+ const resolvedImport = resolveImportPath(importPath, filename, projectRoot ?? void 0);
430
447
  return getLayerForFile(resolvedImport, layers) ?? null;
431
448
  }
432
- function checkLayerImport(node, context, currentLayer, currentLayerDef, layers) {
433
- const importLayer = resolveImportLayer(node.source.value, context.filename, layers);
449
+ function checkLayerImport(node, context, currentLayer, currentLayerDef, layers, projectRoot) {
450
+ const importLayer = resolveImportLayer(node.source.value, context.filename, layers, projectRoot);
434
451
  if (!importLayer) return;
435
452
  if (isLayerViolation(importLayer, currentLayer, currentLayerDef)) {
436
453
  context.report({
@@ -458,7 +475,8 @@ var no_layer_violation_default = createRule4({
458
475
  if (!config?.layers?.length) {
459
476
  return {};
460
477
  }
461
- const filePath = normalizePath2(context.filename);
478
+ const projectRoot = getConfigRoot(context.filename);
479
+ const filePath = normalizePath2(context.filename, projectRoot ?? void 0);
462
480
  const currentLayer = getLayerForFile(filePath, config.layers);
463
481
  if (!currentLayer) {
464
482
  return {};
@@ -470,7 +488,7 @@ var no_layer_violation_default = createRule4({
470
488
  const layers = config.layers;
471
489
  return {
472
490
  ImportDeclaration(node) {
473
- checkLayerImport(node, context, currentLayer, currentLayerDef, layers);
491
+ checkLayerImport(node, context, currentLayer, currentLayerDef, layers, projectRoot);
474
492
  }
475
493
  };
476
494
  }
@@ -964,6 +982,14 @@ function hasProcessEnvProperty(node) {
964
982
  }
965
983
  return void 0;
966
984
  }
985
+ function findEnvViolation(args) {
986
+ for (const arg of args) {
987
+ if (arg.type !== "ObjectExpression") continue;
988
+ const envProp = hasProcessEnvProperty(arg);
989
+ if (envProp) return envProp;
990
+ }
991
+ return void 0;
992
+ }
967
993
  var no_process_env_in_spawn_default = createRule11({
968
994
  name: "no-process-env-in-spawn",
969
995
  meta: {
@@ -978,20 +1004,15 @@ var no_process_env_in_spawn_default = createRule11({
978
1004
  },
979
1005
  defaultOptions: [],
980
1006
  create(context) {
981
- return {
982
- CallExpression(node) {
983
- const name = getSpawnFunctionName(node);
984
- if (!name) return;
985
- for (const arg of node.arguments) {
986
- if (arg.type === "ObjectExpression") {
987
- const envProp = hasProcessEnvProperty(arg);
988
- if (envProp) {
989
- context.report({ node: envProp, messageId: "processEnvInSpawn", data: { name } });
990
- }
991
- }
992
- }
1007
+ function checkCall(node) {
1008
+ const name = getSpawnFunctionName(node);
1009
+ if (!name) return;
1010
+ const violation = findEnvViolation(node.arguments);
1011
+ if (violation) {
1012
+ context.report({ node: violation, messageId: "processEnvInSpawn", data: { name } });
993
1013
  }
994
- };
1014
+ }
1015
+ return { CallExpression: checkCall };
995
1016
  }
996
1017
  });
997
1018
 
@@ -1072,7 +1093,7 @@ var rules = {
1072
1093
  var plugin = {
1073
1094
  meta: {
1074
1095
  name: "@harness-engineering/eslint-plugin",
1075
- version: "0.2.4"
1096
+ version: "0.3.0"
1076
1097
  },
1077
1098
  rules,
1078
1099
  configs: {
@@ -1088,6 +1109,9 @@ var plugin = {
1088
1109
  "@harness-engineering/no-forbidden-imports": "error",
1089
1110
  "@harness-engineering/require-boundary-schema": "warn",
1090
1111
  "@harness-engineering/enforce-doc-exports": "warn",
1112
+ "@harness-engineering/no-nested-loops-in-critical": "warn",
1113
+ "@harness-engineering/no-sync-io-in-async": "warn",
1114
+ "@harness-engineering/no-unbounded-array-chains": "warn",
1091
1115
  "@harness-engineering/no-unix-shell-command": "warn",
1092
1116
  "@harness-engineering/no-hardcoded-path-separator": "warn",
1093
1117
  "@harness-engineering/no-process-env-in-spawn": "error",
@@ -1106,6 +1130,9 @@ var plugin = {
1106
1130
  "@harness-engineering/no-forbidden-imports": "error",
1107
1131
  "@harness-engineering/require-boundary-schema": "error",
1108
1132
  "@harness-engineering/enforce-doc-exports": "error",
1133
+ "@harness-engineering/no-nested-loops-in-critical": "error",
1134
+ "@harness-engineering/no-sync-io-in-async": "error",
1135
+ "@harness-engineering/no-unbounded-array-chains": "error",
1109
1136
  "@harness-engineering/no-unix-shell-command": "error",
1110
1137
  "@harness-engineering/no-hardcoded-path-separator": "error",
1111
1138
  "@harness-engineering/no-process-env-in-spawn": "error",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harness-engineering/eslint-plugin",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "ESLint plugin for harness engineering architectural constraints",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",