@osmix/pbf 0.0.6 → 0.0.7

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/dist/utils.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { PbfFixture } from "@osmix/shared/fixtures";
2
+ import type { OsmPbfBlock, OsmPbfGroup, OsmPbfHeaderBlock } from "../src/proto/osmformat";
1
3
  export type AsyncGeneratorValue<T> = T | ReadableStream<T> | AsyncGenerator<T> | Promise<T> | Promise<ReadableStream<T>> | Promise<AsyncGenerator<T>>;
2
4
  /**
3
5
  * Normalizes values, streams, and iterables into a unified async generator interface.
@@ -19,4 +21,26 @@ export declare function concatUint8(...parts: Uint8Array[]): Uint8Array;
19
21
  * Encodes a 32-bit big-endian unsigned integer as a four-byte buffer.
20
22
  */
21
23
  export declare function uint32BE(n: number): Uint8Array;
24
+ export declare function testOsmPbfReader(osm: {
25
+ header: OsmPbfHeaderBlock;
26
+ blocks: AsyncGenerator<OsmPbfBlock>;
27
+ }, pbf: PbfFixture): Promise<{
28
+ nodes: number;
29
+ ways: number;
30
+ relations: number;
31
+ node0: number;
32
+ way0: number;
33
+ relation0: number;
34
+ }>;
35
+ export declare function createOsmEntityCounter(): {
36
+ onGroup: (group: OsmPbfGroup) => void;
37
+ count: {
38
+ nodes: number;
39
+ ways: number;
40
+ relations: number;
41
+ node0: number;
42
+ way0: number;
43
+ relation0: number;
44
+ };
45
+ };
22
46
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAC9B,CAAC,GACD,cAAc,CAAC,CAAC,CAAC,GACjB,cAAc,CAAC,CAAC,CAAC,GACjB,OAAO,CAAC,CAAC,CAAC,GACV,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;AAE7B;;GAEG;AACH,wBAAuB,gBAAgB,CAAC,CAAC,EACxC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,GACvB,cAAc,CAAC,CAAC,CAAC,CAuBnB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAClC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,GAC3B,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAElC;AAED;;GAEG;AACH,wBAAsB,WAAW,CAChC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,GAC3B,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAElC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,CAS9D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAO9C"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,KAAK,EACX,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,MAAM,wBAAwB,CAAA;AAE/B,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAC9B,CAAC,GACD,cAAc,CAAC,CAAC,CAAC,GACjB,cAAc,CAAC,CAAC,CAAC,GACjB,OAAO,CAAC,CAAC,CAAC,GACV,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;AAE7B;;GAEG;AACH,wBAAuB,gBAAgB,CAAC,CAAC,EACxC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,GACvB,cAAc,CAAC,CAAC,CAAC,CAuBnB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAClC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,GAC3B,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAElC;AAED;;GAEG;AACH,wBAAsB,WAAW,CAChC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,GAC3B,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAElC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,CAS9D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAO9C;AAED,wBAAsB,gBAAgB,CACrC,GAAG,EAAE;IACJ,MAAM,EAAE,iBAAiB,CAAA;IACzB,MAAM,EAAE,cAAc,CAAC,WAAW,CAAC,CAAA;CACnC,EACD,GAAG,EAAE,UAAU;;;;;;;GAqCf;AAED,wBAAgB,sBAAsB;qBAUb,WAAW;;;;;;;;;EAuBnC"}
package/dist/utils.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { assertValue as assert } from "@osmix/shared/assert";
1
2
  import { transformBytes } from "@osmix/shared/transform-bytes";
2
3
  /**
3
4
  * Normalizes values, streams, and iterables into a unified async generator interface.
@@ -65,4 +66,49 @@ export function uint32BE(n) {
65
66
  out[3] = n & 0xff;
66
67
  return out;
67
68
  }
69
+ export async function testOsmPbfReader(osm, pbf) {
70
+ assert(JSON.stringify(osm.header.bbox) === JSON.stringify(pbf.bbox), `Header bbox ${JSON.stringify(osm.header.bbox)} != ${JSON.stringify(pbf.bbox)}`);
71
+ const { onGroup, count } = createOsmEntityCounter();
72
+ for await (const block of osm.blocks)
73
+ for (const group of block.primitivegroup)
74
+ onGroup(group);
75
+ assert(count.nodes === pbf.nodes, `Expected nodes: ${pbf.nodes}, got: ${count.nodes}`);
76
+ assert(count.ways === pbf.ways, `Expected ways: ${pbf.ways}, got: ${count.ways}`);
77
+ assert(count.relations === pbf.relations, `Expected relations: ${pbf.relations}, got: ${count.relations}`);
78
+ assert(count.node0 === pbf.node0.id, `Expected node0: ${pbf.node0.id}, got: ${count.node0}`);
79
+ assert(count.way0 === pbf.way0, `Expected way0: ${pbf.way0}, got: ${count.way0}`);
80
+ assert(count.relation0 === pbf.relation0, `Expected relation0: ${pbf.relation0}, got: ${count.relation0}`);
81
+ return count;
82
+ }
83
+ export function createOsmEntityCounter() {
84
+ const count = {
85
+ nodes: 0,
86
+ ways: 0,
87
+ relations: 0,
88
+ node0: -1,
89
+ way0: -1,
90
+ relation0: -1,
91
+ };
92
+ const onGroup = (group) => {
93
+ if (count.node0 === -1 && group.dense?.id?.[0] != null) {
94
+ count.node0 = group.dense.id[0];
95
+ }
96
+ if (count.way0 === -1 && group.ways?.[0]?.id != null) {
97
+ count.way0 = group.ways[0].id;
98
+ }
99
+ if (count.relation0 === -1 && group.relations?.[0]?.id != null) {
100
+ count.relation0 = group.relations[0].id;
101
+ }
102
+ count.nodes += group.nodes?.length ?? 0;
103
+ if (group.dense) {
104
+ count.nodes += group.dense.id.length;
105
+ }
106
+ count.ways += group.ways?.length ?? 0;
107
+ count.relations += group.relations?.length ?? 0;
108
+ };
109
+ return {
110
+ onGroup,
111
+ count,
112
+ };
113
+ }
68
114
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAU9D;;GAEG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,gBAAgB,CACtC,CAAyB;IAEzB,IAAI,CAAC,YAAY,OAAO;QAAE,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAA;IAE1D,IAAI,CAAC,IAAI,IAAI;QAAE,MAAM,KAAK,CAAC,eAAe,CAAC,CAAA;IAC3C,IAAI,CAAC,YAAY,cAAc,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,CAAA;QAC5B,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;YAC3C,IAAI,IAAI;gBAAE,MAAK;YACf,MAAM,KAAK,CAAA;QACZ,CAAC;QACD,MAAM,CAAC,WAAW,EAAE,CAAA;IACrB,CAAC;SAAM,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,WAAW,EAAE,CAAC;QAC9D,+EAA+E;QAC/E,MAAM,CAAM,CAAA;IACb,CAAC;SAAM,IACN,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,EAClD,CAAC;QACF,OAAO,CAAC,CAAA;IACT,CAAC;SAAM,CAAC;QACP,MAAM,CAAC,CAAA;IACR,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,IAA6B;IAE7B,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAA;AAChE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,IAA6B;IAE7B,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAA;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAG,KAAmB;IACjD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACrD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAA;IACjC,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACvB,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;QAClB,MAAM,IAAI,CAAC,CAAC,MAAM,CAAA;IACnB,CAAC;IACD,OAAO,GAAG,CAAA;AACX,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS;IACjC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;IAC7B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;IAC1B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;IAC1B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;IACzB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;IACjB,OAAO,GAAG,CAAA;AACX,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -2,25 +2,10 @@
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@osmix/pbf",
4
4
  "description": "A low level, modern, runtime agnostic OSM PBF parser and writer written in TypeScript.",
5
- "version": "0.0.6",
5
+ "version": "0.0.7",
6
6
  "type": "module",
7
- "main": "./src/index.ts",
8
7
  "publishConfig": {
9
- "access": "public",
10
- "registry": "https://registry.npmjs.org/",
11
- "main": "./dist/index.js",
12
- "types": "./dist/index.d.ts",
13
- "exports": {
14
- ".": {
15
- "import": "./dist/index.js",
16
- "types": "./dist/index.d.ts"
17
- }
18
- },
19
- "files": [
20
- "dist",
21
- "README.md",
22
- "LICENSE"
23
- ]
8
+ "access": "public"
24
9
  },
25
10
  "license": "MIT",
26
11
  "repository": {
@@ -41,11 +26,26 @@
41
26
  "typecheck": "tsgo --noEmit"
42
27
  },
43
28
  "devDependencies": {
44
- "@osmix/shared": "0.0.10",
45
- "@types/bun": "^1.3.3",
46
- "typescript": "^5.9.0"
29
+ "@osmix/shared": "workspace:*",
30
+ "@types/bun": "catalog:",
31
+ "typescript": "catalog:"
47
32
  },
48
33
  "dependencies": {
49
- "pbf": "^4.0.1"
50
- }
34
+ "pbf": "catalog:"
35
+ },
36
+ "types": "./dist/index.d.ts",
37
+ "exports": {
38
+ ".": {
39
+ "types": "./src/index.ts",
40
+ "bun": "./src/index.ts",
41
+ "development|production": "./src/index.ts",
42
+ "default": "./dist/index.js"
43
+ }
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "src",
48
+ "README.md",
49
+ "LICENSE"
50
+ ]
51
51
  }
package/src/utils.ts CHANGED
@@ -1,4 +1,11 @@
1
+ import { assertValue as assert } from "@osmix/shared/assert"
2
+ import type { PbfFixture } from "@osmix/shared/fixtures"
1
3
  import { transformBytes } from "@osmix/shared/transform-bytes"
4
+ import type {
5
+ OsmPbfBlock,
6
+ OsmPbfGroup,
7
+ OsmPbfHeaderBlock,
8
+ } from "../src/proto/osmformat"
2
9
 
3
10
  export type AsyncGeneratorValue<T> =
4
11
  | T
@@ -81,3 +88,82 @@ export function uint32BE(n: number): Uint8Array {
81
88
  out[3] = n & 0xff
82
89
  return out
83
90
  }
91
+
92
+ export async function testOsmPbfReader(
93
+ osm: {
94
+ header: OsmPbfHeaderBlock
95
+ blocks: AsyncGenerator<OsmPbfBlock>
96
+ },
97
+ pbf: PbfFixture,
98
+ ) {
99
+ assert(
100
+ JSON.stringify(osm.header.bbox) === JSON.stringify(pbf.bbox),
101
+ `Header bbox ${JSON.stringify(osm.header.bbox)} != ${JSON.stringify(pbf.bbox)}`,
102
+ )
103
+
104
+ const { onGroup, count } = createOsmEntityCounter()
105
+ for await (const block of osm.blocks)
106
+ for (const group of block.primitivegroup) onGroup(group)
107
+
108
+ assert(
109
+ count.nodes === pbf.nodes,
110
+ `Expected nodes: ${pbf.nodes}, got: ${count.nodes}`,
111
+ )
112
+ assert(
113
+ count.ways === pbf.ways,
114
+ `Expected ways: ${pbf.ways}, got: ${count.ways}`,
115
+ )
116
+ assert(
117
+ count.relations === pbf.relations,
118
+ `Expected relations: ${pbf.relations}, got: ${count.relations}`,
119
+ )
120
+ assert(
121
+ count.node0 === pbf.node0.id,
122
+ `Expected node0: ${pbf.node0.id}, got: ${count.node0}`,
123
+ )
124
+ assert(
125
+ count.way0 === pbf.way0,
126
+ `Expected way0: ${pbf.way0}, got: ${count.way0}`,
127
+ )
128
+ assert(
129
+ count.relation0 === pbf.relation0,
130
+ `Expected relation0: ${pbf.relation0}, got: ${count.relation0}`,
131
+ )
132
+
133
+ return count
134
+ }
135
+
136
+ export function createOsmEntityCounter() {
137
+ const count = {
138
+ nodes: 0,
139
+ ways: 0,
140
+ relations: 0,
141
+ node0: -1,
142
+ way0: -1,
143
+ relation0: -1,
144
+ }
145
+
146
+ const onGroup = (group: OsmPbfGroup) => {
147
+ if (count.node0 === -1 && group.dense?.id?.[0] != null) {
148
+ count.node0 = group.dense.id[0]
149
+ }
150
+ if (count.way0 === -1 && group.ways?.[0]?.id != null) {
151
+ count.way0 = group.ways[0].id
152
+ }
153
+ if (count.relation0 === -1 && group.relations?.[0]?.id != null) {
154
+ count.relation0 = group.relations[0].id
155
+ }
156
+
157
+ count.nodes += group.nodes?.length ?? 0
158
+ if (group.dense) {
159
+ count.nodes += group.dense.id.length
160
+ }
161
+ count.ways += group.ways?.length ?? 0
162
+ count.relations += group.relations?.length ?? 0
163
+ }
164
+
165
+ return {
166
+ onGroup,
167
+ count,
168
+ }
169
+ }
package/CHANGELOG.md DELETED
@@ -1,37 +0,0 @@
1
- # @osmix/pbf
2
-
3
- ## 0.0.6
4
-
5
- ### Patch Changes
6
-
7
- - f32e4ee: General cleanup
8
-
9
- ## 0.0.5
10
-
11
- ### Patch Changes
12
-
13
- - f468db5: Fix publishing (2)
14
-
15
- ## 0.0.4
16
-
17
- ### Patch Changes
18
-
19
- - 68d6bd8: Fix publishing for packages.
20
-
21
- ## 0.0.3
22
-
23
- ### Patch Changes
24
-
25
- - d001d9a: Refactor to align around new main external API
26
-
27
- ## 0.0.2
28
-
29
- ### Patch Changes
30
-
31
- - 33d9c12: Modify types to take Uint8Array<ArrayBufferLike> for compatiblity
32
-
33
- ## 0.0.1
34
-
35
- ### Patch Changes
36
-
37
- - Initial release
@@ -1,79 +0,0 @@
1
- import { describe, expect, it } from "bun:test"
2
- import { osmPbfBlobsToBlocksGenerator } from "../src/blobs-to-blocks"
3
- import { createOsmPbfBlobGenerator } from "../src/pbf-to-blobs"
4
- import {
5
- createSamplePbfFileBytes,
6
- isHeaderBlock,
7
- isPrimitiveBlock,
8
- } from "./helpers"
9
-
10
- describe("osmPbfBlobsToBlocksGenerator", () => {
11
- it("consumes asynchronous blob sources", async () => {
12
- const { header, primitiveBlock, fileBytes } =
13
- await createSamplePbfFileBytes()
14
- const collectBlobs = createOsmPbfBlobGenerator()
15
- const blobs: Uint8Array<ArrayBuffer>[] = []
16
- for (const blob of collectBlobs(fileBytes)) blobs.push(blob)
17
-
18
- const generator = osmPbfBlobsToBlocksGenerator(
19
- (async function* () {
20
- for (const blob of blobs) {
21
- await Promise.resolve()
22
- yield blob
23
- }
24
- })(),
25
- )
26
-
27
- const { value: headerBlock, done } = await generator.next()
28
- expect(done).toBe(false)
29
- if (!isHeaderBlock(headerBlock)) {
30
- throw new Error("Expected header block")
31
- }
32
- expect(headerBlock.bbox).toEqual(header.bbox)
33
- expect(headerBlock.required_features).toEqual(header.required_features)
34
- expect(headerBlock.optional_features).toEqual(header.optional_features)
35
-
36
- const { value: block, done: blockDone } = await generator.next()
37
- expect(blockDone).toBe(false)
38
- if (!isPrimitiveBlock(block)) {
39
- throw new Error("Expected primitive block")
40
- }
41
- expect(block.primitivegroup).toHaveLength(
42
- primitiveBlock.primitivegroup.length,
43
- )
44
- const group = block.primitivegroup[0]
45
- expect(primitiveBlock.primitivegroup[0]).toBeDefined()
46
- expect(group?.dense).toBeDefined()
47
- expect(group?.ways?.[0]).toBeDefined()
48
- if (!group) throw new Error("group is undefined")
49
- if (!primitiveBlock.primitivegroup[0])
50
- throw new Error("primitiveBlock.primitivegroup[0] is undefined")
51
- expect(group.ways).toHaveLength(
52
- primitiveBlock.primitivegroup[0].ways.length,
53
- )
54
- expect(group.ways[0]?.refs).toEqual(
55
- primitiveBlock.primitivegroup[0]?.ways?.[0]?.refs,
56
- )
57
-
58
- const final = await generator.next()
59
- expect(final.done).toBe(true)
60
- })
61
-
62
- it("accepts synchronous generators", async () => {
63
- const { fileBytes } = await createSamplePbfFileBytes()
64
- const collectBlobs = createOsmPbfBlobGenerator()
65
- const blobs = [...collectBlobs(fileBytes)]
66
- const generator = osmPbfBlobsToBlocksGenerator(
67
- (function* () {
68
- for (const blob of blobs) yield blob
69
- })(),
70
- )
71
-
72
- const header = await generator.next()
73
- expect(header.done).toBe(false)
74
- const block = await generator.next()
75
- expect(block.done).toBe(false)
76
- const final = await generator.next()
77
- expect(final.done).toBe(true)
78
- })
79
- })
package/test/helpers.ts DELETED
@@ -1,66 +0,0 @@
1
- import { osmBlockToPbfBlobBytes } from "../src/blocks-to-pbf"
2
- import type { OsmPbfBlock, OsmPbfHeaderBlock } from "../src/proto/osmformat"
3
- import { concatUint8 } from "../src/utils"
4
-
5
- const encoder = new TextEncoder()
6
-
7
- export function createSampleHeader(): OsmPbfHeaderBlock {
8
- return {
9
- bbox: { left: 0, right: 1, top: 1, bottom: 0 },
10
- required_features: ["OsmSchema-V0.6"],
11
- optional_features: ["DenseNodes"],
12
- writingprogram: "osmix-tests",
13
- }
14
- }
15
-
16
- export function createSamplePrimitiveBlock(): OsmPbfBlock {
17
- return {
18
- stringtable: [
19
- encoder.encode(""),
20
- encoder.encode("name"),
21
- encoder.encode("value"),
22
- ],
23
- primitivegroup: [
24
- {
25
- nodes: [],
26
- dense: {
27
- id: [1, 2],
28
- lat: [1_000, 500],
29
- lon: [1_500, 600],
30
- keys_vals: [1, 2, 0],
31
- },
32
- ways: [
33
- {
34
- id: 10,
35
- keys: [1],
36
- vals: [2],
37
- refs: [1, 1, 0],
38
- },
39
- ],
40
- relations: [],
41
- },
42
- ],
43
- } as const
44
- }
45
-
46
- export async function createSamplePbfFileBytes() {
47
- const header = createSampleHeader()
48
- const primitiveBlock = createSamplePrimitiveBlock()
49
- const headerBytes = await osmBlockToPbfBlobBytes(header)
50
- const primitiveBytes = await osmBlockToPbfBlobBytes(primitiveBlock)
51
- return {
52
- header,
53
- primitiveBlock,
54
- fileBytes: concatUint8(headerBytes, primitiveBytes),
55
- }
56
- }
57
-
58
- export function isHeaderBlock(value: unknown): value is OsmPbfHeaderBlock {
59
- return (
60
- typeof value === "object" && value != null && "required_features" in value
61
- )
62
- }
63
-
64
- export function isPrimitiveBlock(value: unknown): value is OsmPbfBlock {
65
- return typeof value === "object" && value != null && "primitivegroup" in value
66
- }
@@ -1,91 +0,0 @@
1
- import { describe, expect, it } from "bun:test"
2
- import Pbf from "pbf"
3
- import { osmPbfBlobsToBlocksGenerator } from "../src/blobs-to-blocks"
4
- import { createOsmPbfBlobGenerator } from "../src/pbf-to-blobs"
5
- import { writeBlob, writeBlobHeader } from "../src/proto/fileformat"
6
- import { writeHeaderBlock } from "../src/proto/osmformat"
7
- import { concatUint8, uint32BE } from "../src/utils"
8
- import {
9
- createSampleHeader,
10
- createSamplePbfFileBytes,
11
- isHeaderBlock,
12
- isPrimitiveBlock,
13
- } from "./helpers"
14
-
15
- describe("createOsmPbfBlobGenerator", () => {
16
- it("yields compressed blobs across fragmented chunks", async () => {
17
- const { header, primitiveBlock, fileBytes } =
18
- await createSamplePbfFileBytes()
19
- const generate = createOsmPbfBlobGenerator()
20
- const yielded: Uint8Array<ArrayBuffer>[] = []
21
-
22
- let offset = 0
23
- const chunkSizes = [1, 9]
24
- for (const size of chunkSizes) {
25
- const chunk = fileBytes.slice(offset, offset + size)
26
- offset += size
27
- for (const blob of generate(chunk)) yielded.push(blob)
28
- }
29
- if (offset < fileBytes.length) {
30
- for (const blob of generate(fileBytes.slice(offset))) yielded.push(blob)
31
- }
32
-
33
- expect(yielded.length).toBe(2)
34
-
35
- const blocks = osmPbfBlobsToBlocksGenerator(
36
- (async function* () {
37
- for (const blob of yielded) yield blob
38
- })(),
39
- )
40
- const { value: headerBlock, done } = await blocks.next()
41
- expect(done).toBe(false)
42
- if (!isHeaderBlock(headerBlock)) {
43
- throw new Error("Expected first block to be a header")
44
- }
45
- expect(headerBlock.bbox).toEqual(header.bbox)
46
- expect(headerBlock.required_features).toEqual(header.required_features)
47
- expect(headerBlock.optional_features).toEqual(header.optional_features)
48
-
49
- const { value: primitive } = await blocks.next()
50
- if (!isPrimitiveBlock(primitive)) {
51
- throw new Error("Expected primitive block after header")
52
- }
53
- expect(primitive.primitivegroup).toHaveLength(
54
- primitiveBlock.primitivegroup.length,
55
- )
56
- expect(primitive.primitivegroup[0]).toBeDefined()
57
- expect(primitiveBlock.primitivegroup[0]).toBeDefined()
58
- if (!primitive.primitivegroup[0])
59
- throw new Error("primitive.primitivegroup[0] is undefined")
60
- if (!primitiveBlock.primitivegroup[0])
61
- throw new Error("primitiveBlock.primitivegroup[0] is undefined")
62
- const dense = primitive.primitivegroup[0].dense
63
- expect(dense).toBeDefined()
64
- if (!dense) throw new Error("dense is undefined")
65
- if (!primitiveBlock.primitivegroup[0]?.dense)
66
- throw new Error("primitiveBlock.primitivegroup[0].dense is undefined")
67
- expect(dense.id).toEqual(primitiveBlock.primitivegroup[0].dense.id)
68
- expect(dense.lat).toEqual(primitiveBlock.primitivegroup[0].dense.lat)
69
- expect(dense.lon).toEqual(primitiveBlock.primitivegroup[0].dense.lon)
70
- })
71
-
72
- it("throws when a blob omits zlib data", () => {
73
- const headerBlock = createSampleHeader()
74
- const headerPbf = new Pbf()
75
- writeHeaderBlock(headerBlock, headerPbf)
76
- const headerContent = headerPbf.finish()
77
-
78
- const blobPbf = new Pbf()
79
- writeBlob({ raw_size: headerContent.length, raw: headerContent }, blobPbf)
80
- const blob = blobPbf.finish()
81
-
82
- const blobHeaderPbf = new Pbf()
83
- writeBlobHeader({ type: "OSMHeader", datasize: blob.length }, blobHeaderPbf)
84
- const blobHeader = blobHeaderPbf.finish()
85
-
86
- const chunk = concatUint8(uint32BE(blobHeader.byteLength), blobHeader, blob)
87
- const generate = createOsmPbfBlobGenerator()
88
- const iterator = generate(chunk)
89
- expect(() => iterator.next()).toThrow(/Blob has no zlib data/)
90
- })
91
- })
@@ -1,46 +0,0 @@
1
- import { beforeAll, describe, expect } from "bun:test"
2
- import {
3
- getFixtureFile,
4
- getFixtureFileReadStream,
5
- PBFs,
6
- } from "@osmix/shared/test/fixtures"
7
-
8
- // @ts-expect-error - bench is available at runtime but not in types
9
- const { bench } = globalThis as { bench: typeof import("bun:test").test }
10
-
11
- import {
12
- OsmPbfBytesToBlocksTransformStream,
13
- readOsmPbf,
14
- } from "../src/pbf-to-blocks"
15
- import { createOsmEntityCounter, testOsmPbfReader } from "./utils"
16
-
17
- describe.each(Object.entries(PBFs))("%s", (_name, pbf) => {
18
- beforeAll(() => getFixtureFile(pbf.url))
19
-
20
- bench("parse with generators", async () => {
21
- const file = await getFixtureFile(pbf.url)
22
- const osm = await readOsmPbf(file)
23
-
24
- await testOsmPbfReader(osm, pbf)
25
- })
26
-
27
- bench("parse streaming", async () => {
28
- const { onGroup, count } = createOsmEntityCounter()
29
-
30
- await getFixtureFileReadStream(pbf.url)
31
- .pipeThrough(new OsmPbfBytesToBlocksTransformStream())
32
- .pipeTo(
33
- new WritableStream({
34
- write: (block) => {
35
- if ("primitivegroup" in block) {
36
- for (const group of block.primitivegroup) onGroup(group)
37
- }
38
- },
39
- }),
40
- )
41
-
42
- expect(count.nodes).toBe(pbf.nodes)
43
- expect(count.ways).toBe(pbf.ways)
44
- expect(count.relations).toBe(pbf.relations)
45
- })
46
- })
package/test/read.test.ts DELETED
@@ -1,45 +0,0 @@
1
- import { beforeAll, describe, expect, it } from "bun:test"
2
- import {
3
- getFixtureFile,
4
- getFixtureFileReadStream,
5
- PBFs,
6
- } from "@osmix/shared/test/fixtures"
7
- import {
8
- OsmPbfBytesToBlocksTransformStream,
9
- readOsmPbf,
10
- } from "../src/pbf-to-blocks"
11
- import { createOsmEntityCounter, testOsmPbfReader } from "./utils"
12
-
13
- describe("read", () => {
14
- describe.each(Object.entries(PBFs))("%s", async (_name, pbf) => {
15
- beforeAll(() => getFixtureFile(pbf.url))
16
-
17
- it("from stream", async () => {
18
- const { onGroup, count } = createOsmEntityCounter()
19
-
20
- await getFixtureFileReadStream(pbf.url)
21
- .pipeThrough(new OsmPbfBytesToBlocksTransformStream())
22
- .pipeTo(
23
- new WritableStream({
24
- write: (block) => {
25
- if ("primitivegroup" in block) {
26
- for (const group of block.primitivegroup) onGroup(group)
27
- } else {
28
- expect(block.bbox).toEqual(pbf.bbox)
29
- }
30
- },
31
- }),
32
- )
33
-
34
- expect(count.nodes).toBe(pbf.nodes)
35
- expect(count.ways).toBe(pbf.ways)
36
- expect(count.relations).toBe(pbf.relations)
37
- })
38
-
39
- it("from buffer", async () => {
40
- const fileData = await getFixtureFile(pbf.url)
41
- const osm = await readOsmPbf(fileData)
42
- await testOsmPbfReader(osm, pbf)
43
- })
44
- })
45
- })
@@ -1,101 +0,0 @@
1
- import { describe, expect, it } from "bun:test"
2
- import { OsmBlocksToPbfBytesTransformStream } from "../src/blocks-to-pbf"
3
- import { OsmPbfBytesToBlocksTransformStream } from "../src/pbf-to-blocks"
4
- import { concatUint8 } from "../src/utils"
5
- import {
6
- createSamplePbfFileBytes,
7
- createSamplePrimitiveBlock,
8
- isHeaderBlock,
9
- isPrimitiveBlock,
10
- } from "./helpers"
11
-
12
- describe("transform streams", () => {
13
- it("requires the header to be written before data blocks", async () => {
14
- const input = new ReadableStream({
15
- start(controller) {
16
- controller.enqueue(createSamplePrimitiveBlock())
17
- controller.close()
18
- },
19
- })
20
-
21
- await expect(
22
- input
23
- .pipeThrough(new OsmBlocksToPbfBytesTransformStream())
24
- .pipeTo(new WritableStream()),
25
- ).rejects.toThrow("Header first in ReadableStream of blocks.")
26
- })
27
-
28
- it("serialises blocks into the expected PBF byte sequence", async () => {
29
- const { header, primitiveBlock, fileBytes } =
30
- await createSamplePbfFileBytes()
31
- const chunks: Uint8Array[] = []
32
-
33
- const input = new ReadableStream({
34
- start(controller) {
35
- controller.enqueue(header)
36
- controller.enqueue(primitiveBlock)
37
- controller.close()
38
- },
39
- })
40
-
41
- await input.pipeThrough(new OsmBlocksToPbfBytesTransformStream()).pipeTo(
42
- new WritableStream<Uint8Array>({
43
- write(chunk) {
44
- chunks.push(chunk)
45
- },
46
- }),
47
- )
48
-
49
- expect(concatUint8(...chunks)).toEqual(fileBytes)
50
- })
51
-
52
- it("parses streamed bytes back into header and primitive blocks", async () => {
53
- const { header, primitiveBlock, fileBytes } =
54
- await createSamplePbfFileBytes()
55
- expect(primitiveBlock.primitivegroup[0]).toBeDefined()
56
- const blocks: unknown[] = []
57
-
58
- const input = new ReadableStream({
59
- start(controller) {
60
- controller.enqueue(fileBytes.slice(0, 7).buffer)
61
- controller.enqueue(fileBytes.slice(7).buffer)
62
- controller.close()
63
- },
64
- })
65
-
66
- await input.pipeThrough(new OsmPbfBytesToBlocksTransformStream()).pipeTo(
67
- new WritableStream({
68
- write(chunk) {
69
- blocks.push(chunk)
70
- },
71
- }),
72
- )
73
-
74
- expect(blocks.length).toBe(2)
75
- const headerBlock = blocks[0]
76
- if (!isHeaderBlock(headerBlock)) {
77
- throw new Error("Expected header block")
78
- }
79
- expect(headerBlock.bbox).toEqual(header.bbox)
80
- expect(headerBlock.required_features).toEqual(header.required_features)
81
- const block = blocks[1]
82
- if (!isPrimitiveBlock(block)) {
83
- throw new Error("Expected primitive block")
84
- }
85
- expect(block.primitivegroup).toHaveLength(
86
- primitiveBlock.primitivegroup.length,
87
- )
88
- expect(block.primitivegroup).toBeDefined()
89
- expect(block.primitivegroup[0]).toBeDefined()
90
- if (!block.primitivegroup[0])
91
- throw new Error("block.primitivegroup[0] is undefined")
92
- if (!primitiveBlock.primitivegroup[0])
93
- throw new Error("primitiveBlock.primitivegroup[0] is undefined")
94
- const dense = block.primitivegroup[0].dense
95
- expect(dense).toBeDefined()
96
- if (!dense) throw new Error("dense is undefined")
97
- if (!primitiveBlock.primitivegroup[0]?.dense)
98
- throw new Error("primitiveBlock.primitivegroup[0].dense is undefined")
99
- expect(dense.id).toEqual(primitiveBlock.primitivegroup[0].dense.id)
100
- })
101
- })
@@ -1,56 +0,0 @@
1
- import { describe, expect, it } from "bun:test"
2
- import {
3
- concatUint8,
4
- toAsyncGenerator,
5
- uint32BE,
6
- webCompress,
7
- webDecompress,
8
- } from "../src/utils"
9
-
10
- describe("utils", () => {
11
- it("wraps values into an async generator", async () => {
12
- const generator = toAsyncGenerator(3)
13
- const first = await generator.next()
14
- expect(first).toEqual({ value: 3, done: false })
15
- const done = await generator.next()
16
- expect(done).toEqual({ value: undefined, done: true })
17
- })
18
-
19
- it("consumes readable streams", async () => {
20
- const stream = new ReadableStream<number>({
21
- start(controller) {
22
- controller.enqueue(1)
23
- controller.enqueue(2)
24
- controller.close()
25
- },
26
- })
27
- const values: number[] = []
28
- for await (const value of toAsyncGenerator(stream)) values.push(value)
29
- expect(values).toEqual([1, 2])
30
- })
31
-
32
- it("throws on nullish inputs", async () => {
33
- const invalidInput = null as unknown as never
34
- await expect(toAsyncGenerator(invalidInput).next()).rejects.toThrow(
35
- "Value is null",
36
- )
37
- })
38
-
39
- it("concatenates Uint8Array segments", () => {
40
- const a = Uint8Array.of(1, 2)
41
- const b = Uint8Array.of(3)
42
- expect(concatUint8(a, b)).toEqual(Uint8Array.of(1, 2, 3))
43
- })
44
-
45
- it("encodes big-endian 32-bit integers", () => {
46
- expect(uint32BE(0x01020304)).toEqual(Uint8Array.of(1, 2, 3, 4))
47
- })
48
-
49
- it("compresses and decompresses data", async () => {
50
- const input = new TextEncoder().encode("osmix") as Uint8Array<ArrayBuffer>
51
- const compressed = await webCompress(input)
52
- expect(compressed).not.toEqual(input)
53
- const decompressed = await webDecompress(compressed)
54
- expect(decompressed).toEqual(input)
55
- })
56
- })
package/test/utils.ts DELETED
@@ -1,65 +0,0 @@
1
- import { expect } from "bun:test"
2
- import type { PbfFixture } from "@osmix/shared/test/fixtures"
3
- import type {
4
- OsmPbfBlock,
5
- OsmPbfGroup,
6
- OsmPbfHeaderBlock,
7
- } from "../src/proto/osmformat"
8
-
9
- export async function testOsmPbfReader(
10
- osm: {
11
- header: OsmPbfHeaderBlock
12
- blocks: AsyncGenerator<OsmPbfBlock>
13
- },
14
- pbf: PbfFixture,
15
- ) {
16
- expect(osm.header.bbox).toEqual(pbf.bbox)
17
-
18
- const { onGroup, count } = createOsmEntityCounter()
19
- for await (const block of osm.blocks)
20
- for (const group of block.primitivegroup) onGroup(group)
21
-
22
- expect(count.nodes).toBe(pbf.nodes)
23
- expect(count.ways).toBe(pbf.ways)
24
- expect(count.relations).toBe(pbf.relations)
25
- expect(count.node0).toBe(pbf.node0.id)
26
- expect(count.way0).toBe(pbf.way0)
27
- expect(count.relation0).toBe(pbf.relation0)
28
-
29
- return count
30
- }
31
-
32
- export function createOsmEntityCounter() {
33
- const count = {
34
- nodes: 0,
35
- ways: 0,
36
- relations: 0,
37
- node0: -1,
38
- way0: -1,
39
- relation0: -1,
40
- }
41
-
42
- const onGroup = (group: OsmPbfGroup) => {
43
- if (count.node0 === -1 && group.dense?.id?.[0] != null) {
44
- count.node0 = group.dense.id[0]
45
- }
46
- if (count.way0 === -1 && group.ways?.[0]?.id != null) {
47
- count.way0 = group.ways[0].id
48
- }
49
- if (count.relation0 === -1 && group.relations?.[0]?.id != null) {
50
- count.relation0 = group.relations[0].id
51
- }
52
-
53
- count.nodes += group.nodes?.length ?? 0
54
- if (group.dense) {
55
- count.nodes += group.dense.id.length
56
- }
57
- count.ways += group.ways?.length ?? 0
58
- count.relations += group.relations?.length ?? 0
59
- }
60
-
61
- return {
62
- onGroup,
63
- count,
64
- }
65
- }
@@ -1,91 +0,0 @@
1
- import { describe, expect, it } from "bun:test"
2
- import { unlink } from "node:fs/promises"
3
- import {
4
- getFixtureFile,
5
- getFixtureFileReadStream,
6
- getFixtureFileWriteStream,
7
- getFixturePath,
8
- PBFs,
9
- } from "@osmix/shared/test/fixtures"
10
- import {
11
- OsmBlocksToPbfBytesTransformStream,
12
- osmBlockToPbfBlobBytes,
13
- } from "../src/blocks-to-pbf"
14
- import {
15
- OsmPbfBytesToBlocksTransformStream,
16
- readOsmPbf,
17
- } from "../src/pbf-to-blocks"
18
- import { testOsmPbfReader } from "./utils"
19
-
20
- describe("write", () => {
21
- describe.each(Object.entries(PBFs))("%s", (name, pbf) => {
22
- it("to buffer", async () => {
23
- const fileData = await getFixtureFile(pbf.url)
24
- const osm = await readOsmPbf(fileData)
25
-
26
- let node0: number | null = null
27
- let way0: number | null = null
28
- let relation0: number | null = null
29
-
30
- // Write the PBF to an array buffer
31
- let data = new Uint8Array(0)
32
- const write = (chunk: Uint8Array) => {
33
- const newData = new Uint8Array(data.length + chunk.length)
34
- newData.set(data)
35
- newData.set(chunk, data.length)
36
- data = newData
37
- }
38
-
39
- write(await osmBlockToPbfBlobBytes(osm.header))
40
- for await (const block of osm.blocks) {
41
- for (const group of block.primitivegroup) {
42
- if (node0 == null && group.dense?.id?.[0] != null) {
43
- node0 = group.dense.id[0]
44
- }
45
- if (way0 == null && group.ways?.[0]?.id != null) {
46
- way0 = group.ways[0].id
47
- }
48
- if (relation0 == null && group.relations?.[0]?.id != null) {
49
- relation0 = group.relations[0].id
50
- }
51
- }
52
- write(await osmBlockToPbfBlobBytes(block))
53
- }
54
-
55
- // Re-parse the new PBF and test
56
- expect(data.buffer).toBeDefined()
57
- // Note: We don't assert byte-level equality because the written PBF may have
58
- // different compression, block ordering, or encoding than the original file.
59
- // Semantic equivalence (verified by parsing and comparing entities) is more meaningful.
60
- const osm2 = await readOsmPbf(data)
61
-
62
- expect(osm.header).toEqual(osm2.header)
63
- const entities = await testOsmPbfReader(osm2, pbf)
64
- if (node0 === null || way0 === null || relation0 === null) {
65
- throw new Error("Expected node0, way0, and relation0 to be set")
66
- }
67
- expect(entities.node0).toBe(node0)
68
- expect(entities.way0).toBe(way0)
69
- expect(entities.relation0).toBe(relation0)
70
- })
71
-
72
- it("to file", async () => {
73
- const testFileName = `${name}-write-test.pbf`
74
- const fileStream = getFixtureFileReadStream(pbf.url)
75
-
76
- const fileWriteStream = getFixtureFileWriteStream(testFileName)
77
- await fileStream
78
- .pipeThrough(new OsmPbfBytesToBlocksTransformStream())
79
- .pipeThrough(new OsmBlocksToPbfBytesTransformStream())
80
- .pipeTo(fileWriteStream)
81
-
82
- const testFileData = await getFixtureFile(pbf.url)
83
- const testOsm = await readOsmPbf(testFileData)
84
-
85
- expect(testOsm.header.bbox).toEqual(pbf.bbox)
86
- await testOsmPbfReader(testOsm, pbf)
87
-
88
- await unlink(getFixturePath(testFileName))
89
- })
90
- })
91
- })
@@ -1,5 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "extends": "./tsconfig.json",
4
- "include": ["src"]
5
- }
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "extends": "@osmix/shared/tsconfig/base.json",
4
- "exclude": ["node_modules", "dist"],
5
- "include": ["src", "test"],
6
- "compilerOptions": {
7
- "outDir": "./dist"
8
- }
9
- }