geoplegma-js 0.0.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.
- package/README.md +27 -0
- package/dist/index.cjs +110 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +87 -0
- package/dist/index.js.map +1 -0
- package/dist/native/browser.js +1 -0
- package/dist/native/index.d.ts +64 -0
- package/dist/native/napi.node +0 -0
- package/dist/native/napi.wasi-browser.js +61 -0
- package/dist/native/napi.wasi.cjs +113 -0
- package/dist/native/wasi-worker-browser.mjs +32 -0
- package/dist/native/wasi-worker.mjs +63 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# tsdown-starter
|
|
2
|
+
|
|
3
|
+
A starter for creating a TypeScript package.
|
|
4
|
+
|
|
5
|
+
## Development
|
|
6
|
+
|
|
7
|
+
- Install dependencies:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- Run the unit tests:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm run test
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- Build the library:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm run build
|
|
23
|
+
```
|
|
24
|
+
The `build` script will build a new folder `dist` with the bundled files inside, and copy the index.node and index.d.ts files into that same folder. This folder will be used in the npm library as the source code files.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
NOTE: Eventually a github job will be added for this statement workflow.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
const module$1 = __toESM(require("module"));
|
|
25
|
+
const url = __toESM(require("url"));
|
|
26
|
+
const path = __toESM(require("path"));
|
|
27
|
+
|
|
28
|
+
//#region src/utils.ts
|
|
29
|
+
function decodeZones(zones) {
|
|
30
|
+
const decodedZones = [];
|
|
31
|
+
const bufferIds = Buffer.from(zones.utf8Ids);
|
|
32
|
+
const bufferCoords = new Float64Array(zones.regionCoords);
|
|
33
|
+
for (let i = 0; i < zones.idOffsets.length; i++) {
|
|
34
|
+
const start = zones.idOffsets[i];
|
|
35
|
+
const end = i + 1 < zones.idOffsets.length ? zones.idOffsets[i + 1] : bufferIds.length;
|
|
36
|
+
const id = new TextDecoder("utf-8").decode(bufferIds.subarray(start, end));
|
|
37
|
+
const vertexCount = zones.vertexCount[i];
|
|
38
|
+
const regionStart = zones.regionOffsets[i];
|
|
39
|
+
const bufferRegion = bufferCoords.subarray(regionStart, regionStart + vertexCount * 2);
|
|
40
|
+
const region = [];
|
|
41
|
+
for (let j = 0; j < bufferRegion.length; j += 2) region.push([bufferRegion[j], bufferRegion[j + 1]]);
|
|
42
|
+
const children = decodeChildren(zones, i);
|
|
43
|
+
const neighbors = decodeNeighbors(zones, i);
|
|
44
|
+
decodedZones.push({
|
|
45
|
+
id,
|
|
46
|
+
center: [zones.centerX[i], zones.centerY[i]],
|
|
47
|
+
vertexCount,
|
|
48
|
+
region,
|
|
49
|
+
children,
|
|
50
|
+
neighbors
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return decodedZones;
|
|
54
|
+
}
|
|
55
|
+
function decodeChildren(jsZones, zoneIndex) {
|
|
56
|
+
const children = [];
|
|
57
|
+
const start = jsZones.childrenOffsets[zoneIndex];
|
|
58
|
+
const end = zoneIndex + 1 < jsZones.childrenOffsets.length ? jsZones.childrenOffsets[zoneIndex + 1] : jsZones.childrenIdOffsets.length;
|
|
59
|
+
const buffer = new Float64Array(jsZones.childrenUtf8Ids);
|
|
60
|
+
for (let i = start; i < end; i++) {
|
|
61
|
+
const childStart = jsZones.childrenIdOffsets[i];
|
|
62
|
+
const childEnd = i + 1 < jsZones.childrenIdOffsets.length ? jsZones.childrenIdOffsets[i + 1] : jsZones.childrenUtf8Ids.length;
|
|
63
|
+
children.push(new TextDecoder("utf-8").decode(buffer.subarray(childStart, childEnd)));
|
|
64
|
+
}
|
|
65
|
+
return children;
|
|
66
|
+
}
|
|
67
|
+
function decodeNeighbors(jsZones, zoneIndex) {
|
|
68
|
+
const neighbors = [];
|
|
69
|
+
const start = jsZones.neighborsOffsets[zoneIndex];
|
|
70
|
+
const end = zoneIndex + 1 < jsZones.neighborsOffsets.length ? jsZones.neighborsOffsets[zoneIndex + 1] : jsZones.neighborsIdOffsets.length;
|
|
71
|
+
const buffer = new Float64Array(jsZones.neighborsUtf8Ids);
|
|
72
|
+
for (let i = start; i < end; i++) {
|
|
73
|
+
const nStart = jsZones.neighborsIdOffsets[i];
|
|
74
|
+
const nEnd = i + 1 < jsZones.neighborsIdOffsets.length ? jsZones.neighborsIdOffsets[i + 1] : jsZones.neighborsUtf8Ids.length;
|
|
75
|
+
neighbors.push(new TextDecoder("utf-8").decode(buffer.subarray(nStart, nEnd)));
|
|
76
|
+
}
|
|
77
|
+
return neighbors;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/native-loader.ts
|
|
82
|
+
const __dirname$1 = path.default.dirname((0, url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
|
|
83
|
+
const require$1 = (0, module$1.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
84
|
+
const bindings = require$1(path.default.join(__dirname$1, "native/napi.node"));
|
|
85
|
+
var native_loader_default = bindings;
|
|
86
|
+
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/extend.ts
|
|
89
|
+
const { Dggrs: Aux } = native_loader_default;
|
|
90
|
+
var Dggrs = class extends Aux {
|
|
91
|
+
constructor(name) {
|
|
92
|
+
super(name);
|
|
93
|
+
}
|
|
94
|
+
zonesFromBbox(refinement_level, bbox, config) {
|
|
95
|
+
return decodeZones(super.zonesFromBbox(refinement_level, bbox, config));
|
|
96
|
+
}
|
|
97
|
+
zoneFromPoint(refinement_level, point, config) {
|
|
98
|
+
return decodeZones(super.zoneFromPoint(refinement_level, point, config));
|
|
99
|
+
}
|
|
100
|
+
zonesFromParent(relative_depth, parentZoneId, config) {
|
|
101
|
+
return decodeZones(super.zonesFromParent(relative_depth, parentZoneId, config));
|
|
102
|
+
}
|
|
103
|
+
zoneFromId(zoneId, config) {
|
|
104
|
+
return decodeZones(super.zoneFromId(zoneId, config));
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
//#endregion
|
|
109
|
+
exports.Dggrs = Dggrs;
|
|
110
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["zones: any","decodedZones: any","jsZones: any","zoneIndex: any","__dirname","require","bindings","name: string","refinement_level: number","bbox?: number[][]","config?: Config","point?: number[]","relative_depth: number","parentZoneId: string","zoneId: string"],"sources":["../src/utils.ts","../src/native-loader.ts","../src/extend.ts"],"sourcesContent":["// Copyright 2025 contributors to the GeoPlegma project.\n// Originally authored by João Manuel (GeoInsight GmbH, joao.manuel@geoinsight.ai)\n//\n// Licenced under the Apache Licence, Version 2.0 <LICENCE-APACHE or\n// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n// <LICENCE-MIT or http://opensource.org/licenses/MIT>, at your\n// discretion. This file may not be copied, modified, or distributed\n// except according to those terms.\n\n// for now the type is `any`, I will add other types in other PRs\nexport function decodeZones(zones: any) {\n const decodedZones: any = [];\n const bufferIds = Buffer.from(zones.utf8Ids);\n const bufferCoords = new Float64Array(zones.regionCoords);\n\n for (let i = 0; i < zones.idOffsets.length; i++) {\n const start = zones.idOffsets[i];\n const end =\n i + 1 < zones.idOffsets.length\n ? zones.idOffsets[i + 1]\n : bufferIds.length;\n const id = new TextDecoder(\"utf-8\").decode(bufferIds.subarray(start, end));\n\n // region coords\n const vertexCount = zones.vertexCount[i];\n const regionStart = zones.regionOffsets[i];\n const bufferRegion = bufferCoords.subarray(\n regionStart,\n regionStart + vertexCount * 2\n );\n const region = [];\n for (let j = 0; j < bufferRegion.length; j += 2) {\n region.push([bufferRegion[j], bufferRegion[j + 1]]);\n }\n\n // children\n const children = decodeChildren(zones, i);\n\n // neighbors\n const neighbors = decodeNeighbors(zones, i);\n\n decodedZones.push({\n id,\n center: [zones.centerX[i], zones.centerY[i]],\n vertexCount,\n region,\n children,\n neighbors,\n });\n }\n\n return decodedZones;\n}\n\nexport function decodeChildren(jsZones: any, zoneIndex: any) {\n const children = [];\n const start = jsZones.childrenOffsets[zoneIndex];\n const end =\n zoneIndex + 1 < jsZones.childrenOffsets.length\n ? jsZones.childrenOffsets[zoneIndex + 1]\n : jsZones.childrenIdOffsets.length;\n const buffer = new Float64Array(jsZones.childrenUtf8Ids);\n\n // childrenOffsets -> [0, 6, 12,...]\n // childrenIdOffsets -> [0, 18, 36,...]\n for (let i = start; i < end; i++) {\n const childStart = jsZones.childrenIdOffsets[i];\n const childEnd =\n i + 1 < jsZones.childrenIdOffsets.length\n ? jsZones.childrenIdOffsets[i + 1]\n : jsZones.childrenUtf8Ids.length;\n children.push(\n new TextDecoder(\"utf-8\").decode(buffer.subarray(childStart, childEnd))\n );\n }\n\n return children;\n}\n\nexport function decodeNeighbors(jsZones: any, zoneIndex: any) {\n const neighbors = [];\n const start = jsZones.neighborsOffsets[zoneIndex];\n const end =\n zoneIndex + 1 < jsZones.neighborsOffsets.length\n ? jsZones.neighborsOffsets[zoneIndex + 1]\n : jsZones.neighborsIdOffsets.length;\n\n const buffer = new Float64Array(jsZones.neighborsUtf8Ids);\n for (let i = start; i < end; i++) {\n const nStart = jsZones.neighborsIdOffsets[i];\n const nEnd =\n i + 1 < jsZones.neighborsIdOffsets.length\n ? jsZones.neighborsIdOffsets[i + 1]\n : jsZones.neighborsUtf8Ids.length;\n neighbors.push(\n new TextDecoder(\"utf-8\").decode(buffer.subarray(nStart, nEnd))\n );\n }\n return neighbors;\n}\n","// Copyright 2025 contributors to the GeoPlegma project.\n// Originally authored by João Manuel (GeoInsight GmbH, joao.manuel@geoinsight.ai)\n//\n// Licenced under the Apache Licence, Version 2.0 <LICENCE-APACHE or\n// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n// <LICENCE-MIT or http://opensource.org/licenses/MIT>, at your\n// discretion. This file may not be copied, modified, or distributed\n// except according to those terms.\n\nimport { createRequire } from \"module\";\nimport { fileURLToPath } from \"url\";\nimport path from \"path\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst require = createRequire(import.meta.url);\n\nconst bindings = require(path.join(__dirname, \"native/napi.node\"));\n\nexport default bindings;\n","// Copyright 2025 contributors to the GeoPlegma project.\n// Originally authored by João Manuel (GeoInsight GmbH, joao.manuel@geoinsight.ai)\n//\n// Licenced under the Apache Licence, Version 2.0 <LICENCE-APACHE or\n// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n// <LICENCE-MIT or http://opensource.org/licenses/MIT>, at your\n// discretion. This file may not be copied, modified, or distributed\n// except according to those terms.\n\nimport { decodeZones } from \"./utils\";\n\nimport bindings from \"./native-loader\";\n\nconst { Dggrs: Aux } = bindings;\n\ninterface Config {\n region: boolean;\n center: boolean;\n vertexCount: boolean;\n children: boolean;\n neighbors: boolean;\n areaSqm: boolean;\n densify: boolean;\n}\n\nexport class Dggrs extends Aux {\n constructor(name: string) {\n super(name);\n }\n zonesFromBbox(refinement_level: number, bbox?: number[][], config?: Config) {\n return decodeZones(super.zonesFromBbox(refinement_level, bbox, config));\n }\n zoneFromPoint(refinement_level: number, point?: number[], config?: Config) {\n return decodeZones(super.zoneFromPoint(refinement_level, point, config));\n }\n zonesFromParent(\n relative_depth: number,\n parentZoneId: string,\n config?: Config\n ): any {\n return decodeZones(\n super.zonesFromParent(relative_depth, parentZoneId, config)\n );\n }\n zoneFromId(zoneId: string, config?: Config): any {\n return decodeZones(super.zoneFromId(zoneId, config));\n }\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/extend.d.ts
|
|
2
|
+
declare const Aux: any;
|
|
3
|
+
interface Config {
|
|
4
|
+
region: boolean;
|
|
5
|
+
center: boolean;
|
|
6
|
+
vertexCount: boolean;
|
|
7
|
+
children: boolean;
|
|
8
|
+
neighbors: boolean;
|
|
9
|
+
areaSqm: boolean;
|
|
10
|
+
densify: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare class Dggrs extends Aux {
|
|
13
|
+
constructor(name: string);
|
|
14
|
+
zonesFromBbox(refinement_level: number, bbox?: number[][], config?: Config): any;
|
|
15
|
+
zoneFromPoint(refinement_level: number, point?: number[], config?: Config): any;
|
|
16
|
+
zonesFromParent(relative_depth: number, parentZoneId: string, config?: Config): any;
|
|
17
|
+
zoneFromId(zoneId: string, config?: Config): any;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { Dggrs };
|
|
21
|
+
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/extend.d.ts
|
|
2
|
+
declare const Aux: any;
|
|
3
|
+
interface Config {
|
|
4
|
+
region: boolean;
|
|
5
|
+
center: boolean;
|
|
6
|
+
vertexCount: boolean;
|
|
7
|
+
children: boolean;
|
|
8
|
+
neighbors: boolean;
|
|
9
|
+
areaSqm: boolean;
|
|
10
|
+
densify: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare class Dggrs extends Aux {
|
|
13
|
+
constructor(name: string);
|
|
14
|
+
zonesFromBbox(refinement_level: number, bbox?: number[][], config?: Config): any;
|
|
15
|
+
zoneFromPoint(refinement_level: number, point?: number[], config?: Config): any;
|
|
16
|
+
zonesFromParent(relative_depth: number, parentZoneId: string, config?: Config): any;
|
|
17
|
+
zoneFromId(zoneId: string, config?: Config): any;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { Dggrs };
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createRequire } from "module";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
//#region src/utils.ts
|
|
6
|
+
function decodeZones(zones) {
|
|
7
|
+
const decodedZones = [];
|
|
8
|
+
const bufferIds = Buffer.from(zones.utf8Ids);
|
|
9
|
+
const bufferCoords = new Float64Array(zones.regionCoords);
|
|
10
|
+
for (let i = 0; i < zones.idOffsets.length; i++) {
|
|
11
|
+
const start = zones.idOffsets[i];
|
|
12
|
+
const end = i + 1 < zones.idOffsets.length ? zones.idOffsets[i + 1] : bufferIds.length;
|
|
13
|
+
const id = new TextDecoder("utf-8").decode(bufferIds.subarray(start, end));
|
|
14
|
+
const vertexCount = zones.vertexCount[i];
|
|
15
|
+
const regionStart = zones.regionOffsets[i];
|
|
16
|
+
const bufferRegion = bufferCoords.subarray(regionStart, regionStart + vertexCount * 2);
|
|
17
|
+
const region = [];
|
|
18
|
+
for (let j = 0; j < bufferRegion.length; j += 2) region.push([bufferRegion[j], bufferRegion[j + 1]]);
|
|
19
|
+
const children = decodeChildren(zones, i);
|
|
20
|
+
const neighbors = decodeNeighbors(zones, i);
|
|
21
|
+
decodedZones.push({
|
|
22
|
+
id,
|
|
23
|
+
center: [zones.centerX[i], zones.centerY[i]],
|
|
24
|
+
vertexCount,
|
|
25
|
+
region,
|
|
26
|
+
children,
|
|
27
|
+
neighbors
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return decodedZones;
|
|
31
|
+
}
|
|
32
|
+
function decodeChildren(jsZones, zoneIndex) {
|
|
33
|
+
const children = [];
|
|
34
|
+
const start = jsZones.childrenOffsets[zoneIndex];
|
|
35
|
+
const end = zoneIndex + 1 < jsZones.childrenOffsets.length ? jsZones.childrenOffsets[zoneIndex + 1] : jsZones.childrenIdOffsets.length;
|
|
36
|
+
const buffer = new Float64Array(jsZones.childrenUtf8Ids);
|
|
37
|
+
for (let i = start; i < end; i++) {
|
|
38
|
+
const childStart = jsZones.childrenIdOffsets[i];
|
|
39
|
+
const childEnd = i + 1 < jsZones.childrenIdOffsets.length ? jsZones.childrenIdOffsets[i + 1] : jsZones.childrenUtf8Ids.length;
|
|
40
|
+
children.push(new TextDecoder("utf-8").decode(buffer.subarray(childStart, childEnd)));
|
|
41
|
+
}
|
|
42
|
+
return children;
|
|
43
|
+
}
|
|
44
|
+
function decodeNeighbors(jsZones, zoneIndex) {
|
|
45
|
+
const neighbors = [];
|
|
46
|
+
const start = jsZones.neighborsOffsets[zoneIndex];
|
|
47
|
+
const end = zoneIndex + 1 < jsZones.neighborsOffsets.length ? jsZones.neighborsOffsets[zoneIndex + 1] : jsZones.neighborsIdOffsets.length;
|
|
48
|
+
const buffer = new Float64Array(jsZones.neighborsUtf8Ids);
|
|
49
|
+
for (let i = start; i < end; i++) {
|
|
50
|
+
const nStart = jsZones.neighborsIdOffsets[i];
|
|
51
|
+
const nEnd = i + 1 < jsZones.neighborsIdOffsets.length ? jsZones.neighborsIdOffsets[i + 1] : jsZones.neighborsUtf8Ids.length;
|
|
52
|
+
neighbors.push(new TextDecoder("utf-8").decode(buffer.subarray(nStart, nEnd)));
|
|
53
|
+
}
|
|
54
|
+
return neighbors;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/native-loader.ts
|
|
59
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
60
|
+
const require = createRequire(import.meta.url);
|
|
61
|
+
const bindings = require(path.join(__dirname, "native/napi.node"));
|
|
62
|
+
var native_loader_default = bindings;
|
|
63
|
+
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/extend.ts
|
|
66
|
+
const { Dggrs: Aux } = native_loader_default;
|
|
67
|
+
var Dggrs = class extends Aux {
|
|
68
|
+
constructor(name) {
|
|
69
|
+
super(name);
|
|
70
|
+
}
|
|
71
|
+
zonesFromBbox(refinement_level, bbox, config) {
|
|
72
|
+
return decodeZones(super.zonesFromBbox(refinement_level, bbox, config));
|
|
73
|
+
}
|
|
74
|
+
zoneFromPoint(refinement_level, point, config) {
|
|
75
|
+
return decodeZones(super.zoneFromPoint(refinement_level, point, config));
|
|
76
|
+
}
|
|
77
|
+
zonesFromParent(relative_depth, parentZoneId, config) {
|
|
78
|
+
return decodeZones(super.zonesFromParent(relative_depth, parentZoneId, config));
|
|
79
|
+
}
|
|
80
|
+
zoneFromId(zoneId, config) {
|
|
81
|
+
return decodeZones(super.zoneFromId(zoneId, config));
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { Dggrs };
|
|
87
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["zones: any","decodedZones: any","jsZones: any","zoneIndex: any","bindings","name: string","refinement_level: number","bbox?: number[][]","config?: Config","point?: number[]","relative_depth: number","parentZoneId: string","zoneId: string"],"sources":["../src/utils.ts","../src/native-loader.ts","../src/extend.ts"],"sourcesContent":["// Copyright 2025 contributors to the GeoPlegma project.\n// Originally authored by João Manuel (GeoInsight GmbH, joao.manuel@geoinsight.ai)\n//\n// Licenced under the Apache Licence, Version 2.0 <LICENCE-APACHE or\n// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n// <LICENCE-MIT or http://opensource.org/licenses/MIT>, at your\n// discretion. This file may not be copied, modified, or distributed\n// except according to those terms.\n\n// for now the type is `any`, I will add other types in other PRs\nexport function decodeZones(zones: any) {\n const decodedZones: any = [];\n const bufferIds = Buffer.from(zones.utf8Ids);\n const bufferCoords = new Float64Array(zones.regionCoords);\n\n for (let i = 0; i < zones.idOffsets.length; i++) {\n const start = zones.idOffsets[i];\n const end =\n i + 1 < zones.idOffsets.length\n ? zones.idOffsets[i + 1]\n : bufferIds.length;\n const id = new TextDecoder(\"utf-8\").decode(bufferIds.subarray(start, end));\n\n // region coords\n const vertexCount = zones.vertexCount[i];\n const regionStart = zones.regionOffsets[i];\n const bufferRegion = bufferCoords.subarray(\n regionStart,\n regionStart + vertexCount * 2\n );\n const region = [];\n for (let j = 0; j < bufferRegion.length; j += 2) {\n region.push([bufferRegion[j], bufferRegion[j + 1]]);\n }\n\n // children\n const children = decodeChildren(zones, i);\n\n // neighbors\n const neighbors = decodeNeighbors(zones, i);\n\n decodedZones.push({\n id,\n center: [zones.centerX[i], zones.centerY[i]],\n vertexCount,\n region,\n children,\n neighbors,\n });\n }\n\n return decodedZones;\n}\n\nexport function decodeChildren(jsZones: any, zoneIndex: any) {\n const children = [];\n const start = jsZones.childrenOffsets[zoneIndex];\n const end =\n zoneIndex + 1 < jsZones.childrenOffsets.length\n ? jsZones.childrenOffsets[zoneIndex + 1]\n : jsZones.childrenIdOffsets.length;\n const buffer = new Float64Array(jsZones.childrenUtf8Ids);\n\n // childrenOffsets -> [0, 6, 12,...]\n // childrenIdOffsets -> [0, 18, 36,...]\n for (let i = start; i < end; i++) {\n const childStart = jsZones.childrenIdOffsets[i];\n const childEnd =\n i + 1 < jsZones.childrenIdOffsets.length\n ? jsZones.childrenIdOffsets[i + 1]\n : jsZones.childrenUtf8Ids.length;\n children.push(\n new TextDecoder(\"utf-8\").decode(buffer.subarray(childStart, childEnd))\n );\n }\n\n return children;\n}\n\nexport function decodeNeighbors(jsZones: any, zoneIndex: any) {\n const neighbors = [];\n const start = jsZones.neighborsOffsets[zoneIndex];\n const end =\n zoneIndex + 1 < jsZones.neighborsOffsets.length\n ? jsZones.neighborsOffsets[zoneIndex + 1]\n : jsZones.neighborsIdOffsets.length;\n\n const buffer = new Float64Array(jsZones.neighborsUtf8Ids);\n for (let i = start; i < end; i++) {\n const nStart = jsZones.neighborsIdOffsets[i];\n const nEnd =\n i + 1 < jsZones.neighborsIdOffsets.length\n ? jsZones.neighborsIdOffsets[i + 1]\n : jsZones.neighborsUtf8Ids.length;\n neighbors.push(\n new TextDecoder(\"utf-8\").decode(buffer.subarray(nStart, nEnd))\n );\n }\n return neighbors;\n}\n","// Copyright 2025 contributors to the GeoPlegma project.\n// Originally authored by João Manuel (GeoInsight GmbH, joao.manuel@geoinsight.ai)\n//\n// Licenced under the Apache Licence, Version 2.0 <LICENCE-APACHE or\n// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n// <LICENCE-MIT or http://opensource.org/licenses/MIT>, at your\n// discretion. This file may not be copied, modified, or distributed\n// except according to those terms.\n\nimport { createRequire } from \"module\";\nimport { fileURLToPath } from \"url\";\nimport path from \"path\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst require = createRequire(import.meta.url);\n\nconst bindings = require(path.join(__dirname, \"native/napi.node\"));\n\nexport default bindings;\n","// Copyright 2025 contributors to the GeoPlegma project.\n// Originally authored by João Manuel (GeoInsight GmbH, joao.manuel@geoinsight.ai)\n//\n// Licenced under the Apache Licence, Version 2.0 <LICENCE-APACHE or\n// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n// <LICENCE-MIT or http://opensource.org/licenses/MIT>, at your\n// discretion. This file may not be copied, modified, or distributed\n// except according to those terms.\n\nimport { decodeZones } from \"./utils\";\n\nimport bindings from \"./native-loader\";\n\nconst { Dggrs: Aux } = bindings;\n\ninterface Config {\n region: boolean;\n center: boolean;\n vertexCount: boolean;\n children: boolean;\n neighbors: boolean;\n areaSqm: boolean;\n densify: boolean;\n}\n\nexport class Dggrs extends Aux {\n constructor(name: string) {\n super(name);\n }\n zonesFromBbox(refinement_level: number, bbox?: number[][], config?: Config) {\n return decodeZones(super.zonesFromBbox(refinement_level, bbox, config));\n }\n zoneFromPoint(refinement_level: number, point?: number[], config?: Config) {\n return decodeZones(super.zoneFromPoint(refinement_level, point, config));\n }\n zonesFromParent(\n relative_depth: number,\n parentZoneId: string,\n config?: Config\n ): any {\n return decodeZones(\n super.zonesFromParent(relative_depth, parentZoneId, config)\n );\n }\n zoneFromId(zoneId: string, config?: Config): any {\n return decodeZones(super.zoneFromId(zoneId, config));\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from 'js-wasm32-wasi'
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* auto-generated by NAPI-RS */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
export declare class Dggrs {
|
|
4
|
+
constructor(dggrs: string)
|
|
5
|
+
zonesFromBbox(refinementLevel: number, bbox?: Array<Array<number>> | undefined | null, config?: Config | undefined | null): FlatZones
|
|
6
|
+
zoneFromPoint(refinementLevel: number, point?: Array<number> | undefined | null, config?: Config | undefined | null): FlatZones
|
|
7
|
+
zonesFromParent(relativeDepth: number, parentZoneId: string, config?: Config | undefined | null): FlatZones
|
|
8
|
+
zoneFromId(zoneId: string, config?: Config | undefined | null): FlatZones
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Config {
|
|
12
|
+
region: boolean
|
|
13
|
+
center: boolean
|
|
14
|
+
vertexCount: boolean
|
|
15
|
+
children: boolean
|
|
16
|
+
neighbors: boolean
|
|
17
|
+
areaSqm: boolean
|
|
18
|
+
densify: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export declare function defaultConfig(): Config
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The Zone struct has nested heap allocations (String, Vec<(f64,f64)>, Vec<String>), which means:
|
|
25
|
+
* - Each String is 24 bytes (ptr, len, capacity) + heap data.
|
|
26
|
+
* - Each (f64, f64) is fine in Rust, but Vec<(f64,f64)> is not a flat Vec<f64> in wasm/napi-rs.
|
|
27
|
+
* - wasm/napi-rs will have to walk and serialize everything, which is slow for thousands of zones.
|
|
28
|
+
* No napi-rs overhead per zone — you pass one pointer + length per field instead of millions of small objects.
|
|
29
|
+
* Zero-copy — JS reads directly from WebAssembly memory.
|
|
30
|
+
* Keeps geometry-heavy Zone struct in Rust for efficient calculations.
|
|
31
|
+
* Scales to millions of zones without crashing the browser or blowing up memory usage.
|
|
32
|
+
* Tradeoff
|
|
33
|
+
* Pro: Hugely faster for large datasets
|
|
34
|
+
* Con: JS side reconstruction is manual — you need to decode UTF-8 strings from byte arrays using TextDecoder and use offset tables.
|
|
35
|
+
*/
|
|
36
|
+
export interface FlatZones {
|
|
37
|
+
idOffsets: Array<number>
|
|
38
|
+
utf8Ids: Array<number>
|
|
39
|
+
centerX: Array<number>
|
|
40
|
+
centerY: Array<number>
|
|
41
|
+
vertexCount: Array<number>
|
|
42
|
+
regionOffsets: Array<number>
|
|
43
|
+
regionCoords: Array<number>
|
|
44
|
+
childrenOffsets: Array<number>
|
|
45
|
+
childrenIdOffsets: Array<number>
|
|
46
|
+
childrenUtf8Ids: Array<number>
|
|
47
|
+
neighborsOffsets: Array<number>
|
|
48
|
+
neighborsIdOffsets: Array<number>
|
|
49
|
+
neighborsUtf8Ids: Array<number>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export declare const enum Id {
|
|
53
|
+
String = 'String',
|
|
54
|
+
U64 = 'U64'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface Zone {
|
|
58
|
+
id: Id
|
|
59
|
+
region: Array<Array<number>>
|
|
60
|
+
center: Array<number>
|
|
61
|
+
vertexCount: number
|
|
62
|
+
children?: Array<Id>
|
|
63
|
+
neighbors?: Array<Id>
|
|
64
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createOnMessage as __wasmCreateOnMessageForFsProxy,
|
|
3
|
+
getDefaultContext as __emnapiGetDefaultContext,
|
|
4
|
+
instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync,
|
|
5
|
+
WASI as __WASI,
|
|
6
|
+
} from '@napi-rs/wasm-runtime'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const __wasi = new __WASI({
|
|
11
|
+
version: 'preview1',
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const __wasmUrl = new URL('./napi.wasm32-wasi.wasm', import.meta.url).href
|
|
15
|
+
const __emnapiContext = __emnapiGetDefaultContext()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const __sharedMemory = new WebAssembly.Memory({
|
|
19
|
+
initial: 4000,
|
|
20
|
+
maximum: 65536,
|
|
21
|
+
shared: true,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())
|
|
25
|
+
|
|
26
|
+
const {
|
|
27
|
+
instance: __napiInstance,
|
|
28
|
+
module: __wasiModule,
|
|
29
|
+
napiModule: __napiModule,
|
|
30
|
+
} = __emnapiInstantiateNapiModuleSync(__wasmFile, {
|
|
31
|
+
context: __emnapiContext,
|
|
32
|
+
asyncWorkPoolSize: 4,
|
|
33
|
+
wasi: __wasi,
|
|
34
|
+
onCreateWorker() {
|
|
35
|
+
const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {
|
|
36
|
+
type: 'module',
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return worker
|
|
40
|
+
},
|
|
41
|
+
overwriteImports(importObject) {
|
|
42
|
+
importObject.env = {
|
|
43
|
+
...importObject.env,
|
|
44
|
+
...importObject.napi,
|
|
45
|
+
...importObject.emnapi,
|
|
46
|
+
memory: __sharedMemory,
|
|
47
|
+
}
|
|
48
|
+
return importObject
|
|
49
|
+
},
|
|
50
|
+
beforeInit({ instance }) {
|
|
51
|
+
for (const name of Object.keys(instance.exports)) {
|
|
52
|
+
if (name.startsWith('__napi_register__')) {
|
|
53
|
+
instance.exports[name]()
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
})
|
|
58
|
+
export default __napiModule.exports
|
|
59
|
+
export const Dggrs = __napiModule.exports.Dggrs
|
|
60
|
+
export const defaultConfig = __napiModule.exports.defaultConfig
|
|
61
|
+
export const Id = __napiModule.exports.Id
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/* prettier-ignore */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
const __nodeFs = require('node:fs')
|
|
7
|
+
const __nodePath = require('node:path')
|
|
8
|
+
const { WASI: __nodeWASI } = require('node:wasi')
|
|
9
|
+
const { Worker } = require('node:worker_threads')
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
createOnMessage: __wasmCreateOnMessageForFsProxy,
|
|
13
|
+
getDefaultContext: __emnapiGetDefaultContext,
|
|
14
|
+
instantiateNapiModuleSync: __emnapiInstantiateNapiModuleSync,
|
|
15
|
+
} = require('@napi-rs/wasm-runtime')
|
|
16
|
+
|
|
17
|
+
const __rootDir = __nodePath.parse(process.cwd()).root
|
|
18
|
+
|
|
19
|
+
const __wasi = new __nodeWASI({
|
|
20
|
+
version: 'preview1',
|
|
21
|
+
env: process.env,
|
|
22
|
+
preopens: {
|
|
23
|
+
[__rootDir]: __rootDir,
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const __emnapiContext = __emnapiGetDefaultContext()
|
|
28
|
+
|
|
29
|
+
const __sharedMemory = new WebAssembly.Memory({
|
|
30
|
+
initial: 4000,
|
|
31
|
+
maximum: 65536,
|
|
32
|
+
shared: true,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
let __wasmFilePath = __nodePath.join(__dirname, 'napi.wasm32-wasi.wasm')
|
|
36
|
+
const __wasmDebugFilePath = __nodePath.join(__dirname, 'napi.wasm32-wasi.debug.wasm')
|
|
37
|
+
|
|
38
|
+
if (__nodeFs.existsSync(__wasmDebugFilePath)) {
|
|
39
|
+
__wasmFilePath = __wasmDebugFilePath
|
|
40
|
+
} else if (!__nodeFs.existsSync(__wasmFilePath)) {
|
|
41
|
+
try {
|
|
42
|
+
__wasmFilePath = __nodePath.resolve('js-wasm32-wasi')
|
|
43
|
+
} catch {
|
|
44
|
+
throw new Error('Cannot find napi.wasm32-wasi.wasm file, and js-wasm32-wasi package is not installed.')
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = __emnapiInstantiateNapiModuleSync(__nodeFs.readFileSync(__wasmFilePath), {
|
|
49
|
+
context: __emnapiContext,
|
|
50
|
+
asyncWorkPoolSize: (function() {
|
|
51
|
+
const threadsSizeFromEnv = Number(process.env.NAPI_RS_ASYNC_WORK_POOL_SIZE ?? process.env.UV_THREADPOOL_SIZE)
|
|
52
|
+
// NaN > 0 is false
|
|
53
|
+
if (threadsSizeFromEnv > 0) {
|
|
54
|
+
return threadsSizeFromEnv
|
|
55
|
+
} else {
|
|
56
|
+
return 4
|
|
57
|
+
}
|
|
58
|
+
})(),
|
|
59
|
+
reuseWorker: true,
|
|
60
|
+
wasi: __wasi,
|
|
61
|
+
onCreateWorker() {
|
|
62
|
+
const worker = new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), {
|
|
63
|
+
env: process.env,
|
|
64
|
+
})
|
|
65
|
+
worker.onmessage = ({ data }) => {
|
|
66
|
+
__wasmCreateOnMessageForFsProxy(__nodeFs)(data)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// The main thread of Node.js waits for all the active handles before exiting.
|
|
70
|
+
// But Rust threads are never waited without `thread::join`.
|
|
71
|
+
// So here we hack the code of Node.js to prevent the workers from being referenced (active).
|
|
72
|
+
// According to https://github.com/nodejs/node/blob/19e0d472728c79d418b74bddff588bea70a403d0/lib/internal/worker.js#L415,
|
|
73
|
+
// a worker is consist of two handles: kPublicPort and kHandle.
|
|
74
|
+
{
|
|
75
|
+
const kPublicPort = Object.getOwnPropertySymbols(worker).find(s =>
|
|
76
|
+
s.toString().includes("kPublicPort")
|
|
77
|
+
);
|
|
78
|
+
if (kPublicPort) {
|
|
79
|
+
worker[kPublicPort].ref = () => {};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const kHandle = Object.getOwnPropertySymbols(worker).find(s =>
|
|
83
|
+
s.toString().includes("kHandle")
|
|
84
|
+
);
|
|
85
|
+
if (kHandle) {
|
|
86
|
+
worker[kHandle].ref = () => {};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
worker.unref();
|
|
90
|
+
}
|
|
91
|
+
return worker
|
|
92
|
+
},
|
|
93
|
+
overwriteImports(importObject) {
|
|
94
|
+
importObject.env = {
|
|
95
|
+
...importObject.env,
|
|
96
|
+
...importObject.napi,
|
|
97
|
+
...importObject.emnapi,
|
|
98
|
+
memory: __sharedMemory,
|
|
99
|
+
}
|
|
100
|
+
return importObject
|
|
101
|
+
},
|
|
102
|
+
beforeInit({ instance }) {
|
|
103
|
+
for (const name of Object.keys(instance.exports)) {
|
|
104
|
+
if (name.startsWith('__napi_register__')) {
|
|
105
|
+
instance.exports[name]()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
module.exports = __napiModule.exports
|
|
111
|
+
module.exports.Dggrs = __napiModule.exports.Dggrs
|
|
112
|
+
module.exports.defaultConfig = __napiModule.exports.defaultConfig
|
|
113
|
+
module.exports.Id = __napiModule.exports.Id
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { instantiateNapiModuleSync, MessageHandler, WASI } from '@napi-rs/wasm-runtime'
|
|
2
|
+
|
|
3
|
+
const handler = new MessageHandler({
|
|
4
|
+
onLoad({ wasmModule, wasmMemory }) {
|
|
5
|
+
const wasi = new WASI({
|
|
6
|
+
print: function () {
|
|
7
|
+
// eslint-disable-next-line no-console
|
|
8
|
+
console.log.apply(console, arguments)
|
|
9
|
+
},
|
|
10
|
+
printErr: function() {
|
|
11
|
+
// eslint-disable-next-line no-console
|
|
12
|
+
console.error.apply(console, arguments)
|
|
13
|
+
},
|
|
14
|
+
})
|
|
15
|
+
return instantiateNapiModuleSync(wasmModule, {
|
|
16
|
+
childThread: true,
|
|
17
|
+
wasi,
|
|
18
|
+
overwriteImports(importObject) {
|
|
19
|
+
importObject.env = {
|
|
20
|
+
...importObject.env,
|
|
21
|
+
...importObject.napi,
|
|
22
|
+
...importObject.emnapi,
|
|
23
|
+
memory: wasmMemory,
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
globalThis.onmessage = function (e) {
|
|
31
|
+
handler.handle(e)
|
|
32
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { parse } from "node:path";
|
|
4
|
+
import { WASI } from "node:wasi";
|
|
5
|
+
import { parentPort, Worker } from "node:worker_threads";
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
|
|
9
|
+
const { instantiateNapiModuleSync, MessageHandler, getDefaultContext } = require("@napi-rs/wasm-runtime");
|
|
10
|
+
|
|
11
|
+
if (parentPort) {
|
|
12
|
+
parentPort.on("message", (data) => {
|
|
13
|
+
globalThis.onmessage({ data });
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Object.assign(globalThis, {
|
|
18
|
+
self: globalThis,
|
|
19
|
+
require,
|
|
20
|
+
Worker,
|
|
21
|
+
importScripts: function (f) {
|
|
22
|
+
;(0, eval)(fs.readFileSync(f, "utf8") + "//# sourceURL=" + f);
|
|
23
|
+
},
|
|
24
|
+
postMessage: function (msg) {
|
|
25
|
+
if (parentPort) {
|
|
26
|
+
parentPort.postMessage(msg);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const emnapiContext = getDefaultContext();
|
|
32
|
+
|
|
33
|
+
const __rootDir = parse(process.cwd()).root;
|
|
34
|
+
|
|
35
|
+
const handler = new MessageHandler({
|
|
36
|
+
onLoad({ wasmModule, wasmMemory }) {
|
|
37
|
+
const wasi = new WASI({
|
|
38
|
+
version: 'preview1',
|
|
39
|
+
env: process.env,
|
|
40
|
+
preopens: {
|
|
41
|
+
[__rootDir]: __rootDir,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return instantiateNapiModuleSync(wasmModule, {
|
|
46
|
+
childThread: true,
|
|
47
|
+
wasi,
|
|
48
|
+
context: emnapiContext,
|
|
49
|
+
overwriteImports(importObject) {
|
|
50
|
+
importObject.env = {
|
|
51
|
+
...importObject.env,
|
|
52
|
+
...importObject.napi,
|
|
53
|
+
...importObject.emnapi,
|
|
54
|
+
memory: wasmMemory
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
globalThis.onmessage = function (e) {
|
|
62
|
+
handler.handle(e);
|
|
63
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "geoplegma-js",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "A JavaScript library for GeoPlegma.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/author/library#readme",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/author/library/issues"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/author/library.git"
|
|
14
|
+
},
|
|
15
|
+
"author": "João Manuel <joaocsmanuel@gmail.com>",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"main": "./dist/index.cjs",
|
|
20
|
+
"module": "./dist/index.mjs",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": "./dist/index.js",
|
|
24
|
+
"./package.json": "./package.json"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsdown",
|
|
31
|
+
"dev": "tsdown --watch",
|
|
32
|
+
"test": "vitest",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"release": "bumpp && npm publish"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.15.17",
|
|
38
|
+
"bumpp": "^10.1.0",
|
|
39
|
+
"tsdown": "^0.11.9",
|
|
40
|
+
"typescript": "^5.8.3",
|
|
41
|
+
"vitest": "^3.1.3"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"bindings": "^1.5.0"
|
|
45
|
+
}
|
|
46
|
+
}
|