Skip to content

Commit faae48b

Browse files
committed
refactor(api): clean up imports and improve formatting in GeoJSON and SVG nodes
1 parent 1c1d9bd commit faae48b

13 files changed

Lines changed: 178 additions & 111 deletions

apps/api/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
"@hono-rate-limiter/cloudflare": "^0.2.2",
5252
"@hono/oauth-providers": "^0.7.1",
5353
"@hono/zod-validator": "^0.5.0",
54-
"@resvg/resvg-wasm": "^2.6.2",
5554
"@sendgrid/mail": "^8.1.5",
5655
"@turf/helpers": "^7.2.0",
5756
"@turf/turf": "^7.2.0",

apps/api/src/nodes/cloudflare-node-registry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ import { PolygonSmoothNode } from "./geo/polygon-smooth-node";
9494
import { PolygonTangentsNode } from "./geo/polygon-tangents-node";
9595
import { PolygonToLineNode } from "./geo/polygon-to-line-node";
9696
import { PolygonizeNode } from "./geo/polygonize-node";
97-
import { SvgToPngNode } from "./image/svg-to-png-node";
9897
import { RewindNode } from "./geo/rewind-node";
9998
import { RhumbBearingNode } from "./geo/rhumb-bearing-node";
10099
import { RhumbDestinationNode } from "./geo/rhumb-destination-node";
@@ -150,6 +149,7 @@ import { StableDiffusionV15Img2ImgNode } from "./image/stable-diffusion-v1-5-img
150149
import { StableDiffusionV15InpaintingNode } from "./image/stable-diffusion-v1-5-inpainting-node";
151150
import { StableDiffusionXLBase10Node } from "./image/stable-diffusion-xl-base-1-0-node";
152151
import { StableDiffusionXLLightningNode } from "./image/stable-diffusion-xl-lightning-node";
152+
import { SvgToPngNode } from "./image/svg-to-png-node";
153153
import { UformGen2Qwen500mNode } from "./image/uform-gen2-qwen-500m-node";
154154
import { WebcamNode } from "./image/webcam-node";
155155
import { JavaScriptEditorNode } from "./javascript/javascript-editor-node";

apps/api/src/nodes/geo/geojson-node.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,13 @@ export class GeoJsonNode extends ExecutableNode {
3030
{
3131
name: "geojsonType",
3232
type: "string",
33-
description: "The type of GeoJSON (Point, LineString, Feature, FeatureCollection, etc.)",
33+
description:
34+
"The type of GeoJSON (Point, LineString, Feature, FeatureCollection, etc.)",
3435
hidden: true,
3536
},
3637
],
3738
};
3839

39-
40-
4140
public async execute(context: NodeContext): Promise<NodeExecution> {
4241
try {
4342
const { json } = context.inputs;
@@ -59,9 +58,7 @@ export class GeoJsonNode extends ExecutableNode {
5958
return this.createErrorResult("Invalid GeoJSON");
6059
} catch (err) {
6160
const error = err as Error;
62-
return this.createErrorResult(
63-
`Error parsing GeoJSON: ${error.message}`
64-
);
61+
return this.createErrorResult(`Error parsing GeoJSON: ${error.message}`);
6562
}
6663
}
6764

@@ -71,14 +68,14 @@ export class GeoJsonNode extends ExecutableNode {
7168
if (!Array.isArray(data.features)) {
7269
return false;
7370
}
74-
71+
7572
// Validate each feature in the collection
7673
for (const feature of data.features) {
7774
if (!booleanValid(feature)) {
7875
return false;
7976
}
8077
}
81-
78+
8279
return true;
8380
}
8481

apps/api/src/nodes/geo/geojson-to-svg-node.test.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { beforeEach, describe, it, expect } from "vitest";
2-
import { GeoJsonToSvgNode } from "./geojson-to-svg-node";
1+
import { beforeEach, describe, expect, it } from "vitest";
2+
33
import { NodeContext } from "../types";
4+
import { GeoJsonToSvgNode } from "./geojson-to-svg-node";
45

56
describe("GeoJsonToSvgNode", () => {
67
const createMockContext = (inputs: Record<string, any>): NodeContext => ({
@@ -28,8 +29,12 @@ describe("GeoJsonToSvgNode", () => {
2829
expect(GeoJsonToSvgNode.nodeType.id).toBe("geojson-to-svg");
2930
expect(GeoJsonToSvgNode.nodeType.name).toBe("GeoJSON to SVG");
3031
expect(GeoJsonToSvgNode.nodeType.type).toBe("geojson-to-svg");
31-
expect(GeoJsonToSvgNode.nodeType.description).toContain("identity projection");
32-
expect(GeoJsonToSvgNode.nodeType.description).toContain("separate path elements");
32+
expect(GeoJsonToSvgNode.nodeType.description).toContain(
33+
"identity projection"
34+
);
35+
expect(GeoJsonToSvgNode.nodeType.description).toContain(
36+
"separate path elements"
37+
);
3338
expect(GeoJsonToSvgNode.nodeType.tags).toContain("Geo");
3439
expect(GeoJsonToSvgNode.nodeType.tags).toContain("Image");
3540
});
@@ -99,19 +104,19 @@ describe("GeoJsonToSvgNode", () => {
99104
const minYInput = inputs.find((i) => i.name === "minY");
100105
const maxXInput = inputs.find((i) => i.name === "maxX");
101106
const maxYInput = inputs.find((i) => i.name === "maxY");
102-
107+
103108
expect(minXInput).toBeDefined();
104109
expect(minXInput?.description).toContain("Minimum X coordinate");
105110
expect(minXInput?.description).toContain("left boundary");
106-
111+
107112
expect(minYInput).toBeDefined();
108113
expect(minYInput?.description).toContain("Minimum Y coordinate");
109114
expect(minYInput?.description).toContain("bottom boundary");
110-
115+
111116
expect(maxXInput).toBeDefined();
112117
expect(maxXInput?.description).toContain("Maximum X coordinate");
113118
expect(maxXInput?.description).toContain("right boundary");
114-
119+
115120
expect(maxYInput).toBeDefined();
116121
expect(maxYInput?.description).toContain("Maximum Y coordinate");
117122
expect(maxYInput?.description).toContain("top boundary");
@@ -121,9 +126,9 @@ describe("GeoJsonToSvgNode", () => {
121126
const inputs = GeoJsonToSvgNode.nodeType.inputs;
122127
const minXInput = inputs.find((i) => i.name === "minX");
123128
const maxYInput = inputs.find((i) => i.name === "maxY");
124-
129+
125130
// All viewport parameters are optional
126131
expect(minXInput?.required).toBe(false);
127132
expect(maxYInput?.required).toBe(false);
128133
});
129-
});
134+
});

apps/api/src/nodes/geo/geojson-to-svg-node.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { NodeExecution, NodeType } from "@dafthunk/types";
2-
import { geojsonToSvg, type GeoJSONSvgOptions } from "@dafthunk/utils";
2+
import { type GeoJSONSvgOptions, geojsonToSvg } from "@dafthunk/utils";
33

44
import { ExecutableNode } from "../types";
55
import { NodeContext } from "../types";
@@ -9,7 +9,8 @@ export class GeoJsonToSvgNode extends ExecutableNode {
99
id: "geojson-to-svg",
1010
name: "GeoJSON to SVG",
1111
type: "geojson-to-svg",
12-
description: "Renders GeoJSON data into an SVG file using d3-geo with identity projection. Creates separate path elements for each geometry with appropriate styling.",
12+
description:
13+
"Renders GeoJSON data into an SVG file using d3-geo with identity projection. Creates separate path elements for each geometry with appropriate styling.",
1314
tags: ["Geo", "Image"],
1415
icon: "map",
1516
inputs: [
@@ -68,28 +69,32 @@ export class GeoJsonToSvgNode extends ExecutableNode {
6869
{
6970
name: "minX",
7071
type: "number",
71-
description: "Minimum X coordinate (left boundary) of the viewport. If not provided, auto-fits to GeoJSON extent.",
72+
description:
73+
"Minimum X coordinate (left boundary) of the viewport. If not provided, auto-fits to GeoJSON extent.",
7274
required: false,
7375
hidden: true,
7476
},
7577
{
7678
name: "minY",
7779
type: "number",
78-
description: "Minimum Y coordinate (bottom boundary) of the viewport. If not provided, auto-fits to GeoJSON extent.",
80+
description:
81+
"Minimum Y coordinate (bottom boundary) of the viewport. If not provided, auto-fits to GeoJSON extent.",
7982
required: false,
8083
hidden: true,
8184
},
8285
{
8386
name: "maxX",
8487
type: "number",
85-
description: "Maximum X coordinate (right boundary) of the viewport. If not provided, auto-fits to GeoJSON extent.",
88+
description:
89+
"Maximum X coordinate (right boundary) of the viewport. If not provided, auto-fits to GeoJSON extent.",
8690
required: false,
8791
hidden: true,
8892
},
8993
{
9094
name: "maxY",
9195
type: "number",
92-
description: "Maximum Y coordinate (top boundary) of the viewport. If not provided, auto-fits to GeoJSON extent.",
96+
description:
97+
"Maximum Y coordinate (top boundary) of the viewport. If not provided, auto-fits to GeoJSON extent.",
9398
required: false,
9499
hidden: true,
95100
},
@@ -145,7 +150,9 @@ export class GeoJsonToSvgNode extends ExecutableNode {
145150
}
146151

147152
if (result.paths.length === 0) {
148-
return this.createErrorResult("Failed to generate SVG paths from GeoJSON");
153+
return this.createErrorResult(
154+
"Failed to generate SVG paths from GeoJSON"
155+
);
149156
}
150157

151158
// Convert SVG string to Uint8Array
@@ -159,7 +166,9 @@ export class GeoJsonToSvgNode extends ExecutableNode {
159166
});
160167
} catch (err) {
161168
const error = err as Error;
162-
return this.createErrorResult(`Error rendering GeoJSON to SVG: ${error.message}`);
169+
return this.createErrorResult(
170+
`Error rendering GeoJSON to SVG: ${error.message}`
171+
);
163172
}
164173
}
165-
}
174+
}

apps/api/src/nodes/image/svg-to-png-node.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { NodeContext } from "../types";
55
import { SvgToPngNode } from "./svg-to-png-node";
66

77
describe("SvgToPngNode", () => {
8-
const simpleSvg = '<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>';
8+
const simpleSvg =
9+
'<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>';
910
const simpleSvgImage = {
1011
data: new TextEncoder().encode(simpleSvg),
1112
mimeType: "image/svg+xml",
@@ -181,7 +182,7 @@ describe("SvgToPngNode", () => {
181182
} as unknown as Node);
182183

183184
const nonSvgImage = {
184-
data: new Uint8Array([0x89, 0x50, 0x4E, 0x47]), // PNG header
185+
data: new Uint8Array([0x89, 0x50, 0x4e, 0x47]), // PNG header
185186
mimeType: "image/png",
186187
};
187188

@@ -197,4 +198,4 @@ describe("SvgToPngNode", () => {
197198
expect(result.status).toBe("error");
198199
expect(result.error).toContain("Input must be SVG content");
199200
});
200-
});
201+
});

apps/api/src/nodes/image/svg-to-png-node.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ export class SvgToPngNode extends ExecutableNode {
1111
id: "svg-to-png",
1212
name: "SVG to PNG",
1313
type: "svg-to-png",
14-
description:
15-
"Renders SVG content to PNG format using the Resvg library. Accepts SVG image input from GeoJSON to SVG node.",
14+
description: "Renders SVG content to PNG format using the Resvg library.",
1615
tags: ["Image"],
1716
icon: "file-image", // Icon suggesting image conversion
1817
inlinable: true,
@@ -46,7 +45,8 @@ export class SvgToPngNode extends ExecutableNode {
4645
{
4746
name: "backgroundColor",
4847
type: "string",
49-
description: "Background color (e.g., 'white', 'transparent', '#FF0000').",
48+
description:
49+
"Background color (e.g., 'white', 'transparent', '#FF0000').",
5050
required: false,
5151
value: "transparent",
5252
hidden: true,
@@ -73,7 +73,9 @@ export class SvgToPngNode extends ExecutableNode {
7373

7474
// Check if it's SVG content
7575
if (svgInput.mimeType !== "image/svg+xml") {
76-
return this.createErrorResult("Input must be SVG content (image/svg+xml).");
76+
return this.createErrorResult(
77+
"Input must be SVG content (image/svg+xml)."
78+
);
7779
}
7880

7981
// Convert Uint8Array to string
@@ -86,15 +88,20 @@ export class SvgToPngNode extends ExecutableNode {
8688
const width = inputs.width as number | undefined;
8789
const height = inputs.height as number | undefined;
8890
const scale = (inputs.scale as number) || 1.0;
89-
const backgroundColor = (inputs.backgroundColor as string) || "transparent";
91+
const backgroundColor =
92+
(inputs.backgroundColor as string) || "transparent";
9093

9194
// Validate numeric inputs
9295
if (width !== undefined && (width <= 0 || width > 8192)) {
93-
return this.createErrorResult("Width must be between 1 and 8192 pixels.");
96+
return this.createErrorResult(
97+
"Width must be between 1 and 8192 pixels."
98+
);
9499
}
95100

96101
if (height !== undefined && (height <= 0 || height > 8192)) {
97-
return this.createErrorResult("Height must be between 1 and 8192 pixels.");
102+
return this.createErrorResult(
103+
"Height must be between 1 and 8192 pixels."
104+
);
98105
}
99106

100107
if (scale <= 0 || scale > 10) {
@@ -145,7 +152,9 @@ export class SvgToPngNode extends ExecutableNode {
145152

146153
return this.createSuccessResult({ image: imageParameter });
147154
} catch (error) {
148-
return this.createErrorResult(`Failed to render SVG: ${error instanceof Error ? error.message : String(error)}`);
155+
return this.createErrorResult(
156+
`Failed to render SVG: ${error instanceof Error ? error.message : String(error)}`
157+
);
149158
}
150159
}
151-
}
160+
}

apps/api/src/nodes/json/json-to-geojson-node.test.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { describe, expect, it } from "vitest";
21
import { Node } from "@dafthunk/types";
2+
import { describe, expect, it } from "vitest";
33

4-
import { JsonToGeojsonNode } from "./json-to-geojson-node";
54
import { NodeContext } from "../types";
5+
import { JsonToGeojsonNode } from "./json-to-geojson-node";
66

77
describe("JsonToGeojsonNode", () => {
88
const createMockContext = (inputs: Record<string, any>): NodeContext => ({
99
nodeId: "test-node",
10-
workflowId: "test-workflow",
10+
workflowId: "test-workflow",
1111
organizationId: "test-org",
1212
inputs,
1313
env: {} as any,
@@ -44,7 +44,11 @@ describe("JsonToGeojsonNode", () => {
4444
const node = createNode();
4545
const lineString = {
4646
type: "LineString",
47-
coordinates: [[0, 0], [10, 10], [20, 0]],
47+
coordinates: [
48+
[0, 0],
49+
[10, 10],
50+
[20, 0],
51+
],
4852
};
4953

5054
const context = createMockContext({ json: lineString });
@@ -58,7 +62,15 @@ describe("JsonToGeojsonNode", () => {
5862
const node = createNode();
5963
const polygon = {
6064
type: "Polygon",
61-
coordinates: [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]],
65+
coordinates: [
66+
[
67+
[0, 0],
68+
[10, 0],
69+
[10, 10],
70+
[0, 10],
71+
[0, 0],
72+
],
73+
],
6274
};
6375

6476
const context = createMockContext({ json: polygon });
@@ -225,8 +237,8 @@ describe("JsonToGeojsonNode", () => {
225237

226238
it("should return error for missing type property", async () => {
227239
const node = createNode();
228-
const context = createMockContext({
229-
json: { coordinates: [10, 20] }
240+
const context = createMockContext({
241+
json: { coordinates: [10, 20] },
230242
});
231243

232244
const result = await node.execute(context);
@@ -237,8 +249,8 @@ describe("JsonToGeojsonNode", () => {
237249

238250
it("should return error for invalid GeoJSON type", async () => {
239251
const node = createNode();
240-
const context = createMockContext({
241-
json: { type: "InvalidType", coordinates: [10, 20] }
252+
const context = createMockContext({
253+
json: { type: "InvalidType", coordinates: [10, 20] },
242254
});
243255

244256
const result = await node.execute(context);
@@ -249,8 +261,8 @@ describe("JsonToGeojsonNode", () => {
249261

250262
it("should return error for invalid geometry structure", async () => {
251263
const node = createNode();
252-
const context = createMockContext({
253-
json: { type: "Point", coordinates: "not an array" }
264+
const context = createMockContext({
265+
json: { type: "Point", coordinates: "not an array" },
254266
});
255267

256268
const result = await node.execute(context);
@@ -259,4 +271,4 @@ describe("JsonToGeojsonNode", () => {
259271
expect(result.error).toContain("Invalid GeoJSON format");
260272
});
261273
});
262-
});
274+
});

0 commit comments

Comments
 (0)