@nordcraft/search 1.0.45 → 1.0.47

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 (53) hide show
  1. package/dist/problems.worker.js +11 -3
  2. package/dist/problems.worker.js.map +1 -1
  3. package/dist/rules/attributes/unknownComponentAttributeRule.js +33 -0
  4. package/dist/rules/attributes/unknownComponentAttributeRule.js.map +1 -0
  5. package/dist/rules/attributes/unknownComponentAttributeRule.test.js +145 -0
  6. package/dist/rules/attributes/unknownComponentAttributeRule.test.js.map +1 -0
  7. package/dist/rules/logic/noStaticNodeCondition.js +29 -0
  8. package/dist/rules/logic/noStaticNodeCondition.js.map +1 -0
  9. package/dist/rules/logic/noStaticNodeCondition.test.js +274 -0
  10. package/dist/rules/logic/noStaticNodeCondition.test.js.map +1 -0
  11. package/dist/rules/logic/noUnnecessaryConditionFalsy.js +5 -1
  12. package/dist/rules/logic/noUnnecessaryConditionFalsy.js.map +1 -1
  13. package/dist/rules/logic/noUnnecessaryConditionTruthy.js +8 -4
  14. package/dist/rules/logic/noUnnecessaryConditionTruthy.js.map +1 -1
  15. package/dist/rules/logic/noUnnecessaryConditionTruthy.test.js +33 -4
  16. package/dist/rules/logic/noUnnecessaryConditionTruthy.test.js.map +1 -1
  17. package/dist/rules/noReferenceNodeRule.js +10 -8
  18. package/dist/rules/noReferenceNodeRule.js.map +1 -1
  19. package/dist/rules/noReferenceNodeRule.test.js +1 -1
  20. package/dist/rules/style/invalidStyleSyntaxRule.js +2 -2
  21. package/dist/rules/style/invalidStyleSyntaxRule.test.js +1 -1
  22. package/dist/rules/workflows/noPostNavigateAction.js +13 -2
  23. package/dist/rules/workflows/noPostNavigateAction.js.map +1 -1
  24. package/dist/rules/workflows/noPostNavigateAction.test.js +102 -1
  25. package/dist/rules/workflows/noPostNavigateAction.test.js.map +1 -1
  26. package/dist/util/contextlessEvaluateFormula.js +77 -0
  27. package/dist/util/contextlessEvaluateFormula.js.map +1 -0
  28. package/dist/util/contextlessEvaluateFormula.test.js +152 -0
  29. package/dist/util/contextlessEvaluateFormula.test.js.map +1 -0
  30. package/dist/util/helpers.test.js +1 -1
  31. package/dist/util/helpers.test.js.map +1 -1
  32. package/dist/util/removeUnused.fix.js +18 -1
  33. package/dist/util/removeUnused.fix.js.map +1 -1
  34. package/package.json +2 -2
  35. package/src/problems.worker.ts +18 -5
  36. package/src/rules/attributes/unknownComponentAttributeRule.test.ts +156 -0
  37. package/src/rules/attributes/unknownComponentAttributeRule.ts +40 -0
  38. package/src/rules/logic/noStaticNodeCondition.test.ts +290 -0
  39. package/src/rules/logic/noStaticNodeCondition.ts +43 -0
  40. package/src/rules/logic/noUnnecessaryConditionFalsy.ts +5 -4
  41. package/src/rules/logic/noUnnecessaryConditionTruthy.test.ts +37 -4
  42. package/src/rules/logic/noUnnecessaryConditionTruthy.ts +10 -8
  43. package/src/rules/noReferenceNodeRule.test.ts +1 -1
  44. package/src/rules/noReferenceNodeRule.ts +17 -10
  45. package/src/rules/style/invalidStyleSyntaxRule.test.ts +1 -1
  46. package/src/rules/style/invalidStyleSyntaxRule.ts +3 -3
  47. package/src/rules/workflows/noPostNavigateAction.test.ts +111 -1
  48. package/src/rules/workflows/noPostNavigateAction.ts +20 -3
  49. package/src/types.d.ts +12 -0
  50. package/src/util/contextlessEvaluateFormula.test.ts +190 -0
  51. package/src/util/contextlessEvaluateFormula.ts +110 -0
  52. package/src/util/helpers.test.ts +1 -1
  53. package/src/util/removeUnused.fix.ts +29 -1
@@ -0,0 +1,110 @@
1
+ import { type Formula } from '@nordcraft/core/dist/formula/formula'
2
+
3
+ /**
4
+ * Static evaluation of a formula.
5
+ *
6
+ * Can be used by issues to determine if a formula or sub-formula can be reduced to a static value.
7
+ * When sophisticated enough, it can be used during compile-time to reduce all static subgraphs of a formula to static values, greatly reducing payload and improving runtime performance.
8
+ *
9
+ * @returns {
10
+ * isStatic: boolean; // Whether the formula is static (i.e., does not depend on any variables, context AND only use pure formulas (no Random, Date, etc.))
11
+ * result: unknown; // The evaluated value of the formula
12
+ * }
13
+ *
14
+ * TODO: Make this function more capable of evaluating pure core formulas.
15
+ * TODO: Memoize the results (using path or a fast hash) to avoid re-evaluating any similar sub-graphs multiple times.
16
+ * TODO: Add a complex test-suite to ensure it works and develops as expected.
17
+ */
18
+ export const contextlessEvaluateFormula = (
19
+ formula: Formula,
20
+ ): {
21
+ isStatic: boolean
22
+ result: unknown
23
+ } => {
24
+ // Very basic implementation, just to get started.
25
+ switch (formula.type) {
26
+ case 'value': {
27
+ return {
28
+ isStatic: true,
29
+ result: formula.value,
30
+ }
31
+ }
32
+
33
+ case 'array': {
34
+ const results = formula.arguments.map((arg) =>
35
+ contextlessEvaluateFormula(arg.formula),
36
+ )
37
+
38
+ return {
39
+ isStatic: results.every((res) => res.isStatic),
40
+ result: results.map((res) => res.result),
41
+ }
42
+ }
43
+
44
+ case 'record': {
45
+ const entries = Object.entries(formula.entries).map(
46
+ ([key, arg]) => [key, contextlessEvaluateFormula(arg.formula)] as const,
47
+ )
48
+
49
+ const results = entries.map(([, res]) => res)
50
+
51
+ return {
52
+ isStatic: results.every((res) => res.isStatic),
53
+ result: Object.fromEntries(
54
+ entries.map(([key, res]) => [key, res.result]),
55
+ ),
56
+ }
57
+ }
58
+
59
+ // Static if:
60
+ // - ALL conditions are static AND truthy
61
+ // - ANY condition is static and falsy
62
+ // - EMPTY argument list is always true
63
+ case 'and': {
64
+ const results = formula.arguments.map((arg) =>
65
+ contextlessEvaluateFormula(arg.formula),
66
+ )
67
+
68
+ const alwaysTrue =
69
+ results.length === 0 ||
70
+ results.every((res) => res.isStatic && Boolean(res.result) === true)
71
+ const alwaysFalsy = results.some(
72
+ (res) => res.isStatic && Boolean(res.result) === false,
73
+ )
74
+
75
+ return {
76
+ isStatic: alwaysTrue || alwaysFalsy,
77
+ result: alwaysTrue ? true : alwaysFalsy ? false : undefined,
78
+ }
79
+ }
80
+
81
+ // Static if:
82
+ // - ANY condition is static AND truthy
83
+ // - ALL conditions are static AND falsy
84
+ // - EMPTY argument list is always false
85
+ case 'or': {
86
+ const results = formula.arguments.map((arg) =>
87
+ contextlessEvaluateFormula(arg.formula),
88
+ )
89
+
90
+ const alwaysFalsy =
91
+ results.length === 0 ||
92
+ results.every((res) => res.isStatic && Boolean(res.result) === false)
93
+ const alwaysTrue = results.some(
94
+ (res) => res.isStatic && Boolean(res.result) === true,
95
+ )
96
+
97
+ return {
98
+ isStatic: alwaysTrue || alwaysFalsy,
99
+ result: alwaysFalsy ? false : alwaysTrue ? true : undefined,
100
+ }
101
+ }
102
+
103
+ default:
104
+ // For now, we assume that any other formula is not static.
105
+ return {
106
+ isStatic: false,
107
+ result: undefined,
108
+ }
109
+ }
110
+ }
@@ -53,7 +53,7 @@ describe('shouldSearchPath', () => {
53
53
  })
54
54
 
55
55
  describe('shouldSearchExactPath', () => {
56
- test.only('should only return true for exact matches', () => {
56
+ test('should only return true for exact matches', () => {
57
57
  const pathsToVisit = [
58
58
  ['components', 'Button'],
59
59
  ['components', 'Input'],
@@ -1,5 +1,33 @@
1
- import { omit } from '@nordcraft/core/dist/utils/collections'
1
+ import type { NodeModel } from '@nordcraft/core/dist/component/component.types'
2
+ import { get, omit, set } from '@nordcraft/core/dist/utils/collections'
2
3
  import type { FixFunction, NodeType } from '../types'
3
4
 
4
5
  export const removeFromPathFix: FixFunction<NodeType> = ({ path, files }) =>
5
6
  omit(files, path)
7
+
8
+ /**
9
+ * Same as removeFromPathFix, but also removes the node from its parent's children.
10
+ */
11
+ export const removeNodeFromPathFix: FixFunction<NodeType> = (data) => {
12
+ if (data.nodeType !== 'component-node') {
13
+ throw new Error('removeNodeFromPathFix can only be used on component nodes')
14
+ }
15
+
16
+ const componentNodesPath = data.path.slice(0, -1).map(String)
17
+ const filesWithoutNode = removeFromPathFix(data)
18
+ const nodes = get(filesWithoutNode, componentNodesPath) as Record<
19
+ string,
20
+ NodeModel
21
+ >
22
+ for (const key in nodes) {
23
+ if (
24
+ nodes[key].children?.includes(data.path[data.path.length - 1] as string)
25
+ ) {
26
+ nodes[key].children = nodes[key].children.filter(
27
+ (p) => p !== data.path[data.path.length - 1],
28
+ )
29
+ }
30
+ }
31
+
32
+ return set(filesWithoutNode, componentNodesPath, nodes)
33
+ }