@checkstack/dependency-frontend 0.2.1 → 0.2.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,59 @@
1
1
  # @checkstack/dependency-frontend
2
2
 
3
+ ## 0.2.3
4
+
5
+ ### Patch Changes
6
+
7
+ - d1a2796: Enforce stricter code quality standards and eliminate AI slop anti-patterns.
8
+
9
+ **New utility**
10
+
11
+ - `extractErrorMessage(error, fallback?)` in `@checkstack/common` for consistent error extraction
12
+
13
+ **ESLint rules**
14
+
15
+ - `react-hooks/rules-of-hooks` and `exhaustive-deps` for hook correctness
16
+ - `no-console` in frontend packages — forces `toast` over silent `console.error`
17
+ - `no-restricted-syntax` banning `instanceof Error` — forces `extractErrorMessage`
18
+ - Custom `no-eslint-disable-any` rule preventing `@typescript-eslint/no-explicit-any` circumvention
19
+
20
+ **Refactoring**
21
+
22
+ - Replace 141 `instanceof Error` boilerplate patterns across the codebase
23
+ - Replace swallowed `console.error` with user-visible `toast.error()` feedback
24
+ - Remove 15 redundant `as` type casts in IntegrationsPage and ProviderConnectionsPage
25
+ - Consolidate 3 identical callback handlers into `handleDialogClose`
26
+ - Fix conditional React hook call in `FormField.tsx`
27
+ - Fix unstable useMemo deps in `Dashboard.tsx`
28
+ - Replace `useEffect`→`setState` with derived `useMemo` in `RegisterPage.tsx`
29
+ - Rewrite `keystore.test.ts` with typed `DrizzleMockChain` (eliminating 7 `any` suppressions)
30
+ - Delete obvious comments in `encryption.ts` and Teams `provider.ts`
31
+
32
+ - Updated dependencies [d1a2796]
33
+ - Updated dependencies [3c34b07]
34
+ - @checkstack/common@0.6.5
35
+ - @checkstack/ui@1.2.1
36
+ - @checkstack/dashboard-frontend@0.3.26
37
+ - @checkstack/frontend-api@0.3.9
38
+ - @checkstack/catalog-common@1.3.1
39
+ - @checkstack/healthcheck-common@0.10.1
40
+ - @checkstack/dependency-common@0.2.1
41
+ - @checkstack/signal-frontend@0.0.15
42
+
43
+ ## 0.2.2
44
+
45
+ ### Patch Changes
46
+
47
+ - c0935d8: Fix dependency map node positions resetting when connecting two nodes. The graph-building effect was rebuilding all nodes from scratch on every data change, discarding unsaved drag positions. Node and edge construction are now split into separate effects with a clear position resolution priority: in-memory positions → saved positions → auto-layout fallback for new systems only.
48
+ - @checkstack/catalog-common@1.3.0
49
+ - @checkstack/common@0.6.4
50
+ - @checkstack/dashboard-frontend@0.3.25
51
+ - @checkstack/dependency-common@0.2.0
52
+ - @checkstack/frontend-api@0.3.8
53
+ - @checkstack/healthcheck-common@0.10.0
54
+ - @checkstack/signal-frontend@0.0.14
55
+ - @checkstack/ui@1.2.0
56
+
3
57
  ## 0.2.1
4
58
 
5
59
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/dependency-frontend",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "main": "src/index.tsx",
6
6
  "checkstack": {
@@ -12,12 +12,12 @@
12
12
  "lint:code": "eslint . --max-warnings 0"
13
13
  },
14
14
  "dependencies": {
15
- "@checkstack/catalog-common": "1.2.11",
15
+ "@checkstack/catalog-common": "1.3.0",
16
16
  "@checkstack/common": "0.6.4",
17
- "@checkstack/dashboard-frontend": "0.3.23",
18
- "@checkstack/dependency-common": "0.1.0",
17
+ "@checkstack/dashboard-frontend": "0.3.25",
18
+ "@checkstack/dependency-common": "0.2.0",
19
19
  "@checkstack/frontend-api": "0.3.8",
20
- "@checkstack/healthcheck-common": "0.8.4",
20
+ "@checkstack/healthcheck-common": "0.10.0",
21
21
  "@checkstack/signal-frontend": "0.0.14",
22
22
  "@checkstack/ui": "1.2.0",
23
23
  "@xyflow/react": "^12.10.2",
@@ -28,7 +28,7 @@
28
28
  "devDependencies": {
29
29
  "typescript": "^5.0.0",
30
30
  "@types/react": "^18.2.0",
31
- "@checkstack/tsconfig": "0.0.4",
31
+ "@checkstack/tsconfig": "0.0.5",
32
32
  "@checkstack/scripts": "0.1.2"
33
33
  }
34
34
  }
@@ -46,6 +46,7 @@ import {
46
46
  type DependencyEdge,
47
47
  type DependencyEdgeData,
48
48
  } from "./canvas/DependencyEdge";
49
+ import { extractErrorMessage } from "@checkstack/common";
49
50
 
50
51
  const nodeTypes = { system: SystemNodeComponent };
51
52
  const edgeTypes = { dependency: DependencyEdgeComponent };
@@ -171,7 +172,7 @@ function DependencyMapContent() {
171
172
  },
172
173
  onError: (error) => {
173
174
  const message =
174
- error instanceof Error ? error.message : "Failed to create dependency";
175
+ extractErrorMessage(error, "Failed to create dependency");
175
176
 
176
177
  // Check for cycle error and resolve names
177
178
  if (message.includes("circular chain")) {
@@ -193,7 +194,7 @@ function DependencyMapContent() {
193
194
  void refetchWarnings();
194
195
  },
195
196
  onError: (error) => {
196
- toast.error(error instanceof Error ? error.message : "Failed to update");
197
+ toast.error(extractErrorMessage(error, "Failed to update"));
197
198
  },
198
199
  });
199
200
 
@@ -206,7 +207,7 @@ function DependencyMapContent() {
206
207
  void refetchWarnings();
207
208
  },
208
209
  onError: (error) => {
209
- toast.error(error instanceof Error ? error.message : "Failed to delete");
210
+ toast.error(extractErrorMessage(error, "Failed to delete"));
210
211
  },
211
212
  });
212
213
 
@@ -227,21 +228,44 @@ function DependencyMapContent() {
227
228
  [createDependency],
228
229
  );
229
230
 
230
- // Build graph from data
231
+ // Track node positions for saving and for preserving in-memory positions
232
+ const nodesRef = useRef(nodes);
233
+ nodesRef.current = nodes;
234
+
235
+ // Build nodes from systems, positions, warnings, and health data.
236
+ // Position resolution priority:
237
+ // 1. Current in-memory position (user may have dragged but not saved yet)
238
+ // 2. Saved position from the backend
239
+ // 3. Auto-layout fallback for brand-new systems with no position at all
240
+
231
241
  useEffect(() => {
232
- if (!systemsData?.systems || !depsData?.dependencies) return;
242
+ if (!systemsData?.systems) return;
233
243
 
234
244
  const savedPositions = posData?.positions ?? [];
235
- const positions = autoLayout(
236
- systemsData.systems.map((s) => s.id),
237
- savedPositions,
238
- );
239
-
240
245
  const warnings = warningsData?.warnings ?? {};
241
246
  const healthStatuses = healthData?.statuses ?? {};
242
247
 
248
+ // Lookup maps for position resolution
249
+ const savedPositionMap = new Map(
250
+ savedPositions.map((p) => [p.systemId, { x: p.x, y: p.y }]),
251
+ );
252
+ const currentPositionMap = new Map<string, { x: number; y: number }>();
253
+ for (const node of nodesRef.current) {
254
+ currentPositionMap.set(node.id, node.position);
255
+ }
256
+
257
+ // Auto-layout only for systems that have no saved and no in-memory position
258
+ const unpositioned = systemsData.systems
259
+ .map((s) => s.id)
260
+ .filter((id) => !savedPositionMap.has(id) && !currentPositionMap.has(id));
261
+ const fallbackPositions = autoLayout(unpositioned, []);
262
+
243
263
  const newNodes: SystemNode[] = systemsData.systems.map((system) => {
244
- const pos = positions.get(system.id) ?? { x: 0, y: 0 };
264
+ const pos =
265
+ currentPositionMap.get(system.id) ??
266
+ savedPositionMap.get(system.id) ??
267
+ fallbackPositions.get(system.id) ?? { x: 0, y: 0 };
268
+
245
269
  const warning = warnings[system.id];
246
270
 
247
271
  // Map real health status to node status
@@ -270,6 +294,13 @@ function DependencyMapContent() {
270
294
  };
271
295
  });
272
296
 
297
+ setNodes(newNodes);
298
+ }, [systemsData, posData, warningsData, healthData, setNodes]);
299
+
300
+ // Build edges separately — only depends on dependency data
301
+ useEffect(() => {
302
+ if (!depsData?.dependencies) return;
303
+
273
304
  const newEdges: DependencyEdge[] = depsData.dependencies.map(
274
305
  (dep: Dependency) => {
275
306
  const edgeData: DependencyEdgeData = {
@@ -294,13 +325,10 @@ function DependencyMapContent() {
294
325
  },
295
326
  );
296
327
 
297
- setNodes(newNodes);
298
328
  setEdges(newEdges);
299
- }, [systemsData, depsData, posData, warningsData, healthData, setNodes, setEdges]);
329
+ }, [depsData, setEdges]);
300
330
 
301
331
  // Track node position changes for saving
302
- const nodesRef = useRef(nodes);
303
- nodesRef.current = nodes;
304
332
 
305
333
  const handleNodesChange = useCallback(
306
334
  (changes: NodeChange<SystemNode>[]) => {
@@ -323,6 +351,7 @@ function DependencyMapContent() {
323
351
  }, 2000);
324
352
  }
325
353
  },
354
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- handleSave reads from nodesRef (always current); including it would cause infinite re-render loops via setHasUnsaved
326
355
  [onNodesChange],
327
356
  );
328
357