@nordcraft/search 1.0.81 → 1.0.83

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.
@@ -0,0 +1,52 @@
1
+ import { ISSUE_RULES } from './rules/issues/issueRules.index';
2
+ import { searchProject } from './searchProject';
3
+ export const findProblems = (data, reportResults) => {
4
+ const { files, options = {} } = data;
5
+ const idRespond = (results) => reportResults({
6
+ id: data.id,
7
+ results,
8
+ });
9
+ const rules = ISSUE_RULES.filter((rule) => (!options.categories || options.categories.includes(rule.category)) &&
10
+ (!options.levels || options.levels.includes(rule.level)) &&
11
+ !options.rulesToExclude?.includes(rule.code));
12
+ let batch = [];
13
+ let fileType;
14
+ let fileName;
15
+ for (const problem of searchProject({
16
+ files,
17
+ rules,
18
+ pathsToVisit: options.pathsToVisit,
19
+ useExactPaths: options.useExactPaths,
20
+ state: options.state,
21
+ })) {
22
+ switch (options.batchSize) {
23
+ case 'all': {
24
+ batch.push(problem);
25
+ break;
26
+ }
27
+ case 'per-file': {
28
+ if (fileType !== problem.path[0] || fileName !== problem.path[1]) {
29
+ if (batch.length > 0) {
30
+ idRespond(batch);
31
+ }
32
+ batch = [];
33
+ fileType = problem.path[0];
34
+ fileName = problem.path[1];
35
+ }
36
+ batch.push(problem);
37
+ break;
38
+ }
39
+ default: {
40
+ batch.push(problem);
41
+ if (batch.length >= (options.batchSize ?? 1)) {
42
+ idRespond(batch);
43
+ batch = [];
44
+ }
45
+ break;
46
+ }
47
+ }
48
+ }
49
+ // Send the remaining results
50
+ idRespond(batch);
51
+ };
52
+ //# sourceMappingURL=findProblems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findProblems.js","sourceRoot":"","sources":["../src/findProblems.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAG/C,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,IAAsB,EACtB,aAAsD,EACtD,EAAE,CAAC;IACH,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,IAAI,CAAA;IACpC,MAAM,SAAS,GAAG,CAAC,OAAiB,EAAE,EAAE,CACtC,aAAa,CAAC;QACZ,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,OAAO;KACR,CAAC,CAAA;IACJ,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAC9B,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnE,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxD,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/C,CAAA;IAED,IAAI,KAAK,GAAa,EAAE,CAAA;IACxB,IAAI,QAAqC,CAAA;IACzC,IAAI,QAAqC,CAAA;IACzC,KAAK,MAAM,OAAO,IAAI,aAAa,CAAC;QAClC,KAAK;QACL,KAAK;QACL,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,EAAE,CAAC;QACH,QAAQ,OAAO,CAAC,SAAS,EAAE,CAAC;YAC1B,KAAK,KAAK,EAAE,CAAC;gBACX,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACnB,MAAK;YACP,CAAC;YACD,KAAK,UAAU,EAAE,CAAC;gBAChB,IAAI,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;oBACjE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACrB,SAAS,CAAC,KAAK,CAAC,CAAA;oBAClB,CAAC;oBACD,KAAK,GAAG,EAAE,CAAA;oBACV,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;oBAC1B,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBAC5B,CAAC;gBAED,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACnB,MAAK;YACP,CAAC;YAED,SAAS,CAAC;gBACR,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACnB,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC;oBAC7C,SAAS,CAAC,KAAK,CAAC,CAAA;oBAChB,KAAK,GAAG,EAAE,CAAA;gBACZ,CAAC;gBACD,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,SAAS,CAAC,KAAK,CAAC,CAAA;AAAA,CACjB,CAAA"}
@@ -0,0 +1,29 @@
1
+ import { create } from 'jsondiffpatch';
2
+ import { fixProject } from './fixProject';
3
+ import { ISSUE_RULES } from './rules/issues/issueRules.index';
4
+ export const fixProblems = (data, reportResults) => {
5
+ const { files, options = {}, fixRule } = data;
6
+ const rule = ISSUE_RULES.find((r) => r.code === fixRule);
7
+ if (!rule) {
8
+ throw new Error(`Unknown fix rule: ${data.fixRule}`);
9
+ }
10
+ const updatedFiles = fixProject({
11
+ files,
12
+ rule,
13
+ fixType: data.fixType,
14
+ pathsToVisit: options.pathsToVisit,
15
+ useExactPaths: options.useExactPaths,
16
+ state: options.state,
17
+ });
18
+ // Calculate diff
19
+ const jsonDiffPatch = create({ omitRemovedValues: true });
20
+ const diff = jsonDiffPatch.diff(files, updatedFiles);
21
+ // Send diff + metadata to main thread
22
+ reportResults({
23
+ id: data.id,
24
+ patch: diff,
25
+ fixRule: data.fixRule,
26
+ fixType: data.fixType,
27
+ });
28
+ };
29
+ //# sourceMappingURL=fixProblems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixProblems.js","sourceRoot":"","sources":["../src/fixProblems.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAA;AAG7D,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,IAAqB,EACrB,aAAqD,EACrD,EAAE,CAAC;IACH,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC7C,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAA;IACxD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;IACtD,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC;QAC9B,KAAK;QACL,IAAI;QACJ,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAA;IACF,iBAAiB;IACjB,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;IACpD,sCAAsC;IACtC,aAAa,CAAC;QACZ,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAA;AAAA,CACH,CAAA"}
@@ -1,91 +1,15 @@
1
- import { create } from 'jsondiffpatch';
2
- import { fixProject } from './fixProject';
3
- import { ISSUE_RULES } from './rules/issues/issueRules.index';
4
- import { searchProject } from './searchProject';
1
+ import { findProblems } from './findProblems';
2
+ import { fixProblems } from './fixProblems';
5
3
  const respond = (data) => postMessage(data);
6
- const findProblems = (data) => {
7
- const { files, options = {} } = data;
8
- const idRespond = (results) => respond({
9
- id: data.id,
10
- results,
11
- });
12
- const rules = ISSUE_RULES.filter((rule) => (!options.categories || options.categories.includes(rule.category)) &&
13
- (!options.levels || options.levels.includes(rule.level)) &&
14
- !options.rulesToExclude?.includes(rule.code));
15
- let batch = [];
16
- let fileType;
17
- let fileName;
18
- for (const problem of searchProject({
19
- files,
20
- rules,
21
- pathsToVisit: options.pathsToVisit,
22
- useExactPaths: options.useExactPaths,
23
- state: options.state,
24
- })) {
25
- switch (options.batchSize) {
26
- case 'all': {
27
- batch.push(problem);
28
- break;
29
- }
30
- case 'per-file': {
31
- if (fileType !== problem.path[0] || fileName !== problem.path[1]) {
32
- if (batch.length > 0) {
33
- idRespond(batch);
34
- }
35
- batch = [];
36
- fileType = problem.path[0];
37
- fileName = problem.path[1];
38
- }
39
- batch.push(problem);
40
- break;
41
- }
42
- default: {
43
- batch.push(problem);
44
- if (batch.length >= (options.batchSize ?? 1)) {
45
- idRespond(batch);
46
- batch = [];
47
- }
48
- break;
49
- }
50
- }
51
- }
52
- // Send the remaining results
53
- idRespond(batch);
54
- };
55
- const fixProblems = (data) => {
56
- const { files, options = {}, fixRule } = data;
57
- const rule = ISSUE_RULES.find((r) => r.code === fixRule);
58
- if (!rule) {
59
- throw new Error(`Unknown fix rule: ${data.fixRule}`);
60
- }
61
- const updatedFiles = fixProject({
62
- files,
63
- rule,
64
- fixType: data.fixType,
65
- pathsToVisit: options.pathsToVisit,
66
- useExactPaths: options.useExactPaths,
67
- state: options.state,
68
- });
69
- // Calculate diff
70
- const jsonDiffPatch = create({ omitRemovedValues: true });
71
- const diff = jsonDiffPatch.diff(files, updatedFiles);
72
- // Send diff + metadata to main thread
73
- respond({
74
- id: data.id,
75
- patch: diff,
76
- fixRule: data.fixRule,
77
- fixType: data.fixType,
78
- });
79
- };
80
4
  /**
81
5
  * This function is a web worker that checks for problems in the files.
82
6
  */
83
7
  onmessage = (event) => {
84
8
  if ('fixRule' in event.data) {
85
- fixProblems(event.data);
9
+ fixProblems(event.data, respond);
86
10
  }
87
11
  else {
88
- findProblems(event.data);
12
+ findProblems(event.data, respond);
89
13
  }
90
14
  };
91
15
  //# sourceMappingURL=problems.worker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"problems.worker.js","sourceRoot":"","sources":["../src/problems.worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"problems.worker.js","sourceRoot":"","sources":["../src/problems.worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAY3C,MAAM,OAAO,GAAG,CAAC,IAAc,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;AAErD;;GAEG;AACH,SAAS,GAAG,CAAC,KAA4B,EAAE,EAAE,CAAC;IAC5C,IAAI,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC5B,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAClC,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACnC,CAAC;AAAA,CACF,CAAA"}
@@ -7,6 +7,7 @@ import { noReferenceApiServiceRule } from './noReferenceApiServiceRule';
7
7
  import { unknownApiInputRule } from './unknownApiInputRule';
8
8
  import { unknownApiRule } from './unknownApiRule';
9
9
  import { unknownApiServiceRule } from './unknownApiServiceRule';
10
+ import { unknownFetchInputRule } from './unknownFetchInputRule';
10
11
  export default [
11
12
  // noReferenceApiInputRule,
12
13
  invalidApiParserModeRule,
@@ -15,6 +16,7 @@ export default [
15
16
  legacyApiRule,
16
17
  noReferenceApiRule,
17
18
  noReferenceApiServiceRule,
19
+ unknownFetchInputRule,
18
20
  unknownApiInputRule,
19
21
  unknownApiRule,
20
22
  unknownApiServiceRule,
@@ -1 +1 @@
1
- {"version":3,"file":"apiRules.index.js","sourceRoot":"","sources":["../../../../src/rules/issues/apis/apiRules.index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAA;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAE/D,eAAe;IACb,2BAA2B;IAC3B,wBAAwB;IACxB,8BAA8B;IAC9B,gCAAgC;IAChC,aAAa;IACb,kBAAkB;IAClB,yBAAyB;IACzB,mBAAmB;IACnB,cAAc;IACd,qBAAqB;CACtB,CAAA"}
1
+ {"version":3,"file":"apiRules.index.js","sourceRoot":"","sources":["../../../../src/rules/issues/apis/apiRules.index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAA;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAE/D,eAAe;IACb,2BAA2B;IAC3B,wBAAwB;IACxB,8BAA8B;IAC9B,gCAAgC;IAChC,aAAa;IACb,kBAAkB;IAClB,yBAAyB;IACzB,qBAAqB;IACrB,mBAAmB;IACnB,cAAc;IACd,qBAAqB;CACtB,CAAA"}
@@ -6,7 +6,8 @@ export const unknownApiRule = {
6
6
  const isApiFormula = nodeType === 'formula' &&
7
7
  value.type === 'path' &&
8
8
  value.path[0] === 'Apis';
9
- const isApiAction = nodeType === 'action-model' && value.type === 'Fetch';
9
+ const isApiAction = nodeType === 'action-model' &&
10
+ (value.type === 'Fetch' || value.type === 'AbortFetch');
10
11
  if (!isApiFormula && !isApiAction) {
11
12
  return;
12
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"unknownApiRule.js","sourceRoot":"","sources":["../../../../src/rules/issues/apis/unknownApiRule.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAEtB;IACH,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,mBAAmB;IAC7B,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACnD,MAAM,YAAY,GAChB,QAAQ,KAAK,SAAS;YACtB,KAAK,CAAC,IAAI,KAAK,MAAM;YACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,CAAA;QAC1B,MAAM,WAAW,GAAG,QAAQ,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAA;QACzE,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,OAAM;QACR,CAAC;QACD,MAAM,CAAC,EAAE,aAAa,CAAC,GAAG,IAAI,CAAA;QAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;QACjD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAA;YAC7B,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;YAChC,CAAC;QACH,CAAC;aAAM,IAAI,WAAW,EAAE,CAAC;YACvB,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;YACnC,CAAC;QACH,CAAC;IAAA,CACF;CACF,CAAA"}
1
+ {"version":3,"file":"unknownApiRule.js","sourceRoot":"","sources":["../../../../src/rules/issues/apis/unknownApiRule.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAEtB;IACH,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,mBAAmB;IAC7B,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACnD,MAAM,YAAY,GAChB,QAAQ,KAAK,SAAS;YACtB,KAAK,CAAC,IAAI,KAAK,MAAM;YACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,CAAA;QAC1B,MAAM,WAAW,GACf,QAAQ,KAAK,cAAc;YAC3B,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;QACzD,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,OAAM;QACR,CAAC;QACD,MAAM,CAAC,EAAE,aAAa,CAAC,GAAG,IAAI,CAAA;QAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;QACjD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAA;YAC7B,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;YAChC,CAAC;QACH,CAAC;aAAM,IAAI,WAAW,EAAE,CAAC;YACvB,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;YACnC,CAAC;QACH,CAAC;IAAA,CACF;CACF,CAAA"}
@@ -66,6 +66,10 @@ describe('unknownApi', () => {
66
66
  onSuccess: { actions: [] },
67
67
  onError: { actions: [] },
68
68
  },
69
+ {
70
+ type: 'AbortFetch',
71
+ api: 'unknown-abort-api',
72
+ },
69
73
  ],
70
74
  },
71
75
  },
@@ -91,9 +95,11 @@ describe('unknownApi', () => {
91
95
  },
92
96
  rules: [unknownApiRule],
93
97
  }));
94
- expect(problems).toHaveLength(1);
98
+ expect(problems).toHaveLength(2);
95
99
  expect(problems[0].code).toBe('unknown api');
96
100
  expect(problems[0].details).toEqual({ name: 'unknown-api' });
101
+ expect(problems[1].code).toBe('unknown api');
102
+ expect(problems[1].details).toEqual({ name: 'unknown-abort-api' });
97
103
  });
98
104
  test('should not report APIs that exist', () => {
99
105
  const problems = Array.from(searchProject({
@@ -1 +1 @@
1
- {"version":3,"file":"unknownApiRule.test.js","sourceRoot":"","sources":["../../../../src/rules/issues/apis/unknownApiRule.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unknownApiRule.test.js","sourceRoot":"","sources":["../../../../src/rules/issues/apis/unknownApiRule.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC;IAC3B,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE,CAAC;QAC5D,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,aAAa,CAAC;YACZ,KAAK,EAAE;gBACL,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE;4BACL,IAAI,EAAE;gCACJ,IAAI,EAAE,SAAS;gCACf,KAAK,EAAE,EAAE;gCACT,OAAO,EAAE;oCACP,UAAU,EAAE;wCACV,OAAO,EAAE;4CACP,IAAI,EAAE,MAAM;4CACZ,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;yCACzB;qCACF;iCACF;gCACD,MAAM,EAAE,EAAE;gCACV,GAAG,EAAE,KAAK;gCACV,QAAQ,EAAE,EAAE;gCACZ,KAAK,EAAE,EAAE;6BACV;yBACF;wBACD,QAAQ,EAAE,EAAE;wBACZ,IAAI,EAAE,EAAE;wBACR,UAAU,EAAE,EAAE;wBACd,SAAS,EAAE,EAAE;qBACd;iBACF;aACF;YACD,KAAK,EAAE,CAAC,cAAc,CAAC;SACxB,CAAC,CACH,CAAA;QAED,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAChC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;IAAA,CACxD,CAAC,CAAA;IAEF,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE,CAAC;QAC5D,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,aAAa,CAAC;YACZ,KAAK,EAAE;gBACL,QAAQ,EAAE,EAAE;gBACZ,UAAU,EAAE;oBACV,YAAY,EAAE;wBACZ,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE;4BACL,IAAI,EAAE;gCACJ,IAAI,EAAE,SAAS;gCACf,GAAG,EAAE,QAAQ;gCACb,KAAK,EAAE,EAAE;gCACT,KAAK,EAAE,EAAE;gCACT,QAAQ,EAAE,EAAE;gCACZ,OAAO,EAAE,EAAE;gCACX,MAAM,EAAE;oCACN,OAAO,EAAE;wCACP,OAAO,EAAE,SAAS;wCAClB,OAAO,EAAE;4CACP;gDACE,IAAI,EAAE,OAAO;gDACb,GAAG,EAAE,aAAa;gDAClB,MAAM,EAAE,EAAE;gDACV,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;gDAC1B,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;6CACzB;4CACD;gDACE,IAAI,EAAE,YAAY;gDAClB,GAAG,EAAE,mBAAmB;6CACzB;yCACF;qCACF;iCACF;6BACF;yBACF;wBACD,QAAQ,EAAE,EAAE;wBACZ,IAAI,EAAE;4BACJ,QAAQ,EAAE;gCACR,IAAI,EAAE,QAAQ;gCACd,IAAI,EAAE,MAAM;gCACZ,OAAO,EAAE,CAAC;gCACV,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC;gCAC7B,MAAM,EAAE,EAAE;gCACV,qBAAqB,EAAE;oCACrB,QAAQ,EAAE,IAAI;iCACf;6BACF;yBACF;wBACD,UAAU,EAAE,EAAE;wBACd,SAAS,EAAE,EAAE;qBACd;iBACF;aACF;YACD,KAAK,EAAE,CAAC,cAAc,CAAC;SACxB,CAAC,CACH,CAAA;QAED,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAChC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAA;QAC5D,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAA;IAAA,CACnE,CAAC,CAAA;IAEF,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,aAAa,CAAC;YACZ,KAAK,EAAE;gBACL,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE;4BACL,IAAI,EAAE;gCACJ,IAAI,EAAE,SAAS;gCACf,KAAK,EAAE,EAAE;gCACT,OAAO,EAAE;oCACP,UAAU,EAAE;wCACV,OAAO,EAAE;4CACP,IAAI,EAAE,MAAM;4CACZ,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC;yCACjC;qCACF;iCACF;gCACD,MAAM,EAAE,EAAE;gCACV,GAAG,EAAE,KAAK;gCACV,QAAQ,EAAE,EAAE;gCACZ,KAAK,EAAE,EAAE;6BACV;yBACF;wBACD,QAAQ,EAAE,EAAE;wBACZ,IAAI,EAAE;4BACJ,QAAQ,EAAE;gCACR,IAAI,EAAE,QAAQ;gCACd,IAAI,EAAE,MAAM;gCACZ,WAAW,EAAE,IAAI;gCACjB,QAAQ,EAAE,IAAI;6BACf;yBACF;wBACD,SAAS,EAAE,EAAE;wBACb,UAAU,EAAE;4BACV,KAAK,EAAE;gCACL,IAAI,EAAE,OAAO;gCACb,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE;gCACzC,qBAAqB,EAAE;oCACrB,QAAQ,EAAE,IAAI;iCACf;6BACF;yBACF;qBACF;iBACF;aACF;YACD,KAAK,EAAE,CAAC,cAAc,CAAC;SACxB,CAAC,CACH,CAAA;QAED,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAAA,CAC7B,CAAC,CAAA;AAAA,CACH,CAAC,CAAA"}
@@ -0,0 +1,42 @@
1
+ import { get } from '@nordcraft/core/dist/utils/collections';
2
+ import { removeFromPathFix } from '../../../util/removeUnused.fix';
3
+ export const unknownFetchInputRule = {
4
+ code: 'unknown fetch input',
5
+ level: 'warning',
6
+ category: 'Unknown Reference',
7
+ visit: (report, { path, files, value, nodeType }) => {
8
+ if (nodeType !== 'action-model' ||
9
+ value.type !== 'Fetch' ||
10
+ Object.keys(value.inputs ?? {}).length === 0) {
11
+ return;
12
+ }
13
+ const [components, componentName] = path;
14
+ const targetApi = get(files, [components, componentName, 'apis', value.api]);
15
+ if (!targetApi) {
16
+ return;
17
+ }
18
+ const validInputs = new Set(Object.keys(targetApi.inputs ?? {}));
19
+ for (const inputName of Object.keys(value.inputs ?? {})) {
20
+ if (!validInputs.has(inputName)) {
21
+ report(path, { name: inputName }, ['delete-fetch-input']);
22
+ }
23
+ }
24
+ },
25
+ fixes: {
26
+ 'delete-fetch-input': deleteUnknownFetchInputFix,
27
+ },
28
+ };
29
+ function deleteUnknownFetchInputFix(args) {
30
+ const inputToRemove = args.details?.name;
31
+ if (typeof inputToRemove !== 'string') {
32
+ return args.data.files;
33
+ }
34
+ return removeFromPathFix({
35
+ ...args,
36
+ data: {
37
+ ...args.data,
38
+ path: [...args.data.path, 'inputs', inputToRemove],
39
+ },
40
+ });
41
+ }
42
+ //# sourceMappingURL=unknownFetchInputRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unknownFetchInputRule.js","sourceRoot":"","sources":["../../../../src/rules/issues/apis/unknownFetchInputRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,wCAAwC,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAElE,MAAM,CAAC,MAAM,qBAAqB,GAE7B;IACH,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,mBAAmB;IAC7B,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACnD,IACE,QAAQ,KAAK,cAAc;YAC3B,KAAK,CAAC,IAAI,KAAK,OAAO;YACtB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,EAC5C,CAAC;YACD,OAAM;QACR,CAAC;QACD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,IAAI,CAAA;QACxC,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;QAC5E,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAM;QACR,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAA;QAChE,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAChC,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAA;YAC3D,CAAC;QACH,CAAC;IAAA,CACF;IACD,KAAK,EAAE;QACL,oBAAoB,EAAE,0BAA0B;KACjD;CACF,CAAA;AAED,SAAS,0BAA0B,CACjC,IAAmE,EACP;IAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAA;IACxC,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAA;IACxB,CAAC;IACD,OAAO,iBAAiB,CAAC;QACvB,GAAG,IAAI;QACP,IAAI,EAAE;YACJ,GAAG,IAAI,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,aAAa,CAAC;SACnD;KACF,CAAC,CAAA;AAAA,CACH"}
@@ -0,0 +1,175 @@
1
+ import { valueFormula } from '@nordcraft/core/dist/formula/formulaUtils';
2
+ import { describe, expect, test } from 'bun:test';
3
+ import { fixProject } from '../../../fixProject';
4
+ import { searchProject } from '../../../searchProject';
5
+ import { unknownFetchInputRule } from './unknownFetchInputRule';
6
+ describe('find unknownFetchInputRule', () => {
7
+ test('should report unknown api input overrides', () => {
8
+ const problems = Array.from(searchProject({
9
+ files: {
10
+ components: {
11
+ test: {
12
+ name: 'test',
13
+ onLoad: {
14
+ trigger: 'onLoad',
15
+ actions: [
16
+ {
17
+ type: 'Fetch',
18
+ api: 'my-api',
19
+ inputs: {
20
+ invalidInput: { formula: valueFormula('test') },
21
+ },
22
+ onSuccess: { actions: [] },
23
+ onError: { actions: [] },
24
+ },
25
+ ],
26
+ },
27
+ nodes: {
28
+ root: {
29
+ type: 'element',
30
+ attrs: {},
31
+ classes: {},
32
+ events: {},
33
+ tag: 'div',
34
+ children: [],
35
+ style: {},
36
+ },
37
+ },
38
+ formulas: {},
39
+ apis: {
40
+ 'my-api': {
41
+ name: 'my-api',
42
+ type: 'http',
43
+ version: 2,
44
+ autoFetch: valueFormula(true),
45
+ inputs: {
46
+ validInput: {
47
+ formula: valueFormula(null),
48
+ },
49
+ },
50
+ },
51
+ },
52
+ attributes: {},
53
+ variables: {},
54
+ },
55
+ },
56
+ },
57
+ rules: [unknownFetchInputRule],
58
+ }));
59
+ expect(problems).toHaveLength(1);
60
+ expect(problems[0].code).toBe('unknown fetch input');
61
+ expect(problems[0].details).toEqual({ name: 'invalidInput' });
62
+ });
63
+ test('should not report valid api input overrides', () => {
64
+ const problems = Array.from(searchProject({
65
+ files: {
66
+ components: {
67
+ test: {
68
+ name: 'test',
69
+ onLoad: {
70
+ trigger: 'onLoad',
71
+ actions: [
72
+ {
73
+ type: 'Fetch',
74
+ api: 'my-api',
75
+ inputs: {
76
+ validInput: { formula: valueFormula('test') },
77
+ },
78
+ onSuccess: { actions: [] },
79
+ onError: { actions: [] },
80
+ },
81
+ ],
82
+ },
83
+ nodes: {
84
+ root: {
85
+ type: 'element',
86
+ attrs: {},
87
+ classes: {},
88
+ events: {},
89
+ tag: 'div',
90
+ children: [],
91
+ style: {},
92
+ },
93
+ },
94
+ formulas: {},
95
+ apis: {
96
+ 'my-api': {
97
+ name: 'my-api',
98
+ type: 'http',
99
+ version: 2,
100
+ autoFetch: valueFormula(true),
101
+ inputs: {
102
+ validInput: {
103
+ formula: valueFormula(null),
104
+ },
105
+ },
106
+ },
107
+ },
108
+ attributes: {},
109
+ variables: {},
110
+ },
111
+ },
112
+ },
113
+ rules: [unknownFetchInputRule],
114
+ }));
115
+ expect(problems).toBeEmpty();
116
+ });
117
+ });
118
+ describe('fix unknownFetchInputRule', () => {
119
+ test('should remove unknown api input overrides', () => {
120
+ const project = {
121
+ formulas: {},
122
+ components: {
123
+ test: {
124
+ name: 'test',
125
+ onLoad: {
126
+ trigger: 'onLoad',
127
+ actions: [
128
+ {
129
+ type: 'Fetch',
130
+ api: 'my-api',
131
+ inputs: {
132
+ invalidInput: { formula: valueFormula('test') },
133
+ validInput: { formula: valueFormula('test') },
134
+ },
135
+ onSuccess: { actions: [] },
136
+ onError: { actions: [] },
137
+ },
138
+ ],
139
+ },
140
+ nodes: {},
141
+ formulas: {},
142
+ apis: {
143
+ 'my-api': {
144
+ name: 'my-api',
145
+ type: 'http',
146
+ version: 2,
147
+ autoFetch: valueFormula(true),
148
+ inputs: {
149
+ validInput: {
150
+ formula: valueFormula(null),
151
+ },
152
+ },
153
+ },
154
+ },
155
+ attributes: {},
156
+ variables: {},
157
+ },
158
+ },
159
+ };
160
+ const fixedProject = fixProject({
161
+ files: project,
162
+ rule: unknownFetchInputRule,
163
+ fixType: 'delete-fetch-input',
164
+ });
165
+ const fixedAction = fixedProject.components['test']?.onLoad?.actions?.[0];
166
+ if (fixedAction?.type !== 'Fetch') {
167
+ // To help Typescript narrow the type
168
+ throw new Error('Fixed action is not a Fetch action');
169
+ }
170
+ expect(fixedAction.inputs).toMatchObject({
171
+ validInput: { formula: valueFormula('test') },
172
+ });
173
+ });
174
+ });
175
+ //# sourceMappingURL=unknownFetchInputRule.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unknownFetchInputRule.test.js","sourceRoot":"","sources":["../../../../src/rules/issues/apis/unknownFetchInputRule.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -10,8 +10,8 @@
10
10
  "directory": "packages/search"
11
11
  },
12
12
  "dependencies": {
13
- "@nordcraft/ssr": "1.0.81",
14
- "@nordcraft/core": "1.0.81",
13
+ "@nordcraft/ssr": "1.0.83",
14
+ "@nordcraft/core": "1.0.83",
15
15
  "jsondiffpatch": "0.7.3",
16
16
  "postcss": "8.5.6",
17
17
  "zod": "4.2.1"
@@ -26,5 +26,5 @@
26
26
  "test:watch:only": "bun test --watch --only"
27
27
  },
28
28
  "files": ["dist", "src"],
29
- "version": "1.0.81"
29
+ "version": "1.0.83"
30
30
  }
@@ -0,0 +1,64 @@
1
+ import { ISSUE_RULES } from './rules/issues/issueRules.index'
2
+ import { searchProject } from './searchProject'
3
+ import type { FindProblemsArgs, FindProblemsResponse, Result } from './types'
4
+
5
+ export const findProblems = (
6
+ data: FindProblemsArgs,
7
+ reportResults: (results: FindProblemsResponse) => void,
8
+ ) => {
9
+ const { files, options = {} } = data
10
+ const idRespond = (results: Result[]) =>
11
+ reportResults({
12
+ id: data.id,
13
+ results,
14
+ })
15
+ const rules = ISSUE_RULES.filter(
16
+ (rule) =>
17
+ (!options.categories || options.categories.includes(rule.category)) &&
18
+ (!options.levels || options.levels.includes(rule.level)) &&
19
+ !options.rulesToExclude?.includes(rule.code),
20
+ )
21
+
22
+ let batch: Result[] = []
23
+ let fileType: string | number | undefined
24
+ let fileName: string | number | undefined
25
+ for (const problem of searchProject({
26
+ files,
27
+ rules,
28
+ pathsToVisit: options.pathsToVisit,
29
+ useExactPaths: options.useExactPaths,
30
+ state: options.state,
31
+ })) {
32
+ switch (options.batchSize) {
33
+ case 'all': {
34
+ batch.push(problem)
35
+ break
36
+ }
37
+ case 'per-file': {
38
+ if (fileType !== problem.path[0] || fileName !== problem.path[1]) {
39
+ if (batch.length > 0) {
40
+ idRespond(batch)
41
+ }
42
+ batch = []
43
+ fileType = problem.path[0]
44
+ fileName = problem.path[1]
45
+ }
46
+
47
+ batch.push(problem)
48
+ break
49
+ }
50
+
51
+ default: {
52
+ batch.push(problem)
53
+ if (batch.length >= (options.batchSize ?? 1)) {
54
+ idRespond(batch)
55
+ batch = []
56
+ }
57
+ break
58
+ }
59
+ }
60
+ }
61
+
62
+ // Send the remaining results
63
+ idRespond(batch)
64
+ }
@@ -0,0 +1,34 @@
1
+ import { create } from 'jsondiffpatch'
2
+ import { fixProject } from './fixProject'
3
+ import { ISSUE_RULES } from './rules/issues/issueRules.index'
4
+ import type { FixProblemsArgs, FixProblemsResponse } from './types'
5
+
6
+ export const fixProblems = (
7
+ data: FixProblemsArgs,
8
+ reportResults: (results: FixProblemsResponse) => void,
9
+ ) => {
10
+ const { files, options = {}, fixRule } = data
11
+ const rule = ISSUE_RULES.find((r) => r.code === fixRule)
12
+ if (!rule) {
13
+ throw new Error(`Unknown fix rule: ${data.fixRule}`)
14
+ }
15
+
16
+ const updatedFiles = fixProject({
17
+ files,
18
+ rule,
19
+ fixType: data.fixType,
20
+ pathsToVisit: options.pathsToVisit,
21
+ useExactPaths: options.useExactPaths,
22
+ state: options.state,
23
+ })
24
+ // Calculate diff
25
+ const jsonDiffPatch = create({ omitRemovedValues: true })
26
+ const diff = jsonDiffPatch.diff(files, updatedFiles)
27
+ // Send diff + metadata to main thread
28
+ reportResults({
29
+ id: data.id,
30
+ patch: diff,
31
+ fixRule: data.fixRule,
32
+ fixType: data.fixType,
33
+ })
34
+ }
@@ -1,174 +1,25 @@
1
- import type { ProjectFiles } from '@nordcraft/ssr/dist/ssr.types'
2
- import type { Delta } from 'jsondiffpatch'
3
- import { create } from 'jsondiffpatch'
4
- import { fixProject } from './fixProject'
5
- import { ISSUE_RULES } from './rules/issues/issueRules.index'
6
- import { searchProject } from './searchProject'
1
+ import { findProblems } from './findProblems'
2
+ import { fixProblems } from './fixProblems'
7
3
  import type {
8
- ApplicationState,
9
- Category,
10
- Code,
11
- FixType,
12
- Level,
13
- Result,
4
+ FindProblemsArgs,
5
+ FindProblemsResponse,
6
+ FixProblemsArgs,
7
+ FixProblemsResponse,
14
8
  } from './types'
15
9
 
16
- export type Options = {
17
- /**
18
- * Useful for running search on a subset or a single file.
19
- */
20
- pathsToVisit?: string[][]
21
- /**
22
- * Whether to match the paths exactly (including length) or just the beginning.
23
- */
24
- useExactPaths?: boolean
25
- /**
26
- * Search only rules with these specific categories. If empty, all categories are shown.
27
- */
28
- categories?: Category[]
29
- /**
30
- * Search only rules with the specific levels. If empty, all levels are shown.
31
- */
32
- levels?: Level[]
33
- /**
34
- * The number of reports to send per message.
35
- * @default 1
36
- */
37
- batchSize?: number | 'all' | 'per-file'
38
- /**
39
- * Dynamic data that is used by some rules.
40
- */
41
- state?: ApplicationState
42
- /**
43
- * Do not run rules with these codes. Useful for feature flagged rules
44
- */
45
- rulesToExclude?: Code[]
46
- }
47
-
48
- interface FindProblemsArgs {
49
- id: string
50
- files: ProjectFiles
51
- options?: Options
52
- }
53
-
54
- interface FixProblemsArgs {
55
- id: string
56
- files: ProjectFiles
57
- options?: Options
58
- fixRule: Code
59
- fixType: FixType
60
- }
61
-
62
10
  type Message = FindProblemsArgs | FixProblemsArgs
63
11
 
64
- interface FindProblemsResponse {
65
- id: string
66
- results: Result[]
67
- }
68
-
69
- interface FixProblemsResponse {
70
- id: string
71
- patch: Delta
72
- fixRule: Code
73
- fixType: FixType
74
- }
75
-
76
12
  type Response = FindProblemsResponse | FixProblemsResponse
77
13
 
78
14
  const respond = (data: Response) => postMessage(data)
79
15
 
80
- const findProblems = (data: FindProblemsArgs) => {
81
- const { files, options = {} } = data
82
- const idRespond = (results: Result[]) =>
83
- respond({
84
- id: data.id,
85
- results,
86
- })
87
- const rules = ISSUE_RULES.filter(
88
- (rule) =>
89
- (!options.categories || options.categories.includes(rule.category)) &&
90
- (!options.levels || options.levels.includes(rule.level)) &&
91
- !options.rulesToExclude?.includes(rule.code),
92
- )
93
-
94
- let batch: Result[] = []
95
- let fileType: string | number | undefined
96
- let fileName: string | number | undefined
97
- for (const problem of searchProject({
98
- files,
99
- rules,
100
- pathsToVisit: options.pathsToVisit,
101
- useExactPaths: options.useExactPaths,
102
- state: options.state,
103
- })) {
104
- switch (options.batchSize) {
105
- case 'all': {
106
- batch.push(problem)
107
- break
108
- }
109
- case 'per-file': {
110
- if (fileType !== problem.path[0] || fileName !== problem.path[1]) {
111
- if (batch.length > 0) {
112
- idRespond(batch)
113
- }
114
- batch = []
115
- fileType = problem.path[0]
116
- fileName = problem.path[1]
117
- }
118
-
119
- batch.push(problem)
120
- break
121
- }
122
-
123
- default: {
124
- batch.push(problem)
125
- if (batch.length >= (options.batchSize ?? 1)) {
126
- idRespond(batch)
127
- batch = []
128
- }
129
- break
130
- }
131
- }
132
- }
133
-
134
- // Send the remaining results
135
- idRespond(batch)
136
- }
137
-
138
- const fixProblems = (data: FixProblemsArgs) => {
139
- const { files, options = {}, fixRule } = data
140
- const rule = ISSUE_RULES.find((r) => r.code === fixRule)
141
- if (!rule) {
142
- throw new Error(`Unknown fix rule: ${data.fixRule}`)
143
- }
144
-
145
- const updatedFiles = fixProject({
146
- files,
147
- rule,
148
- fixType: data.fixType,
149
- pathsToVisit: options.pathsToVisit,
150
- useExactPaths: options.useExactPaths,
151
- state: options.state,
152
- })
153
- // Calculate diff
154
- const jsonDiffPatch = create({ omitRemovedValues: true })
155
- const diff = jsonDiffPatch.diff(files, updatedFiles)
156
- // Send diff + metadata to main thread
157
- respond({
158
- id: data.id,
159
- patch: diff,
160
- fixRule: data.fixRule,
161
- fixType: data.fixType,
162
- })
163
- }
164
-
165
16
  /**
166
17
  * This function is a web worker that checks for problems in the files.
167
18
  */
168
19
  onmessage = (event: MessageEvent<Message>) => {
169
20
  if ('fixRule' in event.data) {
170
- fixProblems(event.data)
21
+ fixProblems(event.data, respond)
171
22
  } else {
172
- findProblems(event.data)
23
+ findProblems(event.data, respond)
173
24
  }
174
25
  }
@@ -7,6 +7,7 @@ import { noReferenceApiServiceRule } from './noReferenceApiServiceRule'
7
7
  import { unknownApiInputRule } from './unknownApiInputRule'
8
8
  import { unknownApiRule } from './unknownApiRule'
9
9
  import { unknownApiServiceRule } from './unknownApiServiceRule'
10
+ import { unknownFetchInputRule } from './unknownFetchInputRule'
10
11
 
11
12
  export default [
12
13
  // noReferenceApiInputRule,
@@ -16,6 +17,7 @@ export default [
16
17
  legacyApiRule,
17
18
  noReferenceApiRule,
18
19
  noReferenceApiServiceRule,
20
+ unknownFetchInputRule,
19
21
  unknownApiInputRule,
20
22
  unknownApiRule,
21
23
  unknownApiServiceRule,
@@ -72,6 +72,10 @@ describe('unknownApi', () => {
72
72
  onSuccess: { actions: [] },
73
73
  onError: { actions: [] },
74
74
  },
75
+ {
76
+ type: 'AbortFetch',
77
+ api: 'unknown-abort-api',
78
+ },
75
79
  ],
76
80
  },
77
81
  },
@@ -99,9 +103,11 @@ describe('unknownApi', () => {
99
103
  }),
100
104
  )
101
105
 
102
- expect(problems).toHaveLength(1)
106
+ expect(problems).toHaveLength(2)
103
107
  expect(problems[0].code).toBe('unknown api')
104
108
  expect(problems[0].details).toEqual({ name: 'unknown-api' })
109
+ expect(problems[1].code).toBe('unknown api')
110
+ expect(problems[1].details).toEqual({ name: 'unknown-abort-api' })
105
111
  })
106
112
 
107
113
  test('should not report APIs that exist', () => {
@@ -11,7 +11,9 @@ export const unknownApiRule: Rule<{
11
11
  nodeType === 'formula' &&
12
12
  value.type === 'path' &&
13
13
  value.path[0] === 'Apis'
14
- const isApiAction = nodeType === 'action-model' && value.type === 'Fetch'
14
+ const isApiAction =
15
+ nodeType === 'action-model' &&
16
+ (value.type === 'Fetch' || value.type === 'AbortFetch')
15
17
  if (!isApiFormula && !isApiAction) {
16
18
  return
17
19
  }
@@ -0,0 +1,181 @@
1
+ import { valueFormula } from '@nordcraft/core/dist/formula/formulaUtils'
2
+ import type { ProjectFiles } from '@nordcraft/ssr/dist/ssr.types'
3
+ import { describe, expect, test } from 'bun:test'
4
+ import { fixProject } from '../../../fixProject'
5
+ import { searchProject } from '../../../searchProject'
6
+ import { unknownFetchInputRule } from './unknownFetchInputRule'
7
+
8
+ describe('find unknownFetchInputRule', () => {
9
+ test('should report unknown api input overrides', () => {
10
+ const problems = Array.from(
11
+ searchProject({
12
+ files: {
13
+ components: {
14
+ test: {
15
+ name: 'test',
16
+ onLoad: {
17
+ trigger: 'onLoad',
18
+ actions: [
19
+ {
20
+ type: 'Fetch',
21
+ api: 'my-api',
22
+ inputs: {
23
+ invalidInput: { formula: valueFormula('test') },
24
+ },
25
+ onSuccess: { actions: [] },
26
+ onError: { actions: [] },
27
+ },
28
+ ],
29
+ },
30
+ nodes: {
31
+ root: {
32
+ type: 'element',
33
+ attrs: {},
34
+ classes: {},
35
+ events: {},
36
+ tag: 'div',
37
+ children: [],
38
+ style: {},
39
+ },
40
+ },
41
+ formulas: {},
42
+ apis: {
43
+ 'my-api': {
44
+ name: 'my-api',
45
+ type: 'http',
46
+ version: 2,
47
+ autoFetch: valueFormula(true),
48
+ inputs: {
49
+ validInput: {
50
+ formula: valueFormula(null),
51
+ },
52
+ },
53
+ },
54
+ },
55
+ attributes: {},
56
+ variables: {},
57
+ },
58
+ },
59
+ },
60
+ rules: [unknownFetchInputRule],
61
+ }),
62
+ )
63
+
64
+ expect(problems).toHaveLength(1)
65
+ expect(problems[0].code).toBe('unknown fetch input')
66
+ expect(problems[0].details).toEqual({ name: 'invalidInput' })
67
+ })
68
+ test('should not report valid api input overrides', () => {
69
+ const problems = Array.from(
70
+ searchProject({
71
+ files: {
72
+ components: {
73
+ test: {
74
+ name: 'test',
75
+ onLoad: {
76
+ trigger: 'onLoad',
77
+ actions: [
78
+ {
79
+ type: 'Fetch',
80
+ api: 'my-api',
81
+ inputs: {
82
+ validInput: { formula: valueFormula('test') },
83
+ },
84
+ onSuccess: { actions: [] },
85
+ onError: { actions: [] },
86
+ },
87
+ ],
88
+ },
89
+ nodes: {
90
+ root: {
91
+ type: 'element',
92
+ attrs: {},
93
+ classes: {},
94
+ events: {},
95
+ tag: 'div',
96
+ children: [],
97
+ style: {},
98
+ },
99
+ },
100
+ formulas: {},
101
+ apis: {
102
+ 'my-api': {
103
+ name: 'my-api',
104
+ type: 'http',
105
+ version: 2,
106
+ autoFetch: valueFormula(true),
107
+ inputs: {
108
+ validInput: {
109
+ formula: valueFormula(null),
110
+ },
111
+ },
112
+ },
113
+ },
114
+ attributes: {},
115
+ variables: {},
116
+ },
117
+ },
118
+ },
119
+ rules: [unknownFetchInputRule],
120
+ }),
121
+ )
122
+ expect(problems).toBeEmpty()
123
+ })
124
+ })
125
+ describe('fix unknownFetchInputRule', () => {
126
+ test('should remove unknown api input overrides', () => {
127
+ const project: ProjectFiles = {
128
+ formulas: {},
129
+ components: {
130
+ test: {
131
+ name: 'test',
132
+ onLoad: {
133
+ trigger: 'onLoad',
134
+ actions: [
135
+ {
136
+ type: 'Fetch',
137
+ api: 'my-api',
138
+ inputs: {
139
+ invalidInput: { formula: valueFormula('test') },
140
+ validInput: { formula: valueFormula('test') },
141
+ },
142
+ onSuccess: { actions: [] },
143
+ onError: { actions: [] },
144
+ },
145
+ ],
146
+ },
147
+ nodes: {},
148
+ formulas: {},
149
+ apis: {
150
+ 'my-api': {
151
+ name: 'my-api',
152
+ type: 'http',
153
+ version: 2,
154
+ autoFetch: valueFormula(true),
155
+ inputs: {
156
+ validInput: {
157
+ formula: valueFormula(null),
158
+ },
159
+ },
160
+ },
161
+ },
162
+ attributes: {},
163
+ variables: {},
164
+ },
165
+ },
166
+ }
167
+ const fixedProject = fixProject({
168
+ files: project,
169
+ rule: unknownFetchInputRule,
170
+ fixType: 'delete-fetch-input',
171
+ })
172
+ const fixedAction = fixedProject.components['test']?.onLoad?.actions?.[0]
173
+ if (fixedAction?.type !== 'Fetch') {
174
+ // To help Typescript narrow the type
175
+ throw new Error('Fixed action is not a Fetch action')
176
+ }
177
+ expect(fixedAction.inputs!).toMatchObject({
178
+ validInput: { formula: valueFormula('test') },
179
+ })
180
+ })
181
+ })
@@ -0,0 +1,52 @@
1
+ import { get } from '@nordcraft/core/dist/utils/collections'
2
+ import type { ActionModelNode, FixFunction, Rule } from '../../../types'
3
+ import { removeFromPathFix } from '../../../util/removeUnused.fix'
4
+
5
+ export const unknownFetchInputRule: Rule<{
6
+ name: string
7
+ }> = {
8
+ code: 'unknown fetch input',
9
+ level: 'warning',
10
+ category: 'Unknown Reference',
11
+ visit: (report, { path, files, value, nodeType }) => {
12
+ if (
13
+ nodeType !== 'action-model' ||
14
+ value.type !== 'Fetch' ||
15
+ Object.keys(value.inputs ?? {}).length === 0
16
+ ) {
17
+ return
18
+ }
19
+ const [components, componentName] = path
20
+ const targetApi = get(files, [components, componentName, 'apis', value.api])
21
+ if (!targetApi) {
22
+ return
23
+ }
24
+ const validInputs = new Set(Object.keys(targetApi.inputs ?? {}))
25
+ for (const inputName of Object.keys(value.inputs ?? {})) {
26
+ if (!validInputs.has(inputName)) {
27
+ report(path, { name: inputName }, ['delete-fetch-input'])
28
+ }
29
+ }
30
+ },
31
+ fixes: {
32
+ 'delete-fetch-input': deleteUnknownFetchInputFix,
33
+ },
34
+ }
35
+
36
+ function deleteUnknownFetchInputFix(
37
+ args: Parameters<FixFunction<ActionModelNode, { name: string }>>[0],
38
+ ): ReturnType<FixFunction<ActionModelNode, { name: string }>> {
39
+ const inputToRemove = args.details?.name
40
+ if (typeof inputToRemove !== 'string') {
41
+ return args.data.files
42
+ }
43
+ return removeFromPathFix({
44
+ ...args,
45
+ data: {
46
+ ...args.data,
47
+ path: [...args.data.path, 'inputs', inputToRemove],
48
+ },
49
+ })
50
+ }
51
+
52
+ export type DeleteFetchInputFix = 'delete-fetch-input'
package/src/types.d.ts CHANGED
@@ -32,6 +32,7 @@ import type { UnknownActionEventRuleFix } from './rules/issues/actions/unknownAc
32
32
  import type { NoReferenceApiRuleFix } from './rules/issues/apis/noReferenceApiRule'
33
33
  import type { NoReferenceApiServiceRuleFix } from './rules/issues/apis/noReferenceApiServiceRule'
34
34
  import type { UnknownApiServiceRuleFix } from './rules/issues/apis/unknownApiServiceRule'
35
+ import type { DeleteFetchInputFix } from './rules/issues/apis/unknownFetchInputRule'
35
36
  import type { NoReferenceAttributeRuleFix } from './rules/issues/attributes/noReferenceAttributeRule'
36
37
  import type { UnknownComponentAttributeRuleFix } from './rules/issues/attributes/unknownComponentAttributeRule'
37
38
  import type { ChangeDataTypeFix } from './rules/issues/components/invalidComponentStructureRule'
@@ -107,6 +108,7 @@ type Code =
107
108
  | 'unknown cookie'
108
109
  | 'unknown component'
109
110
  | 'unknown event'
111
+ | 'unknown fetch input'
110
112
  | 'unknown formula'
111
113
  | 'unknown project action'
112
114
  | 'unknown project formula input'
@@ -137,7 +139,7 @@ type Category =
137
139
 
138
140
  type Level = 'error' | 'warning' | 'info'
139
141
 
140
- export type Result = {
142
+ type Result = {
141
143
  path: (string | number)[]
142
144
  code: Code
143
145
  category: Category
@@ -168,7 +170,7 @@ type NonHttpOnlyCookie = ApplicationCookie & {
168
170
  value: string
169
171
  }
170
172
 
171
- export interface ApplicationState {
173
+ interface ApplicationState {
172
174
  cookiesAvailable?: Array<HttpOnlyCookie | NonHttpOnlyCookie>
173
175
  isBrowserExtensionAvailable?: boolean
174
176
  projectDetails?: ToddleProject
@@ -377,7 +379,7 @@ type StyleNode = {
377
379
  }
378
380
  } & Base
379
381
 
380
- export type NodeType =
382
+ type NodeType =
381
383
  | ActionModelNode
382
384
  | ComponentAPIInputNode
383
385
  | ComponentAPINode
@@ -405,6 +407,7 @@ export type NodeType =
405
407
 
406
408
  type FixType =
407
409
  | ChangeDataTypeFix
410
+ | DeleteFetchInputFix
408
411
  | InvalidStyleSyntaxRuleFix
409
412
  | LegacyActionRuleFix
410
413
  | LegacyFormulaRuleFix
@@ -425,7 +428,7 @@ type FixType =
425
428
  | UnknownApiServiceRuleFix
426
429
  | UnknownComponentAttributeRuleFix
427
430
 
428
- export interface Rule<T = unknown, V = NodeType> {
431
+ interface Rule<T = unknown, V = NodeType> {
429
432
  category: Category
430
433
  code: Code
431
434
  level: Level
@@ -443,6 +446,64 @@ interface FixFunctionArgs<Data extends NodeType, Details = unknown> {
443
446
  state?: ApplicationState
444
447
  }
445
448
 
446
- export type FixFunction<Data extends NodeType, Details = unknown> = (
449
+ type FixFunction<Data extends NodeType, Details = unknown> = (
447
450
  args: FixFunctionArgs<Data, Details>,
448
451
  ) => ProjectFiles | void
452
+
453
+ type Options = {
454
+ /**
455
+ * Useful for running search on a subset or a single file.
456
+ */
457
+ pathsToVisit?: string[][]
458
+ /**
459
+ * Whether to match the paths exactly (including length) or just the beginning.
460
+ */
461
+ useExactPaths?: boolean
462
+ /**
463
+ * Search only rules with these specific categories. If empty, all categories are shown.
464
+ */
465
+ categories?: Category[]
466
+ /**
467
+ * Search only rules with the specific levels. If empty, all levels are shown.
468
+ */
469
+ levels?: Level[]
470
+ /**
471
+ * The number of reports to send per message.
472
+ * @default 1
473
+ */
474
+ batchSize?: number | 'all' | 'per-file'
475
+ /**
476
+ * Dynamic data that is used by some rules.
477
+ */
478
+ state?: ApplicationState
479
+ /**
480
+ * Do not run rules with these codes. Useful for feature flagged rules
481
+ */
482
+ rulesToExclude?: Code[]
483
+ }
484
+
485
+ interface FindProblemsArgs {
486
+ id: string
487
+ files: ProjectFiles
488
+ options?: Options
489
+ }
490
+
491
+ interface FindProblemsResponse {
492
+ id: string
493
+ results: Result[]
494
+ }
495
+
496
+ interface FixProblemsArgs {
497
+ id: string
498
+ files: ProjectFiles
499
+ options?: Options
500
+ fixRule: Code
501
+ fixType: FixType
502
+ }
503
+
504
+ interface FixProblemsResponse {
505
+ id: string
506
+ patch: Delta
507
+ fixRule: Code
508
+ fixType: FixType
509
+ }