udbx4ts 0.3.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/dist/index.js ADDED
@@ -0,0 +1,3009 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
5
+ // src/core/sql/SqlHelpers.ts
6
+ async function queryAll(driver, sql, params) {
7
+ const statement = await driver.prepare(sql);
8
+ try {
9
+ if (params) {
10
+ await statement.bind(params);
11
+ }
12
+ const rows = [];
13
+ while (await statement.step()) {
14
+ rows.push(await statement.getRow());
15
+ }
16
+ return rows;
17
+ } finally {
18
+ await statement.finalize();
19
+ }
20
+ }
21
+ async function queryOne(driver, sql, params) {
22
+ const rows = await queryAll(driver, sql, params);
23
+ return rows[0] ?? null;
24
+ }
25
+ async function executeStatement(statement, params) {
26
+ try {
27
+ if (params) {
28
+ await statement.bind(params);
29
+ }
30
+ await statement.step();
31
+ } finally {
32
+ await statement.finalize();
33
+ }
34
+ }
35
+ async function executeSql(driver, sql, params) {
36
+ const statement = await driver.prepare(sql);
37
+ await executeStatement(statement, params);
38
+ }
39
+
40
+ // src/core/schema/UdbxTypeMappings.ts
41
+ var datasetKindToValueMap = {
42
+ tabular: 0,
43
+ point: 1,
44
+ line: 3,
45
+ region: 5,
46
+ pointZ: 101,
47
+ lineZ: 103,
48
+ regionZ: 105,
49
+ text: 7,
50
+ cad: 149
51
+ };
52
+ var datasetValueToKindMap = new Map(
53
+ Object.entries(datasetKindToValueMap).map(([kind, value]) => [
54
+ value,
55
+ kind
56
+ ])
57
+ );
58
+ var fieldTypeToValueMap = {
59
+ boolean: 1,
60
+ byte: 2,
61
+ int16: 3,
62
+ int32: 4,
63
+ int64: 5,
64
+ single: 6,
65
+ double: 7,
66
+ date: 8,
67
+ binary: 9,
68
+ geometry: 10,
69
+ char: 11,
70
+ ntext: 127,
71
+ text: 128,
72
+ time: 16
73
+ };
74
+ var fieldValueToTypeMap = /* @__PURE__ */ new Map([
75
+ [1, "boolean"],
76
+ [2, "byte"],
77
+ [3, "int16"],
78
+ [4, "int32"],
79
+ [5, "int64"],
80
+ [6, "single"],
81
+ [7, "double"],
82
+ [8, "date"],
83
+ [9, "binary"],
84
+ [10, "geometry"],
85
+ [11, "char"],
86
+ [16, "time"],
87
+ [127, "ntext"],
88
+ [128, "text"]
89
+ ]);
90
+ function datasetKindToValue(kind) {
91
+ return datasetKindToValueMap[kind];
92
+ }
93
+ function datasetValueToKind(value) {
94
+ const kind = datasetValueToKindMap.get(value);
95
+ if (!kind) {
96
+ throw new Error(`Unsupported SmDatasetType value: ${value}.`);
97
+ }
98
+ return kind;
99
+ }
100
+ function fieldTypeToValue(type) {
101
+ return fieldTypeToValueMap[type];
102
+ }
103
+ function fieldValueToType(value) {
104
+ const type = fieldValueToTypeMap.get(value);
105
+ if (!type) {
106
+ throw new Error(`Unsupported SmFieldType value: ${value}.`);
107
+ }
108
+ return type;
109
+ }
110
+
111
+ // src/core/schema/SmFieldInfoRepository.ts
112
+ function mapRow(row) {
113
+ return {
114
+ name: row.SmFieldName,
115
+ fieldType: fieldValueToType(row.SmFieldType),
116
+ nullable: row.SmFieldbRequired !== 1,
117
+ defaultValue: row.SmFieldDefaultValue ?? void 0
118
+ };
119
+ }
120
+ var SmFieldInfoRepository = class {
121
+ constructor(driver) {
122
+ this.driver = driver;
123
+ }
124
+ async findByDatasetId(datasetId) {
125
+ const rows = await queryAll(
126
+ this.driver,
127
+ `SELECT
128
+ SmFieldName,
129
+ SmFieldType,
130
+ SmFieldbRequired,
131
+ SmFieldDefaultValue
132
+ FROM SmFieldInfo
133
+ WHERE SmDatasetID = ?
134
+ ORDER BY SmID`,
135
+ [datasetId]
136
+ );
137
+ return rows.map(mapRow);
138
+ }
139
+ async insertAll(datasetId, fields) {
140
+ for (const field of fields) {
141
+ const statement = await this.driver.prepare(
142
+ `INSERT INTO SmFieldInfo (
143
+ SmDatasetID,
144
+ SmFieldName,
145
+ SmFieldType,
146
+ SmFieldCaption,
147
+ SmFieldbRequired,
148
+ SmFieldDefaultValue
149
+ ) VALUES (?, ?, ?, ?, ?, ?)`
150
+ );
151
+ await executeStatement(statement, [
152
+ datasetId,
153
+ field.name,
154
+ fieldTypeToValue(field.fieldType),
155
+ field.name,
156
+ field.nullable ? 0 : 1,
157
+ field.defaultValue == null ? null : String(field.defaultValue)
158
+ ]);
159
+ }
160
+ }
161
+ };
162
+
163
+ // src/core/dataset/BaseDataset.ts
164
+ var BaseDataset = class {
165
+ constructor(driver, info) {
166
+ this.driver = driver;
167
+ this.info = info;
168
+ __publicField(this, "fieldInfoRepository");
169
+ this.fieldInfoRepository = new SmFieldInfoRepository(driver);
170
+ }
171
+ getFields() {
172
+ return this.fieldInfoRepository.findByDatasetId(this.info.id);
173
+ }
174
+ };
175
+
176
+ // src/core/utils/errors.ts
177
+ var NotImplementedError = class extends Error {
178
+ constructor(message) {
179
+ super(message);
180
+ this.name = "NotImplementedError";
181
+ }
182
+ };
183
+ function createNotImplementedError(scope) {
184
+ return new NotImplementedError(`${scope} is not implemented yet.`);
185
+ }
186
+
187
+ // src/core/dataset/CadDataset.ts
188
+ var CadDataset = class extends BaseDataset {
189
+ async getById() {
190
+ throw createNotImplementedError("CadDataset.getById");
191
+ }
192
+ async list() {
193
+ throw createNotImplementedError("CadDataset.list");
194
+ }
195
+ async *iterate() {
196
+ throw createNotImplementedError("CadDataset.iterate");
197
+ }
198
+ async count() {
199
+ throw createNotImplementedError("CadDataset.count");
200
+ }
201
+ async insert() {
202
+ throw createNotImplementedError("CadDataset.insert");
203
+ }
204
+ async insertMany() {
205
+ throw createNotImplementedError("CadDataset.insertMany");
206
+ }
207
+ async update() {
208
+ throw createNotImplementedError("CadDataset.update");
209
+ }
210
+ async delete() {
211
+ throw createNotImplementedError("CadDataset.delete");
212
+ }
213
+ };
214
+
215
+ // src/core/utils/BinaryCursor.ts
216
+ function toUint8Array(input) {
217
+ if (input instanceof Uint8Array) {
218
+ return input;
219
+ }
220
+ if (ArrayBuffer.isView(input)) {
221
+ return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
222
+ }
223
+ return new Uint8Array(input);
224
+ }
225
+ var BinaryCursor = class {
226
+ constructor(input) {
227
+ __publicField(this, "bytes");
228
+ __publicField(this, "view");
229
+ __publicField(this, "offset", 0);
230
+ this.bytes = toUint8Array(input);
231
+ this.view = new DataView(
232
+ this.bytes.buffer,
233
+ this.bytes.byteOffset,
234
+ this.bytes.byteLength
235
+ );
236
+ }
237
+ get length() {
238
+ return this.bytes.byteLength;
239
+ }
240
+ get position() {
241
+ return this.offset;
242
+ }
243
+ get remaining() {
244
+ return this.length - this.offset;
245
+ }
246
+ seek(position) {
247
+ if (position < 0 || position > this.length) {
248
+ throw new RangeError(
249
+ `Cannot seek to ${position}; valid range is 0..${this.length}.`
250
+ );
251
+ }
252
+ this.offset = position;
253
+ }
254
+ skip(length) {
255
+ this.seek(this.offset + length);
256
+ }
257
+ readUint8() {
258
+ this.ensureAvailable(1);
259
+ const value = this.view.getUint8(this.offset);
260
+ this.offset += 1;
261
+ return value;
262
+ }
263
+ readInt32(littleEndian = true) {
264
+ this.ensureAvailable(4);
265
+ const value = this.view.getInt32(this.offset, littleEndian);
266
+ this.offset += 4;
267
+ return value;
268
+ }
269
+ readFloat64(littleEndian = true) {
270
+ this.ensureAvailable(8);
271
+ const value = this.view.getFloat64(this.offset, littleEndian);
272
+ this.offset += 8;
273
+ return value;
274
+ }
275
+ readBytes(length) {
276
+ this.ensureAvailable(length);
277
+ const value = this.bytes.slice(this.offset, this.offset + length);
278
+ this.offset += length;
279
+ return value;
280
+ }
281
+ peekUint8() {
282
+ this.ensureAvailable(1);
283
+ return this.view.getUint8(this.offset);
284
+ }
285
+ ensureAvailable(length) {
286
+ if (length < 0) {
287
+ throw new RangeError("Length must be non-negative.");
288
+ }
289
+ if (this.offset + length > this.length) {
290
+ throw new RangeError(
291
+ `Cannot read ${length} byte(s) from offset ${this.offset}; only ${this.remaining} byte(s) remain.`
292
+ );
293
+ }
294
+ }
295
+ };
296
+
297
+ // src/core/utils/BinaryWriter.ts
298
+ var BinaryWriter = class {
299
+ constructor(initialCapacity = 64) {
300
+ __publicField(this, "buffer");
301
+ __publicField(this, "view");
302
+ __publicField(this, "bytes");
303
+ __publicField(this, "offset", 0);
304
+ if (initialCapacity <= 0) {
305
+ throw new RangeError("Initial capacity must be greater than 0.");
306
+ }
307
+ this.buffer = new ArrayBuffer(initialCapacity);
308
+ this.view = new DataView(this.buffer);
309
+ this.bytes = new Uint8Array(this.buffer);
310
+ }
311
+ get length() {
312
+ return this.offset;
313
+ }
314
+ writeUint8(value) {
315
+ this.ensureCapacity(1);
316
+ this.view.setUint8(this.offset, value);
317
+ this.offset += 1;
318
+ }
319
+ writeInt32(value, littleEndian = true) {
320
+ this.ensureCapacity(4);
321
+ this.view.setInt32(this.offset, value, littleEndian);
322
+ this.offset += 4;
323
+ }
324
+ writeFloat64(value, littleEndian = true) {
325
+ this.ensureCapacity(8);
326
+ this.view.setFloat64(this.offset, value, littleEndian);
327
+ this.offset += 8;
328
+ }
329
+ writeBytes(value) {
330
+ const bytes = value instanceof Uint8Array ? value : ArrayBuffer.isView(value) ? new Uint8Array(value.buffer, value.byteOffset, value.byteLength) : new Uint8Array(value);
331
+ this.ensureCapacity(bytes.byteLength);
332
+ this.bytes.set(bytes, this.offset);
333
+ this.offset += bytes.byteLength;
334
+ }
335
+ toUint8Array() {
336
+ return this.bytes.slice(0, this.offset);
337
+ }
338
+ ensureCapacity(required) {
339
+ if (this.offset + required <= this.buffer.byteLength) {
340
+ return;
341
+ }
342
+ let nextCapacity = this.buffer.byteLength;
343
+ while (this.offset + required > nextCapacity) {
344
+ nextCapacity *= 2;
345
+ }
346
+ const nextBuffer = new ArrayBuffer(nextCapacity);
347
+ const nextBytes = new Uint8Array(nextBuffer);
348
+ nextBytes.set(this.bytes.subarray(0, this.offset));
349
+ this.buffer = nextBuffer;
350
+ this.view = new DataView(this.buffer);
351
+ this.bytes = nextBytes;
352
+ }
353
+ };
354
+
355
+ // src/core/geometry/gaia/GaiaConstants.ts
356
+ var GAIA_START = 0;
357
+ var GAIA_BYTE_ORDER_LE = 1;
358
+ var GAIA_MBR = 124;
359
+ var GAIA_END = 254;
360
+ var GAIA_GEOMETRY_DATA_OFFSET = 43;
361
+ var GEO_TYPE_POINT = 1;
362
+ var GEO_TYPE_POINTZ = 1001;
363
+ var GEO_TYPE_MULTILINESTRING = 5;
364
+ var GEO_TYPE_MULTILINESTRINGZ = 1005;
365
+ var GEO_TYPE_MULTIPOLYGON = 6;
366
+ var GEO_TYPE_MULTIPOLYGONZ = 1006;
367
+
368
+ // src/core/geometry/gaia/GaiaErrors.ts
369
+ var GaiaError = class extends Error {
370
+ constructor(message) {
371
+ super(message);
372
+ this.name = "GaiaError";
373
+ }
374
+ };
375
+ var GaiaFormatError = class extends GaiaError {
376
+ constructor(message) {
377
+ super(message);
378
+ this.name = "GaiaFormatError";
379
+ }
380
+ };
381
+ var GaiaGeoTypeMismatchError = class extends GaiaError {
382
+ constructor(expected, actual) {
383
+ super(`Expected geoType=${expected}, got ${actual}.`);
384
+ this.name = "GaiaGeoTypeMismatchError";
385
+ }
386
+ };
387
+ var GaiaUnsupportedGeoTypeError = class extends GaiaError {
388
+ constructor(geoType) {
389
+ super(`Unsupported GAIA geoType: ${geoType}.`);
390
+ this.name = "GaiaUnsupportedGeoTypeError";
391
+ }
392
+ };
393
+
394
+ // src/core/geometry/gaia/GaiaHeader.ts
395
+ function readGaiaHeader(cursor, expectedGeoType) {
396
+ cursor.seek(0);
397
+ const gaiaStart = cursor.readUint8();
398
+ if (gaiaStart !== GAIA_START) {
399
+ throw new GaiaFormatError(
400
+ `Invalid GAIA start marker: expected 0x${GAIA_START.toString(16)}, got 0x${gaiaStart.toString(16)}.`
401
+ );
402
+ }
403
+ const byteOrder = cursor.readUint8();
404
+ if (byteOrder !== GAIA_BYTE_ORDER_LE) {
405
+ throw new GaiaFormatError(
406
+ `Unsupported byte order: expected 0x${GAIA_BYTE_ORDER_LE.toString(16)}, got 0x${byteOrder.toString(16)}.`
407
+ );
408
+ }
409
+ const srid = cursor.readInt32(true);
410
+ const minX = cursor.readFloat64(true);
411
+ const minY = cursor.readFloat64(true);
412
+ const maxX = cursor.readFloat64(true);
413
+ const maxY = cursor.readFloat64(true);
414
+ const gaiaMbr = cursor.readUint8();
415
+ if (gaiaMbr !== GAIA_MBR) {
416
+ throw new GaiaFormatError(
417
+ `Invalid GAIA MBR marker: expected 0x${GAIA_MBR.toString(16)}, got 0x${gaiaMbr.toString(16)}.`
418
+ );
419
+ }
420
+ const geoType = cursor.readInt32(true);
421
+ if (expectedGeoType !== void 0 && geoType !== expectedGeoType) {
422
+ throw new GaiaGeoTypeMismatchError(expectedGeoType, geoType);
423
+ }
424
+ return {
425
+ byteOrder,
426
+ srid,
427
+ mbr: [minX, minY, maxX, maxY],
428
+ geoType,
429
+ geometryDataOffset: GAIA_GEOMETRY_DATA_OFFSET
430
+ };
431
+ }
432
+ function validateGaiaEnd(cursor) {
433
+ const gaiaEnd = cursor.readUint8();
434
+ if (gaiaEnd !== GAIA_END) {
435
+ throw new GaiaFormatError(
436
+ `Invalid GAIA end marker: expected 0x${GAIA_END.toString(16)}, got 0x${gaiaEnd.toString(16)}.`
437
+ );
438
+ }
439
+ }
440
+
441
+ // src/core/geometry/gaia/GaiaPointCodec.ts
442
+ function isPoint3D(geometry) {
443
+ return geometry.coordinates.length === 3;
444
+ }
445
+ function createPointMbr(coordinates) {
446
+ return [coordinates[0], coordinates[1], coordinates[0], coordinates[1]];
447
+ }
448
+ function writeGaiaHeader(writer2, srid, mbr, geoType) {
449
+ writer2.writeUint8(GAIA_START);
450
+ writer2.writeUint8(GAIA_BYTE_ORDER_LE);
451
+ writer2.writeInt32(srid, true);
452
+ writer2.writeFloat64(mbr[0], true);
453
+ writer2.writeFloat64(mbr[1], true);
454
+ writer2.writeFloat64(mbr[2], true);
455
+ writer2.writeFloat64(mbr[3], true);
456
+ writer2.writeUint8(GAIA_MBR);
457
+ writer2.writeInt32(geoType, true);
458
+ }
459
+ var GaiaPointCodec = class {
460
+ static readPoint(input) {
461
+ const cursor = new BinaryCursor(input);
462
+ const header = readGaiaHeader(cursor, GEO_TYPE_POINT);
463
+ const x = cursor.readFloat64(true);
464
+ const y = cursor.readFloat64(true);
465
+ validateGaiaEnd(cursor);
466
+ return {
467
+ type: "Point",
468
+ coordinates: [x, y],
469
+ srid: header.srid,
470
+ bbox: header.mbr,
471
+ hasZ: false,
472
+ geoType: header.geoType
473
+ };
474
+ }
475
+ static readPointZ(input) {
476
+ const cursor = new BinaryCursor(input);
477
+ const header = readGaiaHeader(cursor, GEO_TYPE_POINTZ);
478
+ const x = cursor.readFloat64(true);
479
+ const y = cursor.readFloat64(true);
480
+ const z = cursor.readFloat64(true);
481
+ validateGaiaEnd(cursor);
482
+ return {
483
+ type: "Point",
484
+ coordinates: [x, y, z],
485
+ srid: header.srid,
486
+ bbox: header.mbr,
487
+ hasZ: true,
488
+ geoType: header.geoType
489
+ };
490
+ }
491
+ static writePoint(geometry, srid) {
492
+ if (isPoint3D(geometry)) {
493
+ throw new GaiaFormatError("writePoint expects a 2D Point geometry.");
494
+ }
495
+ const writer2 = new BinaryWriter(60);
496
+ const mbr = createPointMbr(geometry.coordinates);
497
+ writeGaiaHeader(writer2, srid, mbr, GEO_TYPE_POINT);
498
+ writer2.writeFloat64(geometry.coordinates[0], true);
499
+ writer2.writeFloat64(geometry.coordinates[1], true);
500
+ writer2.writeUint8(GAIA_END);
501
+ return writer2.toUint8Array();
502
+ }
503
+ static writePointZ(geometry, srid) {
504
+ if (!isPoint3D(geometry)) {
505
+ throw new GaiaFormatError("writePointZ expects a 3D Point geometry.");
506
+ }
507
+ const writer2 = new BinaryWriter(68);
508
+ const mbr = createPointMbr(geometry.coordinates);
509
+ writeGaiaHeader(writer2, srid, mbr, GEO_TYPE_POINTZ);
510
+ writer2.writeFloat64(geometry.coordinates[0], true);
511
+ writer2.writeFloat64(geometry.coordinates[1], true);
512
+ writer2.writeFloat64(geometry.coordinates[2], true);
513
+ writer2.writeUint8(GAIA_END);
514
+ return writer2.toUint8Array();
515
+ }
516
+ };
517
+
518
+ // src/core/geometry/gaia/GaiaLineCodec.ts
519
+ var GAIA_ENTITY_MARK = 105;
520
+ var GEO_TYPE_LINESTRING = 2;
521
+ var GEO_TYPE_LINESTRINGZ = 1002;
522
+ function is3DCoordinates(coordinates) {
523
+ return coordinates[0]?.[0]?.length === 3;
524
+ }
525
+ function createLineMbr(coordinates) {
526
+ const xs = [];
527
+ const ys = [];
528
+ for (const line of coordinates) {
529
+ for (const point of line) {
530
+ xs.push(point[0]);
531
+ ys.push(point[1]);
532
+ }
533
+ }
534
+ if (xs.length === 0) {
535
+ throw new GaiaFormatError("MultiLineString must contain at least one point.");
536
+ }
537
+ return [
538
+ Math.min(...xs),
539
+ Math.min(...ys),
540
+ Math.max(...xs),
541
+ Math.max(...ys)
542
+ ];
543
+ }
544
+ var GaiaLineCodec = class {
545
+ static readMultiLineString(input) {
546
+ const cursor = new BinaryCursor(input);
547
+ const header = readGaiaHeader(cursor, GEO_TYPE_MULTILINESTRING);
548
+ const lineCount = cursor.readInt32(true);
549
+ const coordinates = [];
550
+ for (let lineIndex = 0; lineIndex < lineCount; lineIndex += 1) {
551
+ const entityMark = cursor.readUint8();
552
+ if (entityMark !== GAIA_ENTITY_MARK) {
553
+ throw new GaiaFormatError(
554
+ `Invalid LineString entity mark: expected 0x${GAIA_ENTITY_MARK.toString(16)}, got 0x${entityMark.toString(16)}.`
555
+ );
556
+ }
557
+ const lineGeoType = cursor.readInt32(true);
558
+ if (lineGeoType !== GEO_TYPE_LINESTRING) {
559
+ throw new GaiaFormatError(
560
+ `Invalid LineString geoType: expected ${GEO_TYPE_LINESTRING}, got ${lineGeoType}.`
561
+ );
562
+ }
563
+ const pointCount = cursor.readInt32(true);
564
+ const line = [];
565
+ for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
566
+ line.push([cursor.readFloat64(true), cursor.readFloat64(true)]);
567
+ }
568
+ coordinates.push(line);
569
+ }
570
+ validateGaiaEnd(cursor);
571
+ return {
572
+ type: "MultiLineString",
573
+ coordinates,
574
+ srid: header.srid,
575
+ bbox: header.mbr,
576
+ hasZ: false,
577
+ geoType: header.geoType
578
+ };
579
+ }
580
+ static readMultiLineStringZ(input) {
581
+ const cursor = new BinaryCursor(input);
582
+ const header = readGaiaHeader(cursor, GEO_TYPE_MULTILINESTRINGZ);
583
+ const lineCount = cursor.readInt32(true);
584
+ const coordinates = [];
585
+ for (let lineIndex = 0; lineIndex < lineCount; lineIndex += 1) {
586
+ const entityMark = cursor.readUint8();
587
+ if (entityMark !== GAIA_ENTITY_MARK) {
588
+ throw new GaiaFormatError(
589
+ `Invalid LineString entity mark: expected 0x${GAIA_ENTITY_MARK.toString(16)}, got 0x${entityMark.toString(16)}.`
590
+ );
591
+ }
592
+ const lineGeoType = cursor.readInt32(true);
593
+ if (lineGeoType !== GEO_TYPE_LINESTRINGZ) {
594
+ throw new GaiaFormatError(
595
+ `Invalid LineStringZ geoType: expected ${GEO_TYPE_LINESTRINGZ}, got ${lineGeoType}.`
596
+ );
597
+ }
598
+ const pointCount = cursor.readInt32(true);
599
+ const line = [];
600
+ for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
601
+ line.push([
602
+ cursor.readFloat64(true),
603
+ cursor.readFloat64(true),
604
+ cursor.readFloat64(true)
605
+ ]);
606
+ }
607
+ coordinates.push(line);
608
+ }
609
+ validateGaiaEnd(cursor);
610
+ return {
611
+ type: "MultiLineString",
612
+ coordinates,
613
+ srid: header.srid,
614
+ bbox: header.mbr,
615
+ hasZ: true,
616
+ geoType: header.geoType
617
+ };
618
+ }
619
+ static writeMultiLineString(geometry, srid) {
620
+ if (is3DCoordinates(geometry.coordinates)) {
621
+ throw new GaiaFormatError(
622
+ "writeMultiLineString expects 2D coordinates."
623
+ );
624
+ }
625
+ const writer2 = new BinaryWriter();
626
+ writeGaiaHeader(
627
+ writer2,
628
+ srid,
629
+ createLineMbr(geometry.coordinates),
630
+ GEO_TYPE_MULTILINESTRING
631
+ );
632
+ writer2.writeInt32(geometry.coordinates.length, true);
633
+ for (const line of geometry.coordinates) {
634
+ writer2.writeUint8(GAIA_ENTITY_MARK);
635
+ writer2.writeInt32(GEO_TYPE_LINESTRING, true);
636
+ writer2.writeInt32(line.length, true);
637
+ for (const point of line) {
638
+ writer2.writeFloat64(point[0], true);
639
+ writer2.writeFloat64(point[1], true);
640
+ }
641
+ }
642
+ writer2.writeUint8(GAIA_END);
643
+ return writer2.toUint8Array();
644
+ }
645
+ static writeMultiLineStringZ(geometry, srid) {
646
+ if (!is3DCoordinates(geometry.coordinates)) {
647
+ throw new GaiaFormatError(
648
+ "writeMultiLineStringZ expects 3D coordinates."
649
+ );
650
+ }
651
+ const writer2 = new BinaryWriter();
652
+ writeGaiaHeader(
653
+ writer2,
654
+ srid,
655
+ createLineMbr(geometry.coordinates),
656
+ GEO_TYPE_MULTILINESTRINGZ
657
+ );
658
+ writer2.writeInt32(geometry.coordinates.length, true);
659
+ for (const line of geometry.coordinates) {
660
+ writer2.writeUint8(GAIA_ENTITY_MARK);
661
+ writer2.writeInt32(GEO_TYPE_LINESTRINGZ, true);
662
+ writer2.writeInt32(line.length, true);
663
+ for (const point of line) {
664
+ writer2.writeFloat64(point[0], true);
665
+ writer2.writeFloat64(point[1], true);
666
+ writer2.writeFloat64(point[2], true);
667
+ }
668
+ }
669
+ writer2.writeUint8(GAIA_END);
670
+ return writer2.toUint8Array();
671
+ }
672
+ };
673
+
674
+ // src/core/schema/SmRegisterRepository.ts
675
+ function mapRow2(row) {
676
+ return {
677
+ id: row.SmDatasetID,
678
+ name: row.SmDatasetName,
679
+ kind: datasetValueToKind(row.SmDatasetType),
680
+ tableName: row.SmTableName,
681
+ srid: row.SmSRID ?? null,
682
+ objectCount: row.SmObjectCount,
683
+ geometryType: row.geometryType ?? null
684
+ };
685
+ }
686
+ var SmRegisterRepository = class {
687
+ constructor(driver) {
688
+ this.driver = driver;
689
+ }
690
+ async findAll() {
691
+ const rows = await queryAll(
692
+ this.driver,
693
+ `SELECT
694
+ SmDatasetID,
695
+ SmDatasetName,
696
+ SmTableName,
697
+ SmDatasetType,
698
+ SmObjectCount,
699
+ SmSRID
700
+ FROM SmRegister
701
+ ORDER BY SmDatasetID`
702
+ );
703
+ return rows.map(mapRow2);
704
+ }
705
+ async findByName(name) {
706
+ const row = await queryOne(
707
+ this.driver,
708
+ `SELECT
709
+ SmDatasetID,
710
+ SmDatasetName,
711
+ SmTableName,
712
+ SmDatasetType,
713
+ SmObjectCount,
714
+ SmSRID
715
+ FROM SmRegister
716
+ WHERE SmDatasetName = ?`,
717
+ [name]
718
+ );
719
+ return row ? mapRow2(row) : null;
720
+ }
721
+ async nextDatasetId() {
722
+ const row = await queryOne(
723
+ this.driver,
724
+ "SELECT COALESCE(MAX(SmDatasetID), 0) + 1 AS nextId FROM SmRegister"
725
+ );
726
+ return row?.nextId ?? 1;
727
+ }
728
+ async insert(params) {
729
+ const datasetId = await this.nextDatasetId();
730
+ const statement = await this.driver.prepare(
731
+ `INSERT INTO SmRegister (
732
+ SmDatasetID,
733
+ SmDatasetName,
734
+ SmTableName,
735
+ SmDatasetType,
736
+ SmObjectCount,
737
+ SmSRID,
738
+ SmIDColName,
739
+ SmGeoColName,
740
+ SmMaxGeometrySize,
741
+ SmCreateTime,
742
+ SmLastUpdateTime
743
+ ) VALUES (?, ?, ?, ?, 0, ?, ?, ?, 0, datetime('now'), datetime('now'))`
744
+ );
745
+ await executeStatement(statement, [
746
+ datasetId,
747
+ params.name,
748
+ params.name,
749
+ datasetKindToValue(params.kind),
750
+ params.srid,
751
+ params.idColumnName,
752
+ params.geometryColumnName
753
+ ]);
754
+ return datasetId;
755
+ }
756
+ async incrementObjectCount(datasetId, geometrySize) {
757
+ if (geometrySize === void 0) {
758
+ const statement2 = await this.driver.prepare(
759
+ "UPDATE SmRegister SET SmObjectCount = SmObjectCount + 1 WHERE SmDatasetID = ?"
760
+ );
761
+ await executeStatement(statement2, [datasetId]);
762
+ return;
763
+ }
764
+ const statement = await this.driver.prepare(
765
+ `UPDATE SmRegister
766
+ SET SmObjectCount = SmObjectCount + 1,
767
+ SmMaxGeometrySize = CASE
768
+ WHEN SmMaxGeometrySize < ? THEN ?
769
+ ELSE SmMaxGeometrySize
770
+ END
771
+ WHERE SmDatasetID = ?`
772
+ );
773
+ await executeStatement(statement, [geometrySize, geometrySize, datasetId]);
774
+ }
775
+ async incrementObjectCountBatch(datasetId, count, maxGeometrySize) {
776
+ const statement = await this.driver.prepare(
777
+ `UPDATE SmRegister
778
+ SET SmObjectCount = SmObjectCount + ?,
779
+ SmMaxGeometrySize = CASE
780
+ WHEN SmMaxGeometrySize < ? THEN ?
781
+ ELSE SmMaxGeometrySize
782
+ END
783
+ WHERE SmDatasetID = ?`
784
+ );
785
+ await executeStatement(statement, [
786
+ count,
787
+ maxGeometrySize,
788
+ maxGeometrySize,
789
+ datasetId
790
+ ]);
791
+ }
792
+ async decrementObjectCount(datasetId) {
793
+ const statement = await this.driver.prepare(
794
+ "UPDATE SmRegister SET SmObjectCount = SmObjectCount - 1 WHERE SmDatasetID = ? AND SmObjectCount > 0"
795
+ );
796
+ await executeStatement(statement, [datasetId]);
797
+ }
798
+ };
799
+
800
+ // src/core/dataset/vectorDatasetShared.ts
801
+ function normalizeGeometryBlob(value) {
802
+ return value instanceof Uint8Array ? value : new Uint8Array(value);
803
+ }
804
+ function buildListSql(tableName, options) {
805
+ const params = [];
806
+ const clauses = [];
807
+ if (options?.ids?.length) {
808
+ const placeholders = options.ids.map(() => "?").join(", ");
809
+ clauses.push(`SmID IN (${placeholders})`);
810
+ params.push(...options.ids);
811
+ }
812
+ const whereClause = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
813
+ let sql = `SELECT * FROM "${tableName}"${whereClause} ORDER BY SmID`;
814
+ if (options?.limit !== void 0) {
815
+ sql += " LIMIT ?";
816
+ params.push(options.limit);
817
+ }
818
+ if (options?.offset !== void 0) {
819
+ if (options.limit === void 0) {
820
+ sql += " LIMIT -1";
821
+ }
822
+ sql += " OFFSET ?";
823
+ params.push(options.offset);
824
+ }
825
+ return { sql, params };
826
+ }
827
+ function sqliteColumnType(field) {
828
+ switch (field.fieldType) {
829
+ case "boolean":
830
+ case "byte":
831
+ case "int16":
832
+ case "int32":
833
+ case "int64":
834
+ return "INTEGER";
835
+ case "single":
836
+ case "double":
837
+ return "REAL";
838
+ case "binary":
839
+ case "geometry":
840
+ return "BLOB";
841
+ case "date":
842
+ case "char":
843
+ case "ntext":
844
+ case "text":
845
+ case "time":
846
+ default:
847
+ return "TEXT";
848
+ }
849
+ }
850
+
851
+ // src/core/dataset/LineDataset.ts
852
+ function mapLineRow(row) {
853
+ const { SmID, SmGeometry, ...attributes } = row;
854
+ return {
855
+ id: SmID,
856
+ geometry: GaiaLineCodec.readMultiLineString(normalizeGeometryBlob(SmGeometry)),
857
+ attributes
858
+ };
859
+ }
860
+ var LineDataset = class _LineDataset extends BaseDataset {
861
+ constructor(driver, info) {
862
+ super(driver, info);
863
+ __publicField(this, "registerRepository");
864
+ this.registerRepository = new SmRegisterRepository(driver);
865
+ }
866
+ async getById(id) {
867
+ const row = await queryOne(
868
+ this.driver,
869
+ `SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
870
+ [id]
871
+ );
872
+ return row ? mapLineRow(row) : null;
873
+ }
874
+ async list(options) {
875
+ const { sql, params } = buildListSql(this.info.tableName, options);
876
+ const rows = await queryAll(this.driver, sql, params);
877
+ return rows.map((row) => mapLineRow(row));
878
+ }
879
+ async *iterate(options) {
880
+ const { sql, params } = buildListSql(this.info.tableName, options);
881
+ const statement = await this.driver.prepare(sql);
882
+ try {
883
+ if (params.length > 0) {
884
+ await statement.bind(params);
885
+ }
886
+ while (await statement.step()) {
887
+ yield mapLineRow(await statement.getRow());
888
+ }
889
+ } finally {
890
+ await statement.finalize();
891
+ }
892
+ }
893
+ async insert(feature) {
894
+ const userFields = await this.getFields();
895
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
896
+ const placeholders = columnNames.map(() => "?").join(", ");
897
+ const geometry = GaiaLineCodec.writeMultiLineString(
898
+ feature.geometry,
899
+ feature.geometry.srid ?? this.info.srid ?? 0
900
+ );
901
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
902
+ const params = [
903
+ feature.id,
904
+ 0,
905
+ geometry,
906
+ ...userFields.map((field) => feature.attributes[field.name] ?? null)
907
+ ];
908
+ await this.driver.transaction(async () => {
909
+ await executeSql(this.driver, sql, params);
910
+ await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
911
+ });
912
+ }
913
+ async insertMany(features) {
914
+ const userFields = await this.getFields();
915
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
916
+ const placeholders = columnNames.map(() => "?").join(", ");
917
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
918
+ await this.driver.transaction(async () => {
919
+ const statement = await this.driver.prepare(sql);
920
+ try {
921
+ let count = 0;
922
+ let maxGeometrySize = 0;
923
+ for await (const feature of features) {
924
+ const geometry = GaiaLineCodec.writeMultiLineString(
925
+ feature.geometry,
926
+ feature.geometry.srid ?? this.info.srid ?? 0
927
+ );
928
+ maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
929
+ const params = [
930
+ feature.id,
931
+ 0,
932
+ geometry,
933
+ ...userFields.map(
934
+ (field) => feature.attributes[field.name] ?? null
935
+ )
936
+ ];
937
+ await statement.bind(params);
938
+ await statement.step();
939
+ await statement.reset();
940
+ count++;
941
+ }
942
+ if (count > 0) {
943
+ await this.registerRepository.incrementObjectCountBatch(
944
+ this.info.id,
945
+ count,
946
+ maxGeometrySize
947
+ );
948
+ }
949
+ } finally {
950
+ await statement.finalize();
951
+ }
952
+ });
953
+ }
954
+ async count() {
955
+ const row = await queryOne(
956
+ this.driver,
957
+ `SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
958
+ []
959
+ );
960
+ return row?.count ?? 0;
961
+ }
962
+ async update(id, changes) {
963
+ if (!changes.geometry && !changes.attributes) {
964
+ return;
965
+ }
966
+ const setClauses = [];
967
+ const params = [];
968
+ if (changes.geometry) {
969
+ const geometry = GaiaLineCodec.writeMultiLineString(
970
+ changes.geometry,
971
+ changes.geometry.srid ?? this.info.srid ?? 0
972
+ );
973
+ setClauses.push('"SmGeometry" = ?');
974
+ params.push(geometry);
975
+ }
976
+ if (changes.attributes) {
977
+ const userFields = await this.getFields();
978
+ const fieldNames = new Set(userFields.map((f) => f.name));
979
+ const validEntries = Object.entries(changes.attributes).filter(
980
+ ([key]) => fieldNames.has(key)
981
+ );
982
+ for (const [key, value] of validEntries) {
983
+ setClauses.push(`"${key}" = ?`);
984
+ params.push(value);
985
+ }
986
+ }
987
+ if (setClauses.length === 0) {
988
+ return;
989
+ }
990
+ const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
991
+ params.push(id);
992
+ await this.driver.transaction(async () => {
993
+ await executeSql(this.driver, sql, params);
994
+ });
995
+ }
996
+ async delete(id) {
997
+ await this.driver.transaction(async () => {
998
+ await executeSql(
999
+ this.driver,
1000
+ `DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
1001
+ [id]
1002
+ );
1003
+ await this.registerRepository.decrementObjectCount(this.info.id);
1004
+ });
1005
+ }
1006
+ static async create(driver, registerRepository, params) {
1007
+ const fields = params.fields ?? [];
1008
+ const datasetId = await registerRepository.insert({
1009
+ name: params.name,
1010
+ kind: "line",
1011
+ srid: params.srid,
1012
+ idColumnName: "SmID",
1013
+ geometryColumnName: "SmGeometry"
1014
+ });
1015
+ const userColumnDefinitions = fields.map((field) => {
1016
+ const nullability = field.nullable ? "" : " NOT NULL";
1017
+ return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
1018
+ });
1019
+ const createTableParts = [
1020
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
1021
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
1022
+ `"SmGeometry" BLOB NOT NULL`,
1023
+ ...userColumnDefinitions
1024
+ ];
1025
+ await driver.exec(
1026
+ `CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
1027
+ );
1028
+ await executeSql(
1029
+ driver,
1030
+ `INSERT INTO geometry_columns (
1031
+ f_table_name,
1032
+ f_geometry_column,
1033
+ geometry_type,
1034
+ coord_dimension,
1035
+ srid,
1036
+ spatial_index_enabled
1037
+ ) VALUES (?, ?, ?, ?, ?, ?)`,
1038
+ [params.name, "SmGeometry", 5, 2, params.srid, 0]
1039
+ );
1040
+ if (fields.length > 0) {
1041
+ const fieldInfoRepository = new SmFieldInfoRepository(driver);
1042
+ await fieldInfoRepository.insertAll(datasetId, fields);
1043
+ }
1044
+ return new _LineDataset(driver, {
1045
+ id: datasetId,
1046
+ name: params.name,
1047
+ kind: "line",
1048
+ tableName: params.name,
1049
+ srid: params.srid,
1050
+ objectCount: 0,
1051
+ geometryType: 5
1052
+ });
1053
+ }
1054
+ };
1055
+
1056
+ // src/core/dataset/LineZDataset.ts
1057
+ function mapLineZRow(row) {
1058
+ const { SmID, SmGeometry, ...attributes } = row;
1059
+ return {
1060
+ id: SmID,
1061
+ geometry: GaiaLineCodec.readMultiLineStringZ(normalizeGeometryBlob(SmGeometry)),
1062
+ attributes
1063
+ };
1064
+ }
1065
+ var LineZDataset = class _LineZDataset extends BaseDataset {
1066
+ constructor(driver, info) {
1067
+ super(driver, info);
1068
+ __publicField(this, "registerRepository");
1069
+ this.registerRepository = new SmRegisterRepository(driver);
1070
+ }
1071
+ async getById(id) {
1072
+ const row = await queryOne(
1073
+ this.driver,
1074
+ `SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
1075
+ [id]
1076
+ );
1077
+ return row ? mapLineZRow(row) : null;
1078
+ }
1079
+ async list(options) {
1080
+ const { sql, params } = buildListSql(this.info.tableName, options);
1081
+ const rows = await queryAll(this.driver, sql, params);
1082
+ return rows.map((row) => mapLineZRow(row));
1083
+ }
1084
+ async *iterate(options) {
1085
+ const { sql, params } = buildListSql(this.info.tableName, options);
1086
+ const statement = await this.driver.prepare(sql);
1087
+ try {
1088
+ if (params.length > 0) {
1089
+ await statement.bind(params);
1090
+ }
1091
+ while (await statement.step()) {
1092
+ yield mapLineZRow(await statement.getRow());
1093
+ }
1094
+ } finally {
1095
+ await statement.finalize();
1096
+ }
1097
+ }
1098
+ async count() {
1099
+ const row = await queryOne(
1100
+ this.driver,
1101
+ `SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
1102
+ []
1103
+ );
1104
+ return row?.count ?? 0;
1105
+ }
1106
+ async insert(feature) {
1107
+ const userFields = await this.getFields();
1108
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
1109
+ const placeholders = columnNames.map(() => "?").join(", ");
1110
+ const geometry = GaiaLineCodec.writeMultiLineStringZ(
1111
+ feature.geometry,
1112
+ feature.geometry.srid ?? this.info.srid ?? 0
1113
+ );
1114
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
1115
+ const params = [
1116
+ feature.id,
1117
+ 0,
1118
+ geometry,
1119
+ ...userFields.map((field) => feature.attributes[field.name] ?? null)
1120
+ ];
1121
+ await this.driver.transaction(async () => {
1122
+ await executeSql(this.driver, sql, params);
1123
+ await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
1124
+ });
1125
+ }
1126
+ async insertMany(features) {
1127
+ const userFields = await this.getFields();
1128
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
1129
+ const placeholders = columnNames.map(() => "?").join(", ");
1130
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
1131
+ await this.driver.transaction(async () => {
1132
+ const statement = await this.driver.prepare(sql);
1133
+ try {
1134
+ let count = 0;
1135
+ let maxGeometrySize = 0;
1136
+ for await (const feature of features) {
1137
+ const geometry = GaiaLineCodec.writeMultiLineStringZ(
1138
+ feature.geometry,
1139
+ feature.geometry.srid ?? this.info.srid ?? 0
1140
+ );
1141
+ maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
1142
+ const params = [
1143
+ feature.id,
1144
+ 0,
1145
+ geometry,
1146
+ ...userFields.map(
1147
+ (field) => feature.attributes[field.name] ?? null
1148
+ )
1149
+ ];
1150
+ await statement.bind(params);
1151
+ await statement.step();
1152
+ await statement.reset();
1153
+ count++;
1154
+ }
1155
+ if (count > 0) {
1156
+ await this.registerRepository.incrementObjectCountBatch(
1157
+ this.info.id,
1158
+ count,
1159
+ maxGeometrySize
1160
+ );
1161
+ }
1162
+ } finally {
1163
+ await statement.finalize();
1164
+ }
1165
+ });
1166
+ }
1167
+ async update(id, changes) {
1168
+ if (!changes.geometry && !changes.attributes) {
1169
+ return;
1170
+ }
1171
+ const setClauses = [];
1172
+ const params = [];
1173
+ if (changes.geometry) {
1174
+ const geometry = GaiaLineCodec.writeMultiLineStringZ(
1175
+ changes.geometry,
1176
+ changes.geometry.srid ?? this.info.srid ?? 0
1177
+ );
1178
+ setClauses.push('"SmGeometry" = ?');
1179
+ params.push(geometry);
1180
+ }
1181
+ if (changes.attributes) {
1182
+ const userFields = await this.getFields();
1183
+ const fieldNames = new Set(userFields.map((f) => f.name));
1184
+ const validEntries = Object.entries(changes.attributes).filter(
1185
+ ([key]) => fieldNames.has(key)
1186
+ );
1187
+ for (const [key, value] of validEntries) {
1188
+ setClauses.push(`"${key}" = ?`);
1189
+ params.push(value);
1190
+ }
1191
+ }
1192
+ if (setClauses.length === 0) {
1193
+ return;
1194
+ }
1195
+ const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
1196
+ params.push(id);
1197
+ await this.driver.transaction(async () => {
1198
+ await executeSql(this.driver, sql, params);
1199
+ });
1200
+ }
1201
+ async delete(id) {
1202
+ await this.driver.transaction(async () => {
1203
+ await executeSql(
1204
+ this.driver,
1205
+ `DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
1206
+ [id]
1207
+ );
1208
+ await this.registerRepository.decrementObjectCount(this.info.id);
1209
+ });
1210
+ }
1211
+ static async create(driver, registerRepository, params) {
1212
+ const fields = params.fields ?? [];
1213
+ const datasetId = await registerRepository.insert({
1214
+ name: params.name,
1215
+ kind: "lineZ",
1216
+ srid: params.srid,
1217
+ idColumnName: "SmID",
1218
+ geometryColumnName: "SmGeometry"
1219
+ });
1220
+ const userColumnDefinitions = fields.map((field) => {
1221
+ const nullability = field.nullable ? "" : " NOT NULL";
1222
+ return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
1223
+ });
1224
+ const createTableParts = [
1225
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
1226
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
1227
+ `"SmGeometry" BLOB NOT NULL`,
1228
+ ...userColumnDefinitions
1229
+ ];
1230
+ await driver.exec(
1231
+ `CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
1232
+ );
1233
+ await executeSql(
1234
+ driver,
1235
+ `INSERT INTO geometry_columns (
1236
+ f_table_name,
1237
+ f_geometry_column,
1238
+ geometry_type,
1239
+ coord_dimension,
1240
+ srid,
1241
+ spatial_index_enabled
1242
+ ) VALUES (?, ?, ?, ?, ?, ?)`,
1243
+ [params.name, "SmGeometry", 1005, 3, params.srid, 0]
1244
+ );
1245
+ if (fields.length > 0) {
1246
+ const fieldInfoRepository = new SmFieldInfoRepository(driver);
1247
+ await fieldInfoRepository.insertAll(datasetId, fields);
1248
+ }
1249
+ return new _LineZDataset(driver, {
1250
+ id: datasetId,
1251
+ name: params.name,
1252
+ kind: "lineZ",
1253
+ tableName: params.name,
1254
+ srid: params.srid,
1255
+ objectCount: 0,
1256
+ geometryType: 1005
1257
+ });
1258
+ }
1259
+ };
1260
+
1261
+ // src/core/dataset/PointDataset.ts
1262
+ function mapPointRow(row) {
1263
+ const { SmID, SmGeometry, ...attributes } = row;
1264
+ return {
1265
+ id: SmID,
1266
+ geometry: GaiaPointCodec.readPoint(normalizeGeometryBlob(SmGeometry)),
1267
+ attributes
1268
+ };
1269
+ }
1270
+ var PointDataset = class _PointDataset extends BaseDataset {
1271
+ constructor(driver, info) {
1272
+ super(driver, info);
1273
+ __publicField(this, "registerRepository");
1274
+ this.registerRepository = new SmRegisterRepository(driver);
1275
+ }
1276
+ async getById(id) {
1277
+ const row = await queryOne(
1278
+ this.driver,
1279
+ `SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
1280
+ [id]
1281
+ );
1282
+ return row ? mapPointRow(row) : null;
1283
+ }
1284
+ async list(options) {
1285
+ const { sql, params } = buildListSql(this.info.tableName, options);
1286
+ const rows = await queryAll(this.driver, sql, params);
1287
+ return rows.map((row) => mapPointRow(row));
1288
+ }
1289
+ async *iterate(options) {
1290
+ const { sql, params } = buildListSql(this.info.tableName, options);
1291
+ const statement = await this.driver.prepare(sql);
1292
+ try {
1293
+ if (params.length > 0) {
1294
+ await statement.bind(params);
1295
+ }
1296
+ while (await statement.step()) {
1297
+ yield mapPointRow(await statement.getRow());
1298
+ }
1299
+ } finally {
1300
+ await statement.finalize();
1301
+ }
1302
+ }
1303
+ async insert(feature) {
1304
+ const userFields = await this.getFields();
1305
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
1306
+ const placeholders = columnNames.map(() => "?").join(", ");
1307
+ const geometry = GaiaPointCodec.writePoint(feature.geometry, feature.geometry.srid ?? this.info.srid ?? 0);
1308
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
1309
+ const params = [
1310
+ feature.id,
1311
+ 0,
1312
+ geometry,
1313
+ ...userFields.map((field) => feature.attributes[field.name] ?? null)
1314
+ ];
1315
+ await this.driver.transaction(async () => {
1316
+ await executeSql(this.driver, sql, params);
1317
+ await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
1318
+ });
1319
+ }
1320
+ async insertMany(features) {
1321
+ const userFields = await this.getFields();
1322
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
1323
+ const placeholders = columnNames.map(() => "?").join(", ");
1324
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
1325
+ await this.driver.transaction(async () => {
1326
+ const statement = await this.driver.prepare(sql);
1327
+ try {
1328
+ let count = 0;
1329
+ let maxGeometrySize = 0;
1330
+ for await (const feature of features) {
1331
+ const geometry = GaiaPointCodec.writePoint(
1332
+ feature.geometry,
1333
+ feature.geometry.srid ?? this.info.srid ?? 0
1334
+ );
1335
+ maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
1336
+ const params = [
1337
+ feature.id,
1338
+ 0,
1339
+ geometry,
1340
+ ...userFields.map(
1341
+ (field) => feature.attributes[field.name] ?? null
1342
+ )
1343
+ ];
1344
+ await statement.bind(params);
1345
+ await statement.step();
1346
+ await statement.reset();
1347
+ count++;
1348
+ }
1349
+ if (count > 0) {
1350
+ await this.registerRepository.incrementObjectCountBatch(
1351
+ this.info.id,
1352
+ count,
1353
+ maxGeometrySize
1354
+ );
1355
+ }
1356
+ } finally {
1357
+ await statement.finalize();
1358
+ }
1359
+ });
1360
+ }
1361
+ async count() {
1362
+ const row = await queryOne(
1363
+ this.driver,
1364
+ `SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
1365
+ []
1366
+ );
1367
+ return row?.count ?? 0;
1368
+ }
1369
+ async update(id, changes) {
1370
+ if (!changes.geometry && !changes.attributes) {
1371
+ return;
1372
+ }
1373
+ const setClauses = [];
1374
+ const params = [];
1375
+ if (changes.geometry) {
1376
+ const geometry = GaiaPointCodec.writePoint(
1377
+ changes.geometry,
1378
+ changes.geometry.srid ?? this.info.srid ?? 0
1379
+ );
1380
+ setClauses.push('"SmGeometry" = ?');
1381
+ params.push(geometry);
1382
+ }
1383
+ if (changes.attributes) {
1384
+ const userFields = await this.getFields();
1385
+ const fieldNames = new Set(userFields.map((f) => f.name));
1386
+ const validEntries = Object.entries(changes.attributes).filter(
1387
+ ([key]) => fieldNames.has(key)
1388
+ );
1389
+ for (const [key, value] of validEntries) {
1390
+ setClauses.push(`"${key}" = ?`);
1391
+ params.push(value);
1392
+ }
1393
+ }
1394
+ if (setClauses.length === 0) {
1395
+ return;
1396
+ }
1397
+ const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
1398
+ params.push(id);
1399
+ await this.driver.transaction(async () => {
1400
+ await executeSql(this.driver, sql, params);
1401
+ });
1402
+ }
1403
+ async delete(id) {
1404
+ await this.driver.transaction(async () => {
1405
+ await executeSql(
1406
+ this.driver,
1407
+ `DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
1408
+ [id]
1409
+ );
1410
+ await this.registerRepository.decrementObjectCount(this.info.id);
1411
+ });
1412
+ }
1413
+ static async create(driver, registerRepository, params) {
1414
+ const fields = params.fields ?? [];
1415
+ const datasetId = await registerRepository.insert({
1416
+ name: params.name,
1417
+ kind: "point",
1418
+ srid: params.srid,
1419
+ idColumnName: "SmID",
1420
+ geometryColumnName: "SmGeometry"
1421
+ });
1422
+ const userColumnDefinitions = fields.map((field) => {
1423
+ const nullability = field.nullable ? "" : " NOT NULL";
1424
+ return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
1425
+ });
1426
+ const createTableParts = [
1427
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
1428
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
1429
+ `"SmGeometry" BLOB NOT NULL`,
1430
+ ...userColumnDefinitions
1431
+ ];
1432
+ await driver.exec(
1433
+ `CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
1434
+ );
1435
+ await executeSql(
1436
+ driver,
1437
+ `INSERT INTO geometry_columns (
1438
+ f_table_name,
1439
+ f_geometry_column,
1440
+ geometry_type,
1441
+ coord_dimension,
1442
+ srid,
1443
+ spatial_index_enabled
1444
+ ) VALUES (?, ?, ?, ?, ?, ?)`,
1445
+ [params.name, "SmGeometry", 1, 2, params.srid, 0]
1446
+ );
1447
+ if (fields.length > 0) {
1448
+ const fieldInfoRepository = new SmFieldInfoRepository(driver);
1449
+ await fieldInfoRepository.insertAll(datasetId, fields);
1450
+ }
1451
+ return new _PointDataset(driver, {
1452
+ id: datasetId,
1453
+ name: params.name,
1454
+ kind: "point",
1455
+ tableName: params.name,
1456
+ srid: params.srid,
1457
+ objectCount: 0,
1458
+ geometryType: 1
1459
+ });
1460
+ }
1461
+ };
1462
+
1463
+ // src/core/dataset/PointZDataset.ts
1464
+ function mapPointZRow(row) {
1465
+ const { SmID, SmGeometry, ...attributes } = row;
1466
+ return {
1467
+ id: SmID,
1468
+ geometry: GaiaPointCodec.readPointZ(normalizeGeometryBlob(SmGeometry)),
1469
+ attributes
1470
+ };
1471
+ }
1472
+ var PointZDataset = class _PointZDataset extends BaseDataset {
1473
+ constructor(driver, info) {
1474
+ super(driver, info);
1475
+ __publicField(this, "registerRepository");
1476
+ this.registerRepository = new SmRegisterRepository(driver);
1477
+ }
1478
+ async getById(id) {
1479
+ const row = await queryOne(
1480
+ this.driver,
1481
+ `SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
1482
+ [id]
1483
+ );
1484
+ return row ? mapPointZRow(row) : null;
1485
+ }
1486
+ async list(options) {
1487
+ const { sql, params } = buildListSql(this.info.tableName, options);
1488
+ const rows = await queryAll(this.driver, sql, params);
1489
+ return rows.map((row) => mapPointZRow(row));
1490
+ }
1491
+ async *iterate(options) {
1492
+ const { sql, params } = buildListSql(this.info.tableName, options);
1493
+ const statement = await this.driver.prepare(sql);
1494
+ try {
1495
+ if (params.length > 0) {
1496
+ await statement.bind(params);
1497
+ }
1498
+ while (await statement.step()) {
1499
+ yield mapPointZRow(await statement.getRow());
1500
+ }
1501
+ } finally {
1502
+ await statement.finalize();
1503
+ }
1504
+ }
1505
+ async count() {
1506
+ const row = await queryOne(
1507
+ this.driver,
1508
+ `SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
1509
+ []
1510
+ );
1511
+ return row?.count ?? 0;
1512
+ }
1513
+ async insert(feature) {
1514
+ const userFields = await this.getFields();
1515
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
1516
+ const placeholders = columnNames.map(() => "?").join(", ");
1517
+ const geometry = GaiaPointCodec.writePointZ(
1518
+ feature.geometry,
1519
+ feature.geometry.srid ?? this.info.srid ?? 0
1520
+ );
1521
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
1522
+ const params = [
1523
+ feature.id,
1524
+ 0,
1525
+ geometry,
1526
+ ...userFields.map((field) => feature.attributes[field.name] ?? null)
1527
+ ];
1528
+ await this.driver.transaction(async () => {
1529
+ await executeSql(this.driver, sql, params);
1530
+ await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
1531
+ });
1532
+ }
1533
+ async insertMany(features) {
1534
+ const userFields = await this.getFields();
1535
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
1536
+ const placeholders = columnNames.map(() => "?").join(", ");
1537
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
1538
+ await this.driver.transaction(async () => {
1539
+ const statement = await this.driver.prepare(sql);
1540
+ try {
1541
+ let count = 0;
1542
+ let maxGeometrySize = 0;
1543
+ for await (const feature of features) {
1544
+ const geometry = GaiaPointCodec.writePointZ(
1545
+ feature.geometry,
1546
+ feature.geometry.srid ?? this.info.srid ?? 0
1547
+ );
1548
+ maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
1549
+ const params = [
1550
+ feature.id,
1551
+ 0,
1552
+ geometry,
1553
+ ...userFields.map(
1554
+ (field) => feature.attributes[field.name] ?? null
1555
+ )
1556
+ ];
1557
+ await statement.bind(params);
1558
+ await statement.step();
1559
+ await statement.reset();
1560
+ count++;
1561
+ }
1562
+ if (count > 0) {
1563
+ await this.registerRepository.incrementObjectCountBatch(
1564
+ this.info.id,
1565
+ count,
1566
+ maxGeometrySize
1567
+ );
1568
+ }
1569
+ } finally {
1570
+ await statement.finalize();
1571
+ }
1572
+ });
1573
+ }
1574
+ async update(id, changes) {
1575
+ if (!changes.geometry && !changes.attributes) {
1576
+ return;
1577
+ }
1578
+ const setClauses = [];
1579
+ const params = [];
1580
+ if (changes.geometry) {
1581
+ const geometry = GaiaPointCodec.writePointZ(
1582
+ changes.geometry,
1583
+ changes.geometry.srid ?? this.info.srid ?? 0
1584
+ );
1585
+ setClauses.push('"SmGeometry" = ?');
1586
+ params.push(geometry);
1587
+ }
1588
+ if (changes.attributes) {
1589
+ const userFields = await this.getFields();
1590
+ const fieldNames = new Set(userFields.map((f) => f.name));
1591
+ const validEntries = Object.entries(changes.attributes).filter(
1592
+ ([key]) => fieldNames.has(key)
1593
+ );
1594
+ for (const [key, value] of validEntries) {
1595
+ setClauses.push(`"${key}" = ?`);
1596
+ params.push(value);
1597
+ }
1598
+ }
1599
+ if (setClauses.length === 0) {
1600
+ return;
1601
+ }
1602
+ const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
1603
+ params.push(id);
1604
+ await this.driver.transaction(async () => {
1605
+ await executeSql(this.driver, sql, params);
1606
+ });
1607
+ }
1608
+ async delete(id) {
1609
+ await this.driver.transaction(async () => {
1610
+ await executeSql(
1611
+ this.driver,
1612
+ `DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
1613
+ [id]
1614
+ );
1615
+ await this.registerRepository.decrementObjectCount(this.info.id);
1616
+ });
1617
+ }
1618
+ static async create(driver, registerRepository, params) {
1619
+ const fields = params.fields ?? [];
1620
+ const datasetId = await registerRepository.insert({
1621
+ name: params.name,
1622
+ kind: "pointZ",
1623
+ srid: params.srid,
1624
+ idColumnName: "SmID",
1625
+ geometryColumnName: "SmGeometry"
1626
+ });
1627
+ const userColumnDefinitions = fields.map((field) => {
1628
+ const nullability = field.nullable ? "" : " NOT NULL";
1629
+ return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
1630
+ });
1631
+ const createTableParts = [
1632
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
1633
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
1634
+ `"SmGeometry" BLOB NOT NULL`,
1635
+ ...userColumnDefinitions
1636
+ ];
1637
+ await driver.exec(
1638
+ `CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
1639
+ );
1640
+ await executeSql(
1641
+ driver,
1642
+ `INSERT INTO geometry_columns (
1643
+ f_table_name,
1644
+ f_geometry_column,
1645
+ geometry_type,
1646
+ coord_dimension,
1647
+ srid,
1648
+ spatial_index_enabled
1649
+ ) VALUES (?, ?, ?, ?, ?, ?)`,
1650
+ [params.name, "SmGeometry", 1001, 3, params.srid, 0]
1651
+ );
1652
+ if (fields.length > 0) {
1653
+ const fieldInfoRepository = new SmFieldInfoRepository(driver);
1654
+ await fieldInfoRepository.insertAll(datasetId, fields);
1655
+ }
1656
+ return new _PointZDataset(driver, {
1657
+ id: datasetId,
1658
+ name: params.name,
1659
+ kind: "pointZ",
1660
+ tableName: params.name,
1661
+ srid: params.srid,
1662
+ objectCount: 0,
1663
+ geometryType: 1001
1664
+ });
1665
+ }
1666
+ };
1667
+
1668
+ // src/core/geometry/gaia/GaiaPolygonCodec.ts
1669
+ var GAIA_ENTITY_MARK2 = 105;
1670
+ var GEO_TYPE_POLYGON = 3;
1671
+ var GEO_TYPE_POLYGONZ = 1003;
1672
+ function is3DCoordinates2(coordinates) {
1673
+ return coordinates[0]?.[0]?.[0]?.length === 3;
1674
+ }
1675
+ function createPolygonMbr(coordinates) {
1676
+ const xs = [];
1677
+ const ys = [];
1678
+ for (const polygon of coordinates) {
1679
+ for (const ring of polygon) {
1680
+ for (const point of ring) {
1681
+ xs.push(point[0]);
1682
+ ys.push(point[1]);
1683
+ }
1684
+ }
1685
+ }
1686
+ if (xs.length === 0) {
1687
+ throw new GaiaFormatError("MultiPolygon must contain at least one point.");
1688
+ }
1689
+ return [
1690
+ Math.min(...xs),
1691
+ Math.min(...ys),
1692
+ Math.max(...xs),
1693
+ Math.max(...ys)
1694
+ ];
1695
+ }
1696
+ function writeRing2D(writer2, ring) {
1697
+ writer2.writeInt32(ring.length, true);
1698
+ for (const point of ring) {
1699
+ writer2.writeFloat64(point[0], true);
1700
+ writer2.writeFloat64(point[1], true);
1701
+ }
1702
+ }
1703
+ function writeRing3D(writer2, ring) {
1704
+ writer2.writeInt32(ring.length, true);
1705
+ for (const point of ring) {
1706
+ writer2.writeFloat64(point[0], true);
1707
+ writer2.writeFloat64(point[1], true);
1708
+ writer2.writeFloat64(point[2], true);
1709
+ }
1710
+ }
1711
+ function readRing2D(cursor) {
1712
+ const pointCount = cursor.readInt32(true);
1713
+ const ring = [];
1714
+ for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
1715
+ ring.push([cursor.readFloat64(true), cursor.readFloat64(true)]);
1716
+ }
1717
+ return ring;
1718
+ }
1719
+ function readRing3D(cursor) {
1720
+ const pointCount = cursor.readInt32(true);
1721
+ const ring = [];
1722
+ for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
1723
+ ring.push([
1724
+ cursor.readFloat64(true),
1725
+ cursor.readFloat64(true),
1726
+ cursor.readFloat64(true)
1727
+ ]);
1728
+ }
1729
+ return ring;
1730
+ }
1731
+ var GaiaPolygonCodec = class {
1732
+ static readMultiPolygon(input) {
1733
+ const cursor = new BinaryCursor(input);
1734
+ const header = readGaiaHeader(cursor, GEO_TYPE_MULTIPOLYGON);
1735
+ const polygonCount = cursor.readInt32(true);
1736
+ const coordinates = [];
1737
+ for (let polygonIndex = 0; polygonIndex < polygonCount; polygonIndex += 1) {
1738
+ const entityMark = cursor.readUint8();
1739
+ if (entityMark !== GAIA_ENTITY_MARK2) {
1740
+ throw new GaiaFormatError(
1741
+ `Invalid Polygon entity mark: expected 0x${GAIA_ENTITY_MARK2.toString(16)}, got 0x${entityMark.toString(16)}.`
1742
+ );
1743
+ }
1744
+ const polygonGeoType = cursor.readInt32(true);
1745
+ if (polygonGeoType !== GEO_TYPE_POLYGON) {
1746
+ throw new GaiaFormatError(
1747
+ `Invalid Polygon geoType: expected ${GEO_TYPE_POLYGON}, got ${polygonGeoType}.`
1748
+ );
1749
+ }
1750
+ const ringCount = cursor.readInt32(true);
1751
+ if (ringCount < 1) {
1752
+ throw new GaiaFormatError(
1753
+ `Polygon must contain at least one ring, got ${ringCount}.`
1754
+ );
1755
+ }
1756
+ const polygon = [];
1757
+ for (let ringIndex = 0; ringIndex < ringCount; ringIndex += 1) {
1758
+ polygon.push(readRing2D(cursor));
1759
+ }
1760
+ coordinates.push(polygon);
1761
+ }
1762
+ validateGaiaEnd(cursor);
1763
+ return {
1764
+ type: "MultiPolygon",
1765
+ coordinates,
1766
+ srid: header.srid,
1767
+ bbox: header.mbr,
1768
+ hasZ: false,
1769
+ geoType: header.geoType
1770
+ };
1771
+ }
1772
+ static readMultiPolygonZ(input) {
1773
+ const cursor = new BinaryCursor(input);
1774
+ const header = readGaiaHeader(cursor, GEO_TYPE_MULTIPOLYGONZ);
1775
+ const polygonCount = cursor.readInt32(true);
1776
+ const coordinates = [];
1777
+ for (let polygonIndex = 0; polygonIndex < polygonCount; polygonIndex += 1) {
1778
+ const entityMark = cursor.readUint8();
1779
+ if (entityMark !== GAIA_ENTITY_MARK2) {
1780
+ throw new GaiaFormatError(
1781
+ `Invalid Polygon entity mark: expected 0x${GAIA_ENTITY_MARK2.toString(16)}, got 0x${entityMark.toString(16)}.`
1782
+ );
1783
+ }
1784
+ const polygonGeoType = cursor.readInt32(true);
1785
+ if (polygonGeoType !== GEO_TYPE_POLYGONZ) {
1786
+ throw new GaiaFormatError(
1787
+ `Invalid PolygonZ geoType: expected ${GEO_TYPE_POLYGONZ}, got ${polygonGeoType}.`
1788
+ );
1789
+ }
1790
+ const ringCount = cursor.readInt32(true);
1791
+ if (ringCount < 1) {
1792
+ throw new GaiaFormatError(
1793
+ `Polygon must contain at least one ring, got ${ringCount}.`
1794
+ );
1795
+ }
1796
+ const polygon = [];
1797
+ for (let ringIndex = 0; ringIndex < ringCount; ringIndex += 1) {
1798
+ polygon.push(readRing3D(cursor));
1799
+ }
1800
+ coordinates.push(polygon);
1801
+ }
1802
+ validateGaiaEnd(cursor);
1803
+ return {
1804
+ type: "MultiPolygon",
1805
+ coordinates,
1806
+ srid: header.srid,
1807
+ bbox: header.mbr,
1808
+ hasZ: true,
1809
+ geoType: header.geoType
1810
+ };
1811
+ }
1812
+ static writeMultiPolygon(geometry, srid) {
1813
+ if (is3DCoordinates2(geometry.coordinates)) {
1814
+ throw new GaiaFormatError("writeMultiPolygon expects 2D coordinates.");
1815
+ }
1816
+ const writer2 = new BinaryWriter();
1817
+ writeGaiaHeader(
1818
+ writer2,
1819
+ srid,
1820
+ createPolygonMbr(geometry.coordinates),
1821
+ GEO_TYPE_MULTIPOLYGON
1822
+ );
1823
+ writer2.writeInt32(geometry.coordinates.length, true);
1824
+ for (const polygon of geometry.coordinates) {
1825
+ writer2.writeUint8(GAIA_ENTITY_MARK2);
1826
+ writer2.writeInt32(GEO_TYPE_POLYGON, true);
1827
+ writer2.writeInt32(polygon.length, true);
1828
+ for (const ring of polygon) {
1829
+ writeRing2D(writer2, ring);
1830
+ }
1831
+ }
1832
+ writer2.writeUint8(GAIA_END);
1833
+ return writer2.toUint8Array();
1834
+ }
1835
+ static writeMultiPolygonZ(geometry, srid) {
1836
+ if (!is3DCoordinates2(geometry.coordinates)) {
1837
+ throw new GaiaFormatError("writeMultiPolygonZ expects 3D coordinates.");
1838
+ }
1839
+ const writer2 = new BinaryWriter();
1840
+ writeGaiaHeader(
1841
+ writer2,
1842
+ srid,
1843
+ createPolygonMbr(geometry.coordinates),
1844
+ GEO_TYPE_MULTIPOLYGONZ
1845
+ );
1846
+ writer2.writeInt32(geometry.coordinates.length, true);
1847
+ for (const polygon of geometry.coordinates) {
1848
+ writer2.writeUint8(GAIA_ENTITY_MARK2);
1849
+ writer2.writeInt32(GEO_TYPE_POLYGONZ, true);
1850
+ writer2.writeInt32(polygon.length, true);
1851
+ for (const ring of polygon) {
1852
+ writeRing3D(writer2, ring);
1853
+ }
1854
+ }
1855
+ writer2.writeUint8(GAIA_END);
1856
+ return writer2.toUint8Array();
1857
+ }
1858
+ };
1859
+
1860
+ // src/core/dataset/RegionDataset.ts
1861
+ function mapRegionRow(row) {
1862
+ const { SmID, SmGeometry, ...attributes } = row;
1863
+ return {
1864
+ id: SmID,
1865
+ geometry: GaiaPolygonCodec.readMultiPolygon(normalizeGeometryBlob(SmGeometry)),
1866
+ attributes
1867
+ };
1868
+ }
1869
+ var RegionDataset = class _RegionDataset extends BaseDataset {
1870
+ constructor(driver, info) {
1871
+ super(driver, info);
1872
+ __publicField(this, "registerRepository");
1873
+ this.registerRepository = new SmRegisterRepository(driver);
1874
+ }
1875
+ async getById(id) {
1876
+ const row = await queryOne(
1877
+ this.driver,
1878
+ `SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
1879
+ [id]
1880
+ );
1881
+ return row ? mapRegionRow(row) : null;
1882
+ }
1883
+ async list(options) {
1884
+ const { sql, params } = buildListSql(this.info.tableName, options);
1885
+ const rows = await queryAll(this.driver, sql, params);
1886
+ return rows.map((row) => mapRegionRow(row));
1887
+ }
1888
+ async *iterate(options) {
1889
+ const { sql, params } = buildListSql(this.info.tableName, options);
1890
+ const statement = await this.driver.prepare(sql);
1891
+ try {
1892
+ if (params.length > 0) {
1893
+ await statement.bind(params);
1894
+ }
1895
+ while (await statement.step()) {
1896
+ yield mapRegionRow(
1897
+ await statement.getRow()
1898
+ );
1899
+ }
1900
+ } finally {
1901
+ await statement.finalize();
1902
+ }
1903
+ }
1904
+ async insert(feature) {
1905
+ const userFields = await this.getFields();
1906
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
1907
+ const placeholders = columnNames.map(() => "?").join(", ");
1908
+ const geometry = GaiaPolygonCodec.writeMultiPolygon(
1909
+ feature.geometry,
1910
+ feature.geometry.srid ?? this.info.srid ?? 0
1911
+ );
1912
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
1913
+ const params = [
1914
+ feature.id,
1915
+ 0,
1916
+ geometry,
1917
+ ...userFields.map((field) => feature.attributes[field.name] ?? null)
1918
+ ];
1919
+ await this.driver.transaction(async () => {
1920
+ await executeSql(this.driver, sql, params);
1921
+ await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
1922
+ });
1923
+ }
1924
+ async insertMany(features) {
1925
+ const userFields = await this.getFields();
1926
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
1927
+ const placeholders = columnNames.map(() => "?").join(", ");
1928
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
1929
+ await this.driver.transaction(async () => {
1930
+ const statement = await this.driver.prepare(sql);
1931
+ try {
1932
+ let count = 0;
1933
+ let maxGeometrySize = 0;
1934
+ for await (const feature of features) {
1935
+ const geometry = GaiaPolygonCodec.writeMultiPolygon(
1936
+ feature.geometry,
1937
+ feature.geometry.srid ?? this.info.srid ?? 0
1938
+ );
1939
+ maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
1940
+ const params = [
1941
+ feature.id,
1942
+ 0,
1943
+ geometry,
1944
+ ...userFields.map(
1945
+ (field) => feature.attributes[field.name] ?? null
1946
+ )
1947
+ ];
1948
+ await statement.bind(params);
1949
+ await statement.step();
1950
+ await statement.reset();
1951
+ count++;
1952
+ }
1953
+ if (count > 0) {
1954
+ await this.registerRepository.incrementObjectCountBatch(
1955
+ this.info.id,
1956
+ count,
1957
+ maxGeometrySize
1958
+ );
1959
+ }
1960
+ } finally {
1961
+ await statement.finalize();
1962
+ }
1963
+ });
1964
+ }
1965
+ async count() {
1966
+ const row = await queryOne(
1967
+ this.driver,
1968
+ `SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
1969
+ []
1970
+ );
1971
+ return row?.count ?? 0;
1972
+ }
1973
+ async update(id, changes) {
1974
+ if (!changes.geometry && !changes.attributes) {
1975
+ return;
1976
+ }
1977
+ const setClauses = [];
1978
+ const params = [];
1979
+ if (changes.geometry) {
1980
+ const geometry = GaiaPolygonCodec.writeMultiPolygon(
1981
+ changes.geometry,
1982
+ changes.geometry.srid ?? this.info.srid ?? 0
1983
+ );
1984
+ setClauses.push('"SmGeometry" = ?');
1985
+ params.push(geometry);
1986
+ }
1987
+ if (changes.attributes) {
1988
+ const userFields = await this.getFields();
1989
+ const fieldNames = new Set(userFields.map((f) => f.name));
1990
+ const validEntries = Object.entries(changes.attributes).filter(
1991
+ ([key]) => fieldNames.has(key)
1992
+ );
1993
+ for (const [key, value] of validEntries) {
1994
+ setClauses.push(`"${key}" = ?`);
1995
+ params.push(value);
1996
+ }
1997
+ }
1998
+ if (setClauses.length === 0) {
1999
+ return;
2000
+ }
2001
+ const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
2002
+ params.push(id);
2003
+ await this.driver.transaction(async () => {
2004
+ await executeSql(this.driver, sql, params);
2005
+ });
2006
+ }
2007
+ async delete(id) {
2008
+ await this.driver.transaction(async () => {
2009
+ await executeSql(
2010
+ this.driver,
2011
+ `DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
2012
+ [id]
2013
+ );
2014
+ await this.registerRepository.decrementObjectCount(this.info.id);
2015
+ });
2016
+ }
2017
+ static async create(driver, registerRepository, params) {
2018
+ const fields = params.fields ?? [];
2019
+ const datasetId = await registerRepository.insert({
2020
+ name: params.name,
2021
+ kind: "region",
2022
+ srid: params.srid,
2023
+ idColumnName: "SmID",
2024
+ geometryColumnName: "SmGeometry"
2025
+ });
2026
+ const userColumnDefinitions = fields.map((field) => {
2027
+ const nullability = field.nullable ? "" : " NOT NULL";
2028
+ return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
2029
+ });
2030
+ const createTableParts = [
2031
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
2032
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
2033
+ `"SmGeometry" BLOB NOT NULL`,
2034
+ ...userColumnDefinitions
2035
+ ];
2036
+ await driver.exec(
2037
+ `CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
2038
+ );
2039
+ await executeSql(
2040
+ driver,
2041
+ `INSERT INTO geometry_columns (
2042
+ f_table_name,
2043
+ f_geometry_column,
2044
+ geometry_type,
2045
+ coord_dimension,
2046
+ srid,
2047
+ spatial_index_enabled
2048
+ ) VALUES (?, ?, ?, ?, ?, ?)`,
2049
+ [params.name, "SmGeometry", 6, 2, params.srid, 0]
2050
+ );
2051
+ if (fields.length > 0) {
2052
+ const fieldInfoRepository = new SmFieldInfoRepository(driver);
2053
+ await fieldInfoRepository.insertAll(datasetId, fields);
2054
+ }
2055
+ return new _RegionDataset(driver, {
2056
+ id: datasetId,
2057
+ name: params.name,
2058
+ kind: "region",
2059
+ tableName: params.name,
2060
+ srid: params.srid,
2061
+ objectCount: 0,
2062
+ geometryType: 6
2063
+ });
2064
+ }
2065
+ };
2066
+
2067
+ // src/core/dataset/RegionZDataset.ts
2068
+ function mapRegionZRow(row) {
2069
+ const { SmID, SmGeometry, ...attributes } = row;
2070
+ return {
2071
+ id: SmID,
2072
+ geometry: GaiaPolygonCodec.readMultiPolygonZ(normalizeGeometryBlob(SmGeometry)),
2073
+ attributes
2074
+ };
2075
+ }
2076
+ var RegionZDataset = class _RegionZDataset extends BaseDataset {
2077
+ constructor(driver, info) {
2078
+ super(driver, info);
2079
+ __publicField(this, "registerRepository");
2080
+ this.registerRepository = new SmRegisterRepository(driver);
2081
+ }
2082
+ async getById(id) {
2083
+ const row = await queryOne(
2084
+ this.driver,
2085
+ `SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
2086
+ [id]
2087
+ );
2088
+ return row ? mapRegionZRow(row) : null;
2089
+ }
2090
+ async list(options) {
2091
+ const { sql, params } = buildListSql(this.info.tableName, options);
2092
+ const rows = await queryAll(this.driver, sql, params);
2093
+ return rows.map((row) => mapRegionZRow(row));
2094
+ }
2095
+ async *iterate(options) {
2096
+ const { sql, params } = buildListSql(this.info.tableName, options);
2097
+ const statement = await this.driver.prepare(sql);
2098
+ try {
2099
+ if (params.length > 0) {
2100
+ await statement.bind(params);
2101
+ }
2102
+ while (await statement.step()) {
2103
+ yield mapRegionZRow(
2104
+ await statement.getRow()
2105
+ );
2106
+ }
2107
+ } finally {
2108
+ await statement.finalize();
2109
+ }
2110
+ }
2111
+ async count() {
2112
+ const row = await queryOne(
2113
+ this.driver,
2114
+ `SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
2115
+ []
2116
+ );
2117
+ return row?.count ?? 0;
2118
+ }
2119
+ async insert(feature) {
2120
+ const userFields = await this.getFields();
2121
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
2122
+ const placeholders = columnNames.map(() => "?").join(", ");
2123
+ const geometry = GaiaPolygonCodec.writeMultiPolygonZ(
2124
+ feature.geometry,
2125
+ feature.geometry.srid ?? this.info.srid ?? 0
2126
+ );
2127
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
2128
+ const params = [
2129
+ feature.id,
2130
+ 0,
2131
+ geometry,
2132
+ ...userFields.map((field) => feature.attributes[field.name] ?? null)
2133
+ ];
2134
+ await this.driver.transaction(async () => {
2135
+ await executeSql(this.driver, sql, params);
2136
+ await this.registerRepository.incrementObjectCount(this.info.id, geometry.byteLength);
2137
+ });
2138
+ }
2139
+ async insertMany(features) {
2140
+ const userFields = await this.getFields();
2141
+ const columnNames = ["SmID", "SmUserID", "SmGeometry", ...userFields.map((field) => field.name)];
2142
+ const placeholders = columnNames.map(() => "?").join(", ");
2143
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
2144
+ await this.driver.transaction(async () => {
2145
+ const statement = await this.driver.prepare(sql);
2146
+ try {
2147
+ let count = 0;
2148
+ let maxGeometrySize = 0;
2149
+ for await (const feature of features) {
2150
+ const geometry = GaiaPolygonCodec.writeMultiPolygonZ(
2151
+ feature.geometry,
2152
+ feature.geometry.srid ?? this.info.srid ?? 0
2153
+ );
2154
+ maxGeometrySize = Math.max(maxGeometrySize, geometry.byteLength);
2155
+ const params = [
2156
+ feature.id,
2157
+ 0,
2158
+ geometry,
2159
+ ...userFields.map(
2160
+ (field) => feature.attributes[field.name] ?? null
2161
+ )
2162
+ ];
2163
+ await statement.bind(params);
2164
+ await statement.step();
2165
+ await statement.reset();
2166
+ count++;
2167
+ }
2168
+ if (count > 0) {
2169
+ await this.registerRepository.incrementObjectCountBatch(
2170
+ this.info.id,
2171
+ count,
2172
+ maxGeometrySize
2173
+ );
2174
+ }
2175
+ } finally {
2176
+ await statement.finalize();
2177
+ }
2178
+ });
2179
+ }
2180
+ async update(id, changes) {
2181
+ if (!changes.geometry && !changes.attributes) {
2182
+ return;
2183
+ }
2184
+ const setClauses = [];
2185
+ const params = [];
2186
+ if (changes.geometry) {
2187
+ const geometry = GaiaPolygonCodec.writeMultiPolygonZ(
2188
+ changes.geometry,
2189
+ changes.geometry.srid ?? this.info.srid ?? 0
2190
+ );
2191
+ setClauses.push('"SmGeometry" = ?');
2192
+ params.push(geometry);
2193
+ }
2194
+ if (changes.attributes) {
2195
+ const userFields = await this.getFields();
2196
+ const fieldNames = new Set(userFields.map((f) => f.name));
2197
+ const validEntries = Object.entries(changes.attributes).filter(
2198
+ ([key]) => fieldNames.has(key)
2199
+ );
2200
+ for (const [key, value] of validEntries) {
2201
+ setClauses.push(`"${key}" = ?`);
2202
+ params.push(value);
2203
+ }
2204
+ }
2205
+ if (setClauses.length === 0) {
2206
+ return;
2207
+ }
2208
+ const sql = `UPDATE "${this.info.tableName}" SET ${setClauses.join(", ")} WHERE SmID = ?`;
2209
+ params.push(id);
2210
+ await this.driver.transaction(async () => {
2211
+ await executeSql(this.driver, sql, params);
2212
+ });
2213
+ }
2214
+ async delete(id) {
2215
+ await this.driver.transaction(async () => {
2216
+ await executeSql(
2217
+ this.driver,
2218
+ `DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
2219
+ [id]
2220
+ );
2221
+ await this.registerRepository.decrementObjectCount(this.info.id);
2222
+ });
2223
+ }
2224
+ static async create(driver, registerRepository, params) {
2225
+ const fields = params.fields ?? [];
2226
+ const datasetId = await registerRepository.insert({
2227
+ name: params.name,
2228
+ kind: "regionZ",
2229
+ srid: params.srid,
2230
+ idColumnName: "SmID",
2231
+ geometryColumnName: "SmGeometry"
2232
+ });
2233
+ const userColumnDefinitions = fields.map((field) => {
2234
+ const nullability = field.nullable ? "" : " NOT NULL";
2235
+ return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
2236
+ });
2237
+ const createTableParts = [
2238
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
2239
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
2240
+ `"SmGeometry" BLOB NOT NULL`,
2241
+ ...userColumnDefinitions
2242
+ ];
2243
+ await driver.exec(
2244
+ `CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
2245
+ );
2246
+ await executeSql(
2247
+ driver,
2248
+ `INSERT INTO geometry_columns (
2249
+ f_table_name,
2250
+ f_geometry_column,
2251
+ geometry_type,
2252
+ coord_dimension,
2253
+ srid,
2254
+ spatial_index_enabled
2255
+ ) VALUES (?, ?, ?, ?, ?, ?)`,
2256
+ [params.name, "SmGeometry", 1006, 3, params.srid, 0]
2257
+ );
2258
+ if (fields.length > 0) {
2259
+ const fieldInfoRepository = new SmFieldInfoRepository(driver);
2260
+ await fieldInfoRepository.insertAll(datasetId, fields);
2261
+ }
2262
+ return new _RegionZDataset(driver, {
2263
+ id: datasetId,
2264
+ name: params.name,
2265
+ kind: "regionZ",
2266
+ tableName: params.name,
2267
+ srid: params.srid,
2268
+ objectCount: 0,
2269
+ geometryType: 1006
2270
+ });
2271
+ }
2272
+ };
2273
+
2274
+ // src/core/dataset/TabularDataset.ts
2275
+ var SYSTEM_COLUMN_PREFIX = "Sm";
2276
+ function mapTabularRow(row) {
2277
+ const { SmID, ...rest } = row;
2278
+ const attributes = {};
2279
+ for (const [key, value] of Object.entries(rest)) {
2280
+ if (!key.startsWith(SYSTEM_COLUMN_PREFIX)) {
2281
+ attributes[key] = value;
2282
+ }
2283
+ }
2284
+ return {
2285
+ id: SmID,
2286
+ attributes
2287
+ };
2288
+ }
2289
+ var TabularDataset = class _TabularDataset extends BaseDataset {
2290
+ constructor(driver, info) {
2291
+ super(driver, info);
2292
+ __publicField(this, "registerRepository");
2293
+ this.registerRepository = new SmRegisterRepository(driver);
2294
+ }
2295
+ async getById(id) {
2296
+ const row = await queryOne(
2297
+ this.driver,
2298
+ `SELECT * FROM "${this.info.tableName}" WHERE SmID = ?`,
2299
+ [id]
2300
+ );
2301
+ return row ? mapTabularRow(row) : null;
2302
+ }
2303
+ async list(options) {
2304
+ const { sql, params } = buildListSql(this.info.tableName, options);
2305
+ const rows = await queryAll(this.driver, sql, params);
2306
+ return rows.map((row) => mapTabularRow(row));
2307
+ }
2308
+ async *iterate(options) {
2309
+ const { sql, params } = buildListSql(this.info.tableName, options);
2310
+ const statement = await this.driver.prepare(sql);
2311
+ try {
2312
+ if (params.length > 0) {
2313
+ await statement.bind(params);
2314
+ }
2315
+ while (await statement.step()) {
2316
+ yield mapTabularRow(
2317
+ await statement.getRow()
2318
+ );
2319
+ }
2320
+ } finally {
2321
+ await statement.finalize();
2322
+ }
2323
+ }
2324
+ async count() {
2325
+ const row = await queryOne(
2326
+ this.driver,
2327
+ `SELECT COUNT(*) AS count FROM "${this.info.tableName}"`,
2328
+ []
2329
+ );
2330
+ return row?.count ?? 0;
2331
+ }
2332
+ async insert(record) {
2333
+ const userFields = await this.getFields();
2334
+ const columnNames = [
2335
+ "SmID",
2336
+ "SmUserID",
2337
+ ...userFields.map((field) => field.name)
2338
+ ];
2339
+ const placeholders = columnNames.map(() => "?").join(", ");
2340
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
2341
+ const params = [
2342
+ record.id,
2343
+ 0,
2344
+ ...userFields.map(
2345
+ (field) => record.attributes[field.name] ?? null
2346
+ )
2347
+ ];
2348
+ await this.driver.transaction(async () => {
2349
+ await executeSql(this.driver, sql, params);
2350
+ await this.registerRepository.incrementObjectCount(this.info.id);
2351
+ });
2352
+ }
2353
+ async insertMany(records) {
2354
+ const userFields = await this.getFields();
2355
+ const columnNames = [
2356
+ "SmID",
2357
+ "SmUserID",
2358
+ ...userFields.map((field) => field.name)
2359
+ ];
2360
+ const placeholders = columnNames.map(() => "?").join(", ");
2361
+ const sql = `INSERT INTO "${this.info.tableName}" (${columnNames.map((column) => `"${column}"`).join(", ")}) VALUES (${placeholders})`;
2362
+ await this.driver.transaction(async () => {
2363
+ const statement = await this.driver.prepare(sql);
2364
+ try {
2365
+ let count = 0;
2366
+ for await (const record of records) {
2367
+ const params = [
2368
+ record.id,
2369
+ 0,
2370
+ ...userFields.map(
2371
+ (field) => record.attributes[field.name] ?? null
2372
+ )
2373
+ ];
2374
+ await statement.bind(params);
2375
+ await statement.step();
2376
+ await statement.reset();
2377
+ count++;
2378
+ }
2379
+ if (count > 0) {
2380
+ await this.registerRepository.incrementObjectCountBatch(
2381
+ this.info.id,
2382
+ count,
2383
+ 0
2384
+ );
2385
+ }
2386
+ } finally {
2387
+ await statement.finalize();
2388
+ }
2389
+ });
2390
+ }
2391
+ async update(id, attributes) {
2392
+ const userFields = await this.getFields();
2393
+ const fieldNames = new Set(userFields.map((f) => f.name));
2394
+ const validEntries = Object.entries(attributes).filter(
2395
+ ([key]) => fieldNames.has(key)
2396
+ );
2397
+ if (validEntries.length === 0) return;
2398
+ const keys = validEntries.map(([key]) => key);
2399
+ const setClauses = keys.map((key) => `"${key}" = ?`).join(", ");
2400
+ const sql = `UPDATE "${this.info.tableName}" SET ${setClauses} WHERE SmID = ?`;
2401
+ const params = [
2402
+ ...keys.map((key) => attributes[key]),
2403
+ id
2404
+ ];
2405
+ await this.driver.transaction(async () => {
2406
+ await executeSql(this.driver, sql, params);
2407
+ });
2408
+ }
2409
+ async delete(id) {
2410
+ await this.driver.transaction(async () => {
2411
+ await executeSql(
2412
+ this.driver,
2413
+ `DELETE FROM "${this.info.tableName}" WHERE SmID = ?`,
2414
+ [id]
2415
+ );
2416
+ await this.registerRepository.decrementObjectCount(this.info.id);
2417
+ });
2418
+ }
2419
+ static async create(driver, registerRepository, params) {
2420
+ const fields = params.fields ?? [];
2421
+ const datasetId = await registerRepository.insert({
2422
+ name: params.name,
2423
+ kind: "tabular",
2424
+ srid: 0,
2425
+ idColumnName: "SmID",
2426
+ geometryColumnName: null
2427
+ });
2428
+ const userColumnDefinitions = fields.map((field) => {
2429
+ const nullability = field.nullable ? "" : " NOT NULL";
2430
+ return `"${field.name}" ${sqliteColumnType(field)}${nullability}`;
2431
+ });
2432
+ const createTableParts = [
2433
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
2434
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
2435
+ ...userColumnDefinitions
2436
+ ];
2437
+ await driver.exec(
2438
+ `CREATE TABLE "${params.name}" (${createTableParts.join(", ")})`
2439
+ );
2440
+ if (fields.length > 0) {
2441
+ const fieldInfoRepository = new SmFieldInfoRepository(driver);
2442
+ await fieldInfoRepository.insertAll(datasetId, fields);
2443
+ }
2444
+ return new _TabularDataset(driver, {
2445
+ id: datasetId,
2446
+ name: params.name,
2447
+ kind: "tabular",
2448
+ tableName: params.name,
2449
+ srid: 0,
2450
+ objectCount: 0,
2451
+ geometryType: null
2452
+ });
2453
+ }
2454
+ };
2455
+
2456
+ // src/core/dataset/TextDataset.ts
2457
+ var TextDataset = class extends BaseDataset {
2458
+ async getById() {
2459
+ throw createNotImplementedError("TextDataset.getById");
2460
+ }
2461
+ async list(_options) {
2462
+ throw createNotImplementedError("TextDataset.list");
2463
+ }
2464
+ async *iterate(_options) {
2465
+ throw createNotImplementedError("TextDataset.iterate");
2466
+ }
2467
+ async count() {
2468
+ throw createNotImplementedError("TextDataset.count");
2469
+ }
2470
+ async insert() {
2471
+ throw createNotImplementedError("TextDataset.insert");
2472
+ }
2473
+ async insertMany() {
2474
+ throw createNotImplementedError("TextDataset.insertMany");
2475
+ }
2476
+ async update() {
2477
+ throw createNotImplementedError("TextDataset.update");
2478
+ }
2479
+ async delete() {
2480
+ throw createNotImplementedError("TextDataset.delete");
2481
+ }
2482
+ };
2483
+
2484
+ // src/core/schema/UdbxSchemaInitializer.ts
2485
+ var UDBX_SYSTEM_TABLES = [
2486
+ "spatial_ref_sys",
2487
+ "geometry_columns",
2488
+ "SmDataSourceInfo",
2489
+ "SmRegister",
2490
+ "SmFieldInfo"
2491
+ ];
2492
+ var UDBX_SCHEMA_STATEMENTS = [
2493
+ `CREATE TABLE spatial_ref_sys (
2494
+ srid INTEGER NOT NULL PRIMARY KEY,
2495
+ auth_name TEXT NOT NULL,
2496
+ auth_srid INTEGER NOT NULL,
2497
+ ref_sys_name TEXT NOT NULL DEFAULT 'Unknown',
2498
+ proj4text TEXT NOT NULL,
2499
+ srtext TEXT NOT NULL DEFAULT 'Undefined'
2500
+ )`,
2501
+ `CREATE TABLE geometry_columns (
2502
+ f_table_name TEXT NOT NULL,
2503
+ f_geometry_column TEXT NOT NULL,
2504
+ geometry_type INTEGER NOT NULL,
2505
+ coord_dimension INTEGER NOT NULL,
2506
+ srid INTEGER NOT NULL,
2507
+ spatial_index_enabled INTEGER NOT NULL,
2508
+ CONSTRAINT pk_geom_cols PRIMARY KEY (f_table_name, f_geometry_column)
2509
+ )`,
2510
+ `CREATE TABLE SmDataSourceInfo (
2511
+ SmFlag INTEGER DEFAULT 0 NOT NULL PRIMARY KEY AUTOINCREMENT,
2512
+ SmVersion INTEGER,
2513
+ SmDsDescription TEXT,
2514
+ SmProjectInfo BLOB,
2515
+ SmLastUpdateTime DATE DEFAULT CURRENT_TIMESTAMP NOT NULL,
2516
+ SmDataFormat INTEGER DEFAULT 0 NOT NULL
2517
+ )`,
2518
+ `CREATE TABLE SmRegister (
2519
+ SmDatasetID INTEGER DEFAULT 0 NOT NULL PRIMARY KEY,
2520
+ SmDatasetName TEXT,
2521
+ SmTableName TEXT,
2522
+ SmOption INTEGER,
2523
+ SmEncType INTEGER,
2524
+ SmParentDTID INTEGER DEFAULT 0 NOT NULL,
2525
+ SmDatasetType INTEGER,
2526
+ SmObjectCount INTEGER DEFAULT 0 NOT NULL,
2527
+ SmLeft REAL,
2528
+ SmRight REAL,
2529
+ SmTop REAL,
2530
+ SmBottom REAL,
2531
+ SmIDColName TEXT,
2532
+ SmGeoColName TEXT,
2533
+ SmMinZ REAL,
2534
+ SmMaxZ REAL,
2535
+ SmSRID INTEGER DEFAULT 0,
2536
+ SmIndexType INTEGER DEFAULT 1,
2537
+ SmToleRanceFuzzy REAL,
2538
+ SmToleranceDAngle REAL,
2539
+ SmToleranceNodeSnap REAL,
2540
+ SmToleranceSmallPolygon REAL,
2541
+ SmToleranceGrain REAL,
2542
+ SmMaxGeometrySize INTEGER DEFAULT 0 NOT NULL,
2543
+ SmOptimizeCount INTEGER DEFAULT 0 NOT NULL,
2544
+ SmOptimizeRatio REAL,
2545
+ SmDescription TEXT,
2546
+ SmExtInfo TEXT,
2547
+ SmCreateTime TEXT,
2548
+ SmLastUpdateTime TEXT,
2549
+ SmProjectInfo BLOB
2550
+ )`,
2551
+ `CREATE TABLE SmFieldInfo (
2552
+ SmID INTEGER DEFAULT 0 NOT NULL PRIMARY KEY AUTOINCREMENT,
2553
+ SmDatasetID INTEGER,
2554
+ SmFieldName TEXT,
2555
+ SmFieldCaption TEXT,
2556
+ SmFieldType INTEGER,
2557
+ SmFieldFormat TEXT,
2558
+ SmFieldSign INTEGER,
2559
+ SmFieldDomain TEXT,
2560
+ SmFieldUpdatable INTEGER,
2561
+ SmFieldbRequired INTEGER,
2562
+ SmFieldDefaultValue TEXT,
2563
+ SmFieldSize INTEGER
2564
+ )`,
2565
+ "INSERT INTO SmDataSourceInfo (SmVersion, SmDataFormat) VALUES (0, 1)",
2566
+ "INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, ref_sys_name, proj4text, srtext) VALUES (0, 'none', 0, 'Undefined', '', 'Undefined')",
2567
+ `INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, ref_sys_name, proj4text, srtext)
2568
+ VALUES (
2569
+ 4326,
2570
+ 'epsg',
2571
+ 4326,
2572
+ 'WGS 84',
2573
+ '+proj=longlat +datum=WGS84 +no_defs',
2574
+ 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4326"]]'
2575
+ )`
2576
+ ];
2577
+ var UdbxSchemaInitializer = class {
2578
+ static async isInitialized(driver) {
2579
+ const statement = await driver.prepare(
2580
+ "SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1"
2581
+ );
2582
+ try {
2583
+ await statement.bind(["SmDataSourceInfo"]);
2584
+ return statement.step();
2585
+ } finally {
2586
+ await statement.finalize();
2587
+ }
2588
+ }
2589
+ static async ensureInitialized(driver) {
2590
+ const initialized = await this.isInitialized(driver);
2591
+ if (initialized) {
2592
+ return false;
2593
+ }
2594
+ await this.initialize(driver);
2595
+ return true;
2596
+ }
2597
+ static async initialize(driver) {
2598
+ await driver.exec("PRAGMA journal_mode = WAL");
2599
+ await driver.transaction(async () => {
2600
+ for (const statement of UDBX_SCHEMA_STATEMENTS) {
2601
+ await driver.exec(statement);
2602
+ }
2603
+ });
2604
+ }
2605
+ };
2606
+
2607
+ // src/core/datasource/UdbxDataSource.ts
2608
+ var UdbxDataSource = class _UdbxDataSource {
2609
+ constructor(driver, runtime = "unknown") {
2610
+ this.driver = driver;
2611
+ this.runtime = runtime;
2612
+ __publicField(this, "registerRepository");
2613
+ this.registerRepository = new SmRegisterRepository(driver);
2614
+ }
2615
+ static async open(params) {
2616
+ await params.driver.open(params.target);
2617
+ return new _UdbxDataSource(params.driver, params.runtime ?? "unknown");
2618
+ }
2619
+ static async create(params) {
2620
+ await params.driver.open(params.target);
2621
+ await UdbxSchemaInitializer.initialize(params.driver);
2622
+ return new _UdbxDataSource(params.driver, params.runtime ?? "unknown");
2623
+ }
2624
+ async listDatasets() {
2625
+ return this.registerRepository.findAll();
2626
+ }
2627
+ async getDataset(name) {
2628
+ const info = await this.registerRepository.findByName(name);
2629
+ if (!info) {
2630
+ return null;
2631
+ }
2632
+ switch (info.kind) {
2633
+ case "point":
2634
+ return new PointDataset(this.driver, info);
2635
+ case "pointZ":
2636
+ return new PointZDataset(this.driver, info);
2637
+ case "line":
2638
+ return new LineDataset(this.driver, info);
2639
+ case "lineZ":
2640
+ return new LineZDataset(this.driver, info);
2641
+ case "region":
2642
+ return new RegionDataset(this.driver, info);
2643
+ case "regionZ":
2644
+ return new RegionZDataset(this.driver, info);
2645
+ case "tabular":
2646
+ return new TabularDataset(this.driver, info);
2647
+ case "text":
2648
+ return new TextDataset(this.driver, info);
2649
+ case "cad":
2650
+ return new CadDataset(this.driver, info);
2651
+ default:
2652
+ return null;
2653
+ }
2654
+ }
2655
+ async createPointDataset(name, srid, fields) {
2656
+ return this.driver.transaction(async () => {
2657
+ const params = fields === void 0 ? { name, srid } : { name, srid, fields };
2658
+ return PointDataset.create(this.driver, this.registerRepository, params);
2659
+ });
2660
+ }
2661
+ async createLineDataset(name, srid, fields) {
2662
+ return this.driver.transaction(async () => {
2663
+ const params = fields === void 0 ? { name, srid } : { name, srid, fields };
2664
+ return LineDataset.create(this.driver, this.registerRepository, params);
2665
+ });
2666
+ }
2667
+ async createRegionDataset(name, srid, fields) {
2668
+ return this.driver.transaction(async () => {
2669
+ const params = fields === void 0 ? { name, srid } : { name, srid, fields };
2670
+ return RegionDataset.create(this.driver, this.registerRepository, params);
2671
+ });
2672
+ }
2673
+ async createPointZDataset(name, srid, fields) {
2674
+ return this.driver.transaction(async () => {
2675
+ const params = fields === void 0 ? { name, srid } : { name, srid, fields };
2676
+ return PointZDataset.create(this.driver, this.registerRepository, params);
2677
+ });
2678
+ }
2679
+ async createLineZDataset(name, srid, fields) {
2680
+ return this.driver.transaction(async () => {
2681
+ const params = fields === void 0 ? { name, srid } : { name, srid, fields };
2682
+ return LineZDataset.create(this.driver, this.registerRepository, params);
2683
+ });
2684
+ }
2685
+ async createRegionZDataset(name, srid, fields) {
2686
+ return this.driver.transaction(async () => {
2687
+ const params = fields === void 0 ? { name, srid } : { name, srid, fields };
2688
+ return RegionZDataset.create(this.driver, this.registerRepository, params);
2689
+ });
2690
+ }
2691
+ async createTabularDataset(name, fields) {
2692
+ return this.driver.transaction(async () => {
2693
+ const params = fields === void 0 ? { name } : { name, fields };
2694
+ return TabularDataset.create(this.driver, this.registerRepository, params);
2695
+ });
2696
+ }
2697
+ async createTextDataset(name, srid, fields) {
2698
+ return this.driver.transaction(async () => {
2699
+ const fieldList = fields ?? [];
2700
+ const datasetId = await this.registerRepository.insert({
2701
+ name,
2702
+ kind: "text",
2703
+ srid,
2704
+ idColumnName: "SmID",
2705
+ geometryColumnName: "SmGeometry"
2706
+ });
2707
+ const userColumnDefinitions = fieldList.map((field) => {
2708
+ const nullability = field.nullable ? "" : " NOT NULL";
2709
+ return `"${field.name}" TEXT${nullability}`;
2710
+ });
2711
+ const createTableParts = [
2712
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
2713
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
2714
+ `"SmGeometry" BLOB`,
2715
+ `"SmIndexKey" POLYGON`,
2716
+ ...userColumnDefinitions
2717
+ ];
2718
+ await this.driver.exec(
2719
+ `CREATE TABLE "${name}" (${createTableParts.join(", ")})`
2720
+ );
2721
+ if (fieldList.length > 0) {
2722
+ const fieldInfoRepository = new SmFieldInfoRepository(this.driver);
2723
+ await fieldInfoRepository.insertAll(datasetId, fieldList);
2724
+ }
2725
+ return new TextDataset(this.driver, {
2726
+ id: datasetId,
2727
+ name,
2728
+ kind: "text",
2729
+ tableName: name,
2730
+ srid,
2731
+ objectCount: 0,
2732
+ geometryType: null
2733
+ });
2734
+ });
2735
+ }
2736
+ async createCadDataset(name, fields) {
2737
+ return this.driver.transaction(async () => {
2738
+ const fieldList = fields ?? [];
2739
+ const datasetId = await this.registerRepository.insert({
2740
+ name,
2741
+ kind: "cad",
2742
+ srid: 0,
2743
+ idColumnName: "SmID",
2744
+ geometryColumnName: "SmGeometry"
2745
+ });
2746
+ const userColumnDefinitions = fieldList.map((field) => {
2747
+ const nullability = field.nullable ? "" : " NOT NULL";
2748
+ return `"${field.name}" TEXT${nullability}`;
2749
+ });
2750
+ const createTableParts = [
2751
+ `"SmID" INTEGER NOT NULL PRIMARY KEY`,
2752
+ `"SmUserID" INTEGER DEFAULT 0 NOT NULL`,
2753
+ `"SmGeometry" BLOB`,
2754
+ ...userColumnDefinitions
2755
+ ];
2756
+ await this.driver.exec(
2757
+ `CREATE TABLE "${name}" (${createTableParts.join(", ")})`
2758
+ );
2759
+ if (fieldList.length > 0) {
2760
+ const fieldInfoRepository = new SmFieldInfoRepository(this.driver);
2761
+ await fieldInfoRepository.insertAll(datasetId, fieldList);
2762
+ }
2763
+ return new CadDataset(this.driver, {
2764
+ id: datasetId,
2765
+ name,
2766
+ kind: "cad",
2767
+ tableName: name,
2768
+ srid: 0,
2769
+ objectCount: 0,
2770
+ geometryType: null
2771
+ });
2772
+ });
2773
+ }
2774
+ async close() {
2775
+ await this.driver.close();
2776
+ }
2777
+ };
2778
+
2779
+ // src/core/errors.ts
2780
+ var UdbxError = class extends Error {
2781
+ constructor(message) {
2782
+ super(message);
2783
+ this.name = "UdbxError";
2784
+ }
2785
+ };
2786
+ var UdbxFormatError = class extends UdbxError {
2787
+ constructor(message) {
2788
+ super(message);
2789
+ this.name = "UdbxFormatError";
2790
+ }
2791
+ };
2792
+ var UdbxNotFoundError = class extends UdbxError {
2793
+ constructor(what, id) {
2794
+ super(id !== void 0 ? `${what} not found (id=${id})` : `${what} not found`);
2795
+ this.name = "UdbxNotFoundError";
2796
+ }
2797
+ };
2798
+ var UdbxUnsupportedError = class extends UdbxError {
2799
+ constructor(what) {
2800
+ super(`Unsupported: ${what}`);
2801
+ this.name = "UdbxUnsupportedError";
2802
+ }
2803
+ };
2804
+ var UdbxConstraintError = class extends UdbxError {
2805
+ constructor(what) {
2806
+ super(`Constraint violation: ${what}`);
2807
+ this.name = "UdbxConstraintError";
2808
+ }
2809
+ };
2810
+ var UdbxIOError = class extends UdbxError {
2811
+ constructor(cause) {
2812
+ super(cause ? `IO error: ${cause.message}` : "IO error");
2813
+ this.name = "UdbxIOError";
2814
+ }
2815
+ };
2816
+
2817
+ // src/core/geometry/gaia/GaiaGeometryCodec.ts
2818
+ var decodeByGeoType = /* @__PURE__ */ new Map([
2819
+ [GEO_TYPE_POINT, GaiaPointCodec.readPoint],
2820
+ [GEO_TYPE_POINTZ, GaiaPointCodec.readPointZ],
2821
+ [GEO_TYPE_MULTILINESTRING, GaiaLineCodec.readMultiLineString],
2822
+ [GEO_TYPE_MULTILINESTRINGZ, GaiaLineCodec.readMultiLineStringZ],
2823
+ [GEO_TYPE_MULTIPOLYGON, GaiaPolygonCodec.readMultiPolygon],
2824
+ [GEO_TYPE_MULTIPOLYGONZ, GaiaPolygonCodec.readMultiPolygonZ]
2825
+ ]);
2826
+ var pointCodecs = {
2827
+ [GEO_TYPE_POINT]: {
2828
+ geoType: GEO_TYPE_POINT,
2829
+ decode: GaiaPointCodec.readPoint
2830
+ },
2831
+ [GEO_TYPE_POINTZ]: {
2832
+ geoType: GEO_TYPE_POINTZ,
2833
+ decode: GaiaPointCodec.readPointZ
2834
+ }
2835
+ };
2836
+ var lineCodecs = {
2837
+ [GEO_TYPE_MULTILINESTRING]: {
2838
+ geoType: GEO_TYPE_MULTILINESTRING,
2839
+ decode: GaiaLineCodec.readMultiLineString
2840
+ },
2841
+ [GEO_TYPE_MULTILINESTRINGZ]: {
2842
+ geoType: GEO_TYPE_MULTILINESTRINGZ,
2843
+ decode: GaiaLineCodec.readMultiLineStringZ
2844
+ }
2845
+ };
2846
+ var polygonCodecs = {
2847
+ [GEO_TYPE_MULTIPOLYGON]: {
2848
+ geoType: GEO_TYPE_MULTIPOLYGON,
2849
+ decode: GaiaPolygonCodec.readMultiPolygon
2850
+ },
2851
+ [GEO_TYPE_MULTIPOLYGONZ]: {
2852
+ geoType: GEO_TYPE_MULTIPOLYGONZ,
2853
+ decode: GaiaPolygonCodec.readMultiPolygonZ
2854
+ }
2855
+ };
2856
+ function geometryHasZ(geometry) {
2857
+ switch (geometry.type) {
2858
+ case "Point":
2859
+ return geometry.coordinates.length === 3;
2860
+ case "MultiLineString":
2861
+ return geometry.coordinates[0]?.[0]?.length === 3;
2862
+ case "MultiPolygon":
2863
+ return geometry.coordinates[0]?.[0]?.[0]?.length === 3;
2864
+ case "Cad":
2865
+ case "Text":
2866
+ return false;
2867
+ default:
2868
+ return false;
2869
+ }
2870
+ }
2871
+ function encodeGeometry(geometry, srid) {
2872
+ switch (geometry.type) {
2873
+ case "Point":
2874
+ return geometryHasZ(geometry) ? GaiaPointCodec.writePointZ(geometry, srid) : GaiaPointCodec.writePoint(geometry, srid);
2875
+ case "MultiLineString":
2876
+ return geometryHasZ(geometry) ? GaiaLineCodec.writeMultiLineStringZ(geometry, srid) : GaiaLineCodec.writeMultiLineString(geometry, srid);
2877
+ case "MultiPolygon":
2878
+ return geometryHasZ(geometry) ? GaiaPolygonCodec.writeMultiPolygonZ(geometry, srid) : GaiaPolygonCodec.writeMultiPolygon(geometry, srid);
2879
+ case "Cad":
2880
+ throw new Error("CAD geometry is not supported by GaiaGeometryCodec.");
2881
+ case "Text":
2882
+ throw new Error("Text geometry is not supported by GaiaGeometryCodec.");
2883
+ default:
2884
+ throw new Error(`Unsupported geometry type: ${geometry.type}`);
2885
+ }
2886
+ }
2887
+ var GaiaGeometryCodec = class {
2888
+ static decode(input) {
2889
+ const header = readGaiaHeader(new BinaryCursor(input));
2890
+ const decoder = decodeByGeoType.get(header.geoType);
2891
+ if (!decoder) {
2892
+ throw new GaiaUnsupportedGeoTypeError(header.geoType);
2893
+ }
2894
+ return decoder(input);
2895
+ }
2896
+ static encode(geometry, srid) {
2897
+ return encodeGeometry(geometry, srid);
2898
+ }
2899
+ };
2900
+
2901
+ // src/core/geometry/jsts/JstsGeometryAdapter.ts
2902
+ var reader = null;
2903
+ var writer = null;
2904
+ async function getReader() {
2905
+ if (!reader) {
2906
+ const { default: GeoJSONReader } = await import("jsts/org/locationtech/jts/io/GeoJSONReader");
2907
+ const { default: GeometryFactory } = await import("jsts/org/locationtech/jts/geom/GeometryFactory");
2908
+ reader = new GeoJSONReader(new GeometryFactory());
2909
+ }
2910
+ return reader;
2911
+ }
2912
+ async function getWriter() {
2913
+ if (!writer) {
2914
+ const { default: GeoJSONWriter } = await import("jsts/org/locationtech/jts/io/GeoJSONWriter");
2915
+ writer = new GeoJSONWriter();
2916
+ }
2917
+ return writer;
2918
+ }
2919
+ async function toJsts(geometry) {
2920
+ const r = await getReader();
2921
+ return r.read(geometry);
2922
+ }
2923
+ async function fromJsts(jtsGeom) {
2924
+ const w = await getWriter();
2925
+ return w.write(jtsGeom);
2926
+ }
2927
+ async function toJstsPoint(geometry) {
2928
+ const r = await getReader();
2929
+ return r.read(geometry);
2930
+ }
2931
+ async function toJstsMultiLineString(geometry) {
2932
+ const r = await getReader();
2933
+ return r.read(geometry);
2934
+ }
2935
+ async function toJstsMultiPolygon(geometry) {
2936
+ const r = await getReader();
2937
+ return r.read(geometry);
2938
+ }
2939
+ var JstsGeometryCodec = class {
2940
+ static async decode(input) {
2941
+ const geojson = GaiaGeometryCodec.decode(input);
2942
+ return toJsts(geojson);
2943
+ }
2944
+ static async encode(jtsGeom, srid) {
2945
+ const geojson = await fromJsts(jtsGeom);
2946
+ return GaiaGeometryCodec.encode(geojson, srid);
2947
+ }
2948
+ };
2949
+ export {
2950
+ BaseDataset,
2951
+ BinaryCursor,
2952
+ BinaryWriter,
2953
+ CadDataset,
2954
+ GAIA_BYTE_ORDER_LE,
2955
+ GAIA_END,
2956
+ GAIA_GEOMETRY_DATA_OFFSET,
2957
+ GAIA_MBR,
2958
+ GAIA_START,
2959
+ GEO_TYPE_MULTILINESTRING,
2960
+ GEO_TYPE_MULTILINESTRINGZ,
2961
+ GEO_TYPE_MULTIPOLYGON,
2962
+ GEO_TYPE_MULTIPOLYGONZ,
2963
+ GEO_TYPE_POINT,
2964
+ GEO_TYPE_POINTZ,
2965
+ GaiaError,
2966
+ GaiaFormatError,
2967
+ GaiaGeoTypeMismatchError,
2968
+ GaiaGeometryCodec,
2969
+ GaiaLineCodec,
2970
+ GaiaPointCodec,
2971
+ GaiaPolygonCodec,
2972
+ GaiaUnsupportedGeoTypeError,
2973
+ JstsGeometryCodec,
2974
+ LineDataset,
2975
+ LineZDataset,
2976
+ NotImplementedError,
2977
+ PointDataset,
2978
+ PointZDataset,
2979
+ RegionDataset,
2980
+ RegionZDataset,
2981
+ SmFieldInfoRepository,
2982
+ SmRegisterRepository,
2983
+ TabularDataset,
2984
+ TextDataset,
2985
+ UDBX_SCHEMA_STATEMENTS,
2986
+ UDBX_SYSTEM_TABLES,
2987
+ UdbxConstraintError,
2988
+ UdbxDataSource,
2989
+ UdbxError,
2990
+ UdbxFormatError,
2991
+ UdbxIOError,
2992
+ UdbxNotFoundError,
2993
+ UdbxSchemaInitializer,
2994
+ UdbxUnsupportedError,
2995
+ createNotImplementedError,
2996
+ datasetKindToValue,
2997
+ datasetValueToKind,
2998
+ fieldTypeToValue,
2999
+ fieldValueToType,
3000
+ fromJsts,
3001
+ readGaiaHeader,
3002
+ toJsts,
3003
+ toJstsMultiLineString,
3004
+ toJstsMultiPolygon,
3005
+ toJstsPoint,
3006
+ validateGaiaEnd,
3007
+ writeGaiaHeader
3008
+ };
3009
+ //# sourceMappingURL=index.js.map