Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 50 additions & 6 deletions .monorepolint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const PACKAGES = []; // packages that aren't @turf/turf
const MAIN_PACKAGE = "@turf/turf";

const TAPE_PACKAGES = []; // packages that have tape tests
const NODE_TEST_PACKAGES = []; // projects that use node's native test runner
const TYPES_PACKAGES = []; // packages that have types tests
const TSTYCHE_PACKAGES = []; // packages that use tstyche for type tests.

Expand All @@ -32,8 +33,16 @@ for (const pk of await fs.readdir(packagesPath)) {

PACKAGES.push(name);

if (existsSync(path.join(pk, "test.js"))) {
TAPE_PACKAGES.push(name);
if (existsSync(path.join(packagesPath, pk, "test.ts"))) {
const testFileContents = await fs.readFile(
path.join(packagesPath, pk, "test.ts"),
"utf-8"
);
if (testFileContents.includes(`from "tape"`)) {
TAPE_PACKAGES.push(name);
} else {
NODE_TEST_PACKAGES.push(name);
}
}

if (existsSync(path.join(packagesPath, pk, "types.ts"))) {
Expand Down Expand Up @@ -198,11 +207,23 @@ export default {
scripts: {
bench: "tsx bench.ts",
"test:tape": "tsx test.ts",
"test:node": REMOVE,
},
},
includePackages: TAPE_PACKAGES,
}),

packageScript({
options: {
scripts: {
bench: "node bench.ts",
"test:node": "node --test",
"test:tape": REMOVE,
},
},
includePackages: NODE_TEST_PACKAGES,
}),

packageScript({
options: {
scripts: {
Expand Down Expand Up @@ -233,20 +254,43 @@ export default {
},
},
includePackages: PACKAGES,
excludePackages: NODE_TEST_PACKAGES,
}),

requireDependency({
options: {
dependencies: {
tslib: "catalog:",
devDependencies: {
tape: "catalog:",
"@types/tape": "catalog:",
},
},
includePackages: TAPE_PACKAGES,
}),

requireDependency({
options: {
devDependencies: {
"@types/benchmark": REMOVE,
"@types/tape": REMOVE,
benchmark: REMOVE,
"load-json-file": REMOVE,
tape: REMOVE,
tsx: REMOVE,
"write-json-file": REMOVE,
},
},
includePackages: NODE_TEST_PACKAGES,
}),

requireDependency({
options: {
devDependencies: {
"@types/benchmark": "catalog:",
"@types/tape": "catalog:",
typescript: "catalog:",
benchmark: "catalog:",
},
},
includePackages: PACKAGES,
excludePackages: NODE_TEST_PACKAGES,
}),

requireDependency({
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
"@monorepolint/config": "0.6.0-alpha.6",
"@monorepolint/core": "0.6.0-alpha.6",
"@monorepolint/rules": "0.6.0-alpha.6",
"@types/benchmark": "^2.1.5",
"@types/node": "22.15.3",
"acorn": "^8.14.1",
"benchmark": "^2.1.4",
"camelcase": "^8.0.0",
"d3-queue": "*",
"decamelize": "^6.0.0",
Expand Down
60 changes: 12 additions & 48 deletions packages/turf-center/bench.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,12 @@
import path from "path";
import { fileURLToPath } from "url";
import { glob } from "glob";
import { loadJsonFileSync } from "load-json-file";
import Benchmark from "benchmark";
import { center } from "./index.js";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const fixtures = glob
.sync(path.join(__dirname, "test", "in", "*.geojson"))
.map((input) => {
return {
name: path.parse(input).name,
geojson: loadJsonFileSync(input),
};
});

/**
* Single Process Benchmark
*
* feature-collection: 0.445ms
* imbalanced-polygon: 0.051ms
* linestring: 0.027ms
* point: 0.011ms
* polygon: 0.013ms
*/
for (const { name, geojson } of fixtures) {
console.time(name);
center(geojson);
console.timeEnd(name);
}

/**
* Benchmark Results
*
* feature-collection x 2,786,700 ops/sec ±1.50% (83 runs sampled)
* imbalanced-polygon x 1,364,145 ops/sec ±3.33% (76 runs sampled)
* linestring x 4,104,106 ops/sec ±4.16% (81 runs sampled)
* point x 4,901,692 ops/sec ±5.23% (81 runs sampled)
* polygon x 2,862,759 ops/sec ±1.14% (86 runs sampled)
*/
const suite = new Benchmark.Suite("turf-center");
for (const { name, geojson } of fixtures) {
suite.add(name, () => center(geojson));
}

suite.on("cycle", (e) => console.log(String(e.target))).run();
import { center } from "./index.ts";
import { benchFixtures } from "../../support/benchFixtures.mts";

// Benchmark Results
// feature-collection.geojson x 27,241,658 ops/sec ±0.34% (99 runs sampled)
// imbalanced-polygon.geojson x 14,679,583 ops/sec ±0.27% (98 runs sampled)
// linestring.geojson x 34,199,495 ops/sec ±0.52% (95 runs sampled)
// point.geojson x 52,230,993 ops/sec ±0.70% (96 runs sampled)
// points-with-weights.geojson x 24,802,237 ops/sec ±0.33% (100 runs sampled)
// polygon-without-weights.geojson x 18,423,881 ops/sec ±0.28% (100 runs sampled)
// polygon.geojson x 24,990,920 ops/sec ±0.45% (99 runs sampled)
await benchFixtures("turf-center", (input) => center(input));
4 changes: 2 additions & 2 deletions packages/turf-center/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BBox, Feature, GeoJsonProperties, Point } from "geojson";
import type { BBox, Feature, GeoJsonProperties, Point } from "geojson";
import { bbox } from "@turf/bbox";
import { point, Id, AllGeoJSON } from "@turf/helpers";
import { point, type Id, type AllGeoJSON } from "@turf/helpers";

/**
* Takes a {@link Feature} or {@link FeatureCollection} and returns the absolute center point of all features.
Expand Down
13 changes: 3 additions & 10 deletions packages/turf-center/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,17 @@
"dist"
],
"scripts": {
"bench": "tsx bench.ts",
"bench": "node bench.ts",
"build": "tsup --config ../../tsup.config.ts",
"test": "pnpm run /test:.*/",
"test:tape": "tsx test.ts",
"test:node": "node --test",
"test:types": "tsc --esModuleInterop --module node16 --moduleResolution node16 --noEmit --strict types.ts"
},
"devDependencies": {
"@turf/bbox-polygon": "workspace:*",
"@turf/meta": "workspace:*",
"@types/benchmark": "catalog:",
"@types/tape": "catalog:",
"benchmark": "catalog:",
"load-json-file": "^7.0.1",
"tape": "catalog:",
"tsup": "catalog:",
"tsx": "catalog:",
"typescript": "catalog:",
"write-json-file": "^6.0.0"
"typescript": "catalog:"
},
"dependencies": {
"@turf/bbox": "workspace:*",
Expand Down
86 changes: 36 additions & 50 deletions packages/turf-center/test.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,47 @@
import test from "tape";
import { glob } from "glob";
import path from "path";
import { fileURLToPath } from "url";
import { loadJsonFileSync } from "load-json-file";
import { writeJsonFileSync } from "write-json-file";
import { bboxPolygon } from "@turf/bbox-polygon";
import { bbox } from "@turf/bbox";
import { featureEach, coordEach } from "@turf/meta";
import { lineString, featureCollection } from "@turf/helpers";
import { center } from "./index.js";
import test from "node:test";
import center from "./index.ts";
import { featureCollection, lineString } from "@turf/helpers";
import { coordEach, featureEach } from "@turf/meta";
import bboxPolygon from "@turf/bbox-polygon";
import bbox from "@turf/bbox";
import type { Geometry } from "geojson";
import { testFixtures } from "../../support/testFixtures.mts";
import assert from "assert";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
await test("center fixtures", async (t) => {
await testFixtures(t, (geojson) => {
const options = geojson.options || {};
options.properties = { "marker-symbol": "star", "marker-color": "#F00" };
const centered = center(geojson, options);

test("turf-center", (t) => {
glob
.sync(path.join(__dirname, "test", "in", "*.geojson"))
.forEach((filepath) => {
const geojson = loadJsonFileSync(filepath);
const options = geojson.options || {};
options.properties = { "marker-symbol": "star", "marker-color": "#F00" };
const centered = center(geojson, options);
// Display Results
const results = featureCollection<Geometry>([centered]);
featureEach(geojson, (feature) => results.features.push(feature));
const extent = bboxPolygon(bbox(geojson));
extent.properties = {
stroke: "#00F",
"stroke-width": 1,
"fill-opacity": 0,
};
coordEach(extent, (coord) =>
results.features.push(
lineString([coord, centered.geometry.coordinates], {
stroke: "#00F",
"stroke-width": 1,
})
)
);
results.features.push(extent);

// Display Results
const results = featureCollection([centered]);
featureEach(geojson, (feature) => results.features.push(feature));
const extent = bboxPolygon(bbox(geojson));
extent.properties = {
stroke: "#00F",
"stroke-width": 1,
"fill-opacity": 0,
};
coordEach(extent, (coord) =>
results.features.push(
lineString([coord, centered.geometry.coordinates], {
stroke: "#00F",
"stroke-width": 1,
})
)
);
results.features.push(extent);

const out = filepath.replace(
path.join("test", "in"),
path.join("test", "out")
);
if (process.env.REGEN) writeJsonFileSync(out, results);
t.deepEqual(results, loadJsonFileSync(out), path.parse(filepath).name);
});
t.end();
return results;
});
});

test("turf-center -- properties", (t) => {
test("turf-center -- properties", () => {
const line = lineString([
[0, 0],
[1, 1],
]);
const pt = center(line, { properties: { foo: "bar" } });
t.equal(pt.properties.foo, "bar", "translate properties");
t.end();
assert.strictEqual(pt.properties.foo, "bar", "translate properties");
});
27 changes: 6 additions & 21 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions support/benchFixtures.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import path from "path";
import { readdir, readFile } from "node:fs/promises";
import Benchmark from "benchmark";

export async function benchFixtures(pkgName: string, fn: (input: any) => void) {
const suite = new Benchmark.Suite(pkgName);
const fixturesPath = path.join(process.cwd(), "test", "in");
for (const file of await readdir(fixturesPath)) {
const inputPath = path.join(fixturesPath, file);
const inputData = JSON.parse(await readFile(inputPath, "utf-8"));
suite.add(file, () => fn(inputData));
}

suite.on("cycle", (e: any) => console.log(String(e.target))).run();
}
Loading
Loading