@intentius/chant 0.38.0 → 0.41.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 (106) hide show
  1. package/dist/apply.d.ts +171 -0
  2. package/dist/apply.d.ts.map +1 -0
  3. package/dist/build.d.ts +21 -0
  4. package/dist/build.d.ts.map +1 -1
  5. package/dist/cli/commands/build.d.ts.map +1 -1
  6. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  7. package/dist/cli/commands/doctor.d.ts.map +1 -1
  8. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  9. package/dist/cli/handlers/run-client.d.ts.map +1 -1
  10. package/dist/cli/handlers/search.d.ts +30 -1
  11. package/dist/cli/handlers/search.d.ts.map +1 -1
  12. package/dist/cli/main.d.ts.map +1 -1
  13. package/dist/cli/plugins.d.ts +20 -0
  14. package/dist/cli/plugins.d.ts.map +1 -1
  15. package/dist/codegen/naming.d.ts +48 -1
  16. package/dist/codegen/naming.d.ts.map +1 -1
  17. package/dist/codegen/registry.d.ts +23 -0
  18. package/dist/codegen/registry.d.ts.map +1 -0
  19. package/dist/codegen/validate.d.ts +31 -0
  20. package/dist/codegen/validate.d.ts.map +1 -1
  21. package/dist/components/sandbox/driver.d.ts.map +1 -1
  22. package/dist/composite.d.ts +23 -4
  23. package/dist/composite.d.ts.map +1 -1
  24. package/dist/deep-observation.d.ts +11 -0
  25. package/dist/deep-observation.d.ts.map +1 -1
  26. package/dist/discovery/index.d.ts.map +1 -1
  27. package/dist/discovery/sandbox/driver.d.ts.map +1 -1
  28. package/dist/graph-declared.d.ts.map +1 -1
  29. package/dist/graph-ir.d.ts +17 -3
  30. package/dist/graph-ir.d.ts.map +1 -1
  31. package/dist/graph-refs.d.ts +24 -0
  32. package/dist/graph-refs.d.ts.map +1 -1
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/kubectl-context.d.ts.map +1 -1
  36. package/dist/lexicon-config.d.ts +61 -0
  37. package/dist/lexicon-config.d.ts.map +1 -0
  38. package/dist/lexicon.d.ts +19 -0
  39. package/dist/lexicon.d.ts.map +1 -1
  40. package/dist/lifecycle/deep-diff.d.ts +11 -0
  41. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  42. package/dist/lifecycle/digest.d.ts.map +1 -1
  43. package/dist/lifecycle/identity.d.ts +52 -0
  44. package/dist/lifecycle/identity.d.ts.map +1 -0
  45. package/dist/lifecycle/observe.d.ts +5 -0
  46. package/dist/lifecycle/observe.d.ts.map +1 -1
  47. package/dist/lifecycle/replay.d.ts.map +1 -1
  48. package/dist/lifecycle/types.d.ts +30 -0
  49. package/dist/lifecycle/types.d.ts.map +1 -1
  50. package/dist/managed-fields.d.ts +11 -0
  51. package/dist/managed-fields.d.ts.map +1 -1
  52. package/package.json +1 -1
  53. package/src/apply.test.ts +169 -0
  54. package/src/apply.ts +249 -0
  55. package/src/build.ts +24 -0
  56. package/src/cli/commands/build.ts +10 -0
  57. package/src/cli/commands/check-lexicon.ts +20 -1
  58. package/src/cli/commands/doctor.test.ts +45 -0
  59. package/src/cli/commands/doctor.ts +40 -0
  60. package/src/cli/handlers/lifecycle.ts +10 -0
  61. package/src/cli/handlers/run-client.ts +3 -1
  62. package/src/cli/handlers/search-kind.test.ts +45 -0
  63. package/src/cli/handlers/search.ts +102 -4
  64. package/src/cli/main.ts +32 -10
  65. package/src/cli/param-flag-scope.test.ts +69 -0
  66. package/src/cli/plugins.test.ts +33 -1
  67. package/src/cli/plugins.ts +55 -0
  68. package/src/codegen/naming.test.ts +129 -0
  69. package/src/codegen/naming.ts +72 -1
  70. package/src/codegen/registry.test.ts +56 -0
  71. package/src/codegen/registry.ts +69 -0
  72. package/src/codegen/validate.test.ts +86 -0
  73. package/src/codegen/validate.ts +74 -0
  74. package/src/components/SPRAWL-VALIDATION.md +5 -5
  75. package/src/components/sandbox/driver.test.ts +27 -0
  76. package/src/components/sandbox/driver.ts +12 -0
  77. package/src/composite.ts +33 -4
  78. package/src/deep-observation.ts +11 -0
  79. package/src/discovery/index.ts +59 -0
  80. package/src/discovery/params-cjs-warning.test.ts +75 -0
  81. package/src/discovery/sandbox/driver.test.ts +34 -0
  82. package/src/discovery/sandbox/driver.ts +19 -0
  83. package/src/graph-declared.test.ts +86 -0
  84. package/src/graph-declared.ts +14 -2
  85. package/src/graph-ir.ts +32 -8
  86. package/src/graph-refs.test.ts +56 -0
  87. package/src/graph-refs.ts +37 -1
  88. package/src/index.ts +1 -0
  89. package/src/kubectl-context.ts +4 -1
  90. package/src/lexicon-config.test.ts +111 -0
  91. package/src/lexicon-config.ts +92 -0
  92. package/src/lexicon.ts +20 -0
  93. package/src/lifecycle/deep-diff.test.ts +48 -1
  94. package/src/lifecycle/deep-diff.ts +16 -0
  95. package/src/lifecycle/digest.test.ts +81 -0
  96. package/src/lifecycle/digest.ts +34 -3
  97. package/src/lifecycle/identity.test.ts +39 -0
  98. package/src/lifecycle/identity.ts +61 -0
  99. package/src/lifecycle/observe.test.ts +75 -1
  100. package/src/lifecycle/observe.ts +28 -2
  101. package/src/lifecycle/replay.test.ts +251 -0
  102. package/src/lifecycle/replay.ts +67 -19
  103. package/src/lifecycle/types.ts +26 -0
  104. package/src/managed-fields.test.ts +50 -0
  105. package/src/managed-fields.ts +25 -6
  106. package/src/meta/peer-deps.test.ts +111 -14
@@ -4,26 +4,123 @@ import { fileURLToPath } from "url";
4
4
  import { join } from "path";
5
5
 
6
6
  /**
7
- * The lexicon packages are published in lockstep with core, so their
8
- * `@intentius/*` peerDependencies must track the current core version. They were
9
- * once frozen at `^0.1.0` while shipping at 0.7.0, which made a clean
10
- * `npm install` fail (#411). This locks the invariant so it can't drift again.
7
+ * The lexicon packages declare `@intentius/*` peers, and a range frozen at an
8
+ * old version makes a clean `npm install` fail they were once stuck at
9
+ * `^0.1.0` while shipping at 0.7.0 (#411). This locks the invariant so it
10
+ * cannot drift again.
11
+ *
12
+ * The range must track the version of the package that PROVIDES the peer, not
13
+ * core's version for every peer alike. Two providers exist: core backs
14
+ * `@intentius/chant`, and `lexicons/github` backs
15
+ * `@intentius/chant-lexicon-github` (forgejo and gitlab both peer on it).
16
+ * `just release-lexicon` writes exactly that — `^$core` for the core peer,
17
+ * `^$github_lexicon` for the github one — because a single-lexicon release
18
+ * moves one package without moving the others, so pinning every peer to core
19
+ * would demand a version that was never published.
20
+ *
21
+ * Asserting against core for both passed only while the whole workspace
22
+ * happened to sit on one version. `just release-lexicon github patch` alone is
23
+ * enough to separate them, and the old assertion then failed on a tree the
24
+ * release recipe had written correctly.
11
25
  */
12
26
  const repoRoot = fileURLToPath(new URL("../../../../", import.meta.url));
13
- const coreVersion = JSON.parse(readFileSync(join(repoRoot, "packages/core/package.json"), "utf-8")).version as string;
14
- const expected = `^${coreVersion}`;
27
+
28
+ function versionOf(packageDir: string): string {
29
+ return JSON.parse(readFileSync(join(repoRoot, packageDir, "package.json"), "utf-8")).version as string;
30
+ }
15
31
 
16
32
  const lexiconsDir = join(repoRoot, "lexicons");
17
33
  const lexicons = readdirSync(lexiconsDir).filter((name) => existsSync(join(lexiconsDir, name, "package.json")));
18
34
 
19
- describe("lexicon peerDependencies track the core version", () => {
20
- test.each(lexicons)("%s pins @intentius/* peers to the current version", (lexicon) => {
21
- const pkg = JSON.parse(readFileSync(join(lexiconsDir, lexicon, "package.json"), "utf-8"));
22
- const peers: Record<string, string> = pkg.peerDependencies ?? {};
23
- for (const [dep, range] of Object.entries(peers)) {
24
- if (dep.startsWith("@intentius/")) {
25
- expect(range, `${lexicon}: peer ${dep} should be ${expected}`).toBe(expected);
26
- }
35
+ /** Which workspace package publishes each `@intentius/*` peer a lexicon can declare. */
36
+ const providerDir: Record<string, string> = {
37
+ "@intentius/chant": join("packages", "core"),
38
+ "@intentius/chant-lexicon-github": join("lexicons", "github"),
39
+ };
40
+
41
+ function intentiusPeersOf(lexicon: string): [string, string][] {
42
+ const pkg = JSON.parse(readFileSync(join(lexiconsDir, lexicon, "package.json"), "utf-8"));
43
+ const peers: Record<string, string> = pkg.peerDependencies ?? {};
44
+ // Third-party peers (typescript) aren't ours to track.
45
+ return Object.entries(peers).filter(([dep]) => dep.startsWith("@intentius/"));
46
+ }
47
+
48
+ describe("lexicon peerDependencies track the version of the package providing them", () => {
49
+ test.each(lexicons)("%s pins @intentius/* peers to their provider's version", (lexicon) => {
50
+ for (const [dep, range] of intentiusPeersOf(lexicon)) {
51
+ const dir = providerDir[dep];
52
+ expect(
53
+ dir,
54
+ `${lexicon} peers ${dep}, which no workspace package is registered as providing — ` +
55
+ `add it to providerDir so its range is checked`,
56
+ ).toBeDefined();
57
+
58
+ expect(range, `${lexicon}: peer ${dep} should be ^${versionOf(dir)}`).toBe(`^${versionOf(dir)}`);
27
59
  }
28
60
  });
61
+
62
+ test("every @intentius/* peer declared anywhere has a registered provider", () => {
63
+ // Guards the map itself: a new cross-lexicon peer added without a
64
+ // providerDir entry would be reported per-lexicon above, but only if that
65
+ // lexicon is reached — this states the whole set in one place.
66
+ const declared = new Set(lexicons.flatMap((l) => intentiusPeersOf(l).map(([dep]) => dep)));
67
+ expect([...declared].sort()).toEqual(Object.keys(providerDir).sort());
68
+ });
69
+
70
+ });
71
+
72
+ /**
73
+ * The rule itself, over fixtures rather than the real tree — the tree sits on
74
+ * one version today, so it cannot demonstrate the skew this exists to handle.
75
+ */
76
+ function rangeViolations(
77
+ versions: Record<string, string>,
78
+ peers: Record<string, Record<string, string>>,
79
+ ): string[] {
80
+ const out: string[] = [];
81
+ for (const [lexicon, declared] of Object.entries(peers)) {
82
+ for (const [dep, range] of Object.entries(declared)) {
83
+ if (!dep.startsWith("@intentius/")) continue;
84
+ if (range !== `^${versions[dep]}`) out.push(`${lexicon}:${dep}`);
85
+ }
86
+ }
87
+ return out;
88
+ }
89
+
90
+ describe("the provider-aware rule, over fixtures", () => {
91
+ // `just release-lexicon github patch`: github moves, core does not, and the
92
+ // recipe rewrites forgejo's github peer to the new github version.
93
+ const skewed = { "@intentius/chant": "0.38.0", "@intentius/chant-lexicon-github": "0.38.1" };
94
+
95
+ test("accepts a provider ahead of core when its dependents track it", () => {
96
+ expect(
97
+ rangeViolations(skewed, {
98
+ forgejo: { "@intentius/chant": "^0.38.0", "@intentius/chant-lexicon-github": "^0.38.1" },
99
+ }),
100
+ ).toEqual([]);
101
+ // This is the case the old core-for-everything assertion rejected: it
102
+ // demanded ^0.38.0 for the github peer, on a tree release-lexicon wrote.
103
+ expect(`^${skewed["@intentius/chant-lexicon-github"]}`).not.toBe(`^${skewed["@intentius/chant"]}`);
104
+ });
105
+
106
+ test("still catches a range left behind by its provider", () => {
107
+ expect(
108
+ rangeViolations(skewed, {
109
+ forgejo: { "@intentius/chant": "^0.38.0", "@intentius/chant-lexicon-github": "^0.38.0" },
110
+ }),
111
+ ).toEqual(["forgejo:@intentius/chant-lexicon-github"]);
112
+ });
113
+
114
+ test("catches the #411 case — every range frozen at an old version", () => {
115
+ expect(
116
+ rangeViolations(skewed, {
117
+ aws: { "@intentius/chant": "^0.1.0" },
118
+ k8s: { "@intentius/chant": "^0.1.0" },
119
+ }),
120
+ ).toEqual(["aws:@intentius/chant", "k8s:@intentius/chant"]);
121
+ });
122
+
123
+ test("ignores third-party peers", () => {
124
+ expect(rangeViolations(skewed, { aws: { typescript: ">=5.0.0" } })).toEqual([]);
125
+ });
29
126
  });