@map-colonies/mc-utils 3.3.0 → 3.4.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.
Files changed (46) hide show
  1. package/README.md +101 -0
  2. package/dist/files/index.d.ts +2 -0
  3. package/dist/files/index.d.ts.map +1 -0
  4. package/dist/files/index.js +18 -0
  5. package/dist/files/index.js.map +1 -0
  6. package/dist/files/shapefile/core/chunkBuilder.d.ts +18 -0
  7. package/dist/files/shapefile/core/chunkBuilder.d.ts.map +1 -0
  8. package/dist/files/shapefile/core/chunkBuilder.js +62 -0
  9. package/dist/files/shapefile/core/chunkBuilder.js.map +1 -0
  10. package/dist/files/shapefile/core/metricsManager.d.ts +25 -0
  11. package/dist/files/shapefile/core/metricsManager.d.ts.map +1 -0
  12. package/dist/files/shapefile/core/metricsManager.js +54 -0
  13. package/dist/files/shapefile/core/metricsManager.js.map +1 -0
  14. package/dist/files/shapefile/core/progressTracker.d.ts +60 -0
  15. package/dist/files/shapefile/core/progressTracker.d.ts.map +1 -0
  16. package/dist/files/shapefile/core/progressTracker.js +89 -0
  17. package/dist/files/shapefile/core/progressTracker.js.map +1 -0
  18. package/dist/files/shapefile/core/shapeFileReader.d.ts +30 -0
  19. package/dist/files/shapefile/core/shapeFileReader.d.ts.map +1 -0
  20. package/dist/files/shapefile/core/shapeFileReader.js +185 -0
  21. package/dist/files/shapefile/core/shapeFileReader.js.map +1 -0
  22. package/dist/files/shapefile/index.d.ts +3 -0
  23. package/dist/files/shapefile/index.d.ts.map +1 -0
  24. package/dist/files/shapefile/index.js +21 -0
  25. package/dist/files/shapefile/index.js.map +1 -0
  26. package/dist/files/shapefile/types/index.d.ts +22 -0
  27. package/dist/files/shapefile/types/index.d.ts.map +1 -0
  28. package/dist/files/shapefile/types/index.js +19 -0
  29. package/dist/files/shapefile/types/index.js.map +1 -0
  30. package/dist/files/shapefile/types/metrics.d.ts +26 -0
  31. package/dist/files/shapefile/types/metrics.d.ts.map +1 -0
  32. package/dist/files/shapefile/types/metrics.js +3 -0
  33. package/dist/files/shapefile/types/metrics.js.map +1 -0
  34. package/dist/files/shapefile/types/state.d.ts +30 -0
  35. package/dist/files/shapefile/types/state.d.ts.map +1 -0
  36. package/dist/files/shapefile/types/state.js +3 -0
  37. package/dist/files/shapefile/types/state.js.map +1 -0
  38. package/dist/geo/vertices.d.ts +9 -0
  39. package/dist/geo/vertices.d.ts.map +1 -0
  40. package/dist/geo/vertices.js +45 -0
  41. package/dist/geo/vertices.js.map +1 -0
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +1 -0
  45. package/dist/index.js.map +1 -1
  46. package/package.json +7 -4
package/README.md CHANGED
@@ -65,3 +65,104 @@ http requests retry configuration interface with the following attributes:
65
65
  - ```attempts``` - the number of request to send until valid response (not 500+ status code). this value must be integer and greater then 0.
66
66
  - ```delay``` - the amount of time in ms to wait between attempts (for constant delay) or ```'exponential'``` for exponential backoff.
67
67
  - ```shouldResetTimeout``` boolean value to indicate if the request timeout should be for each request (true) or global for all attempts (false)
68
+
69
+ ## Shapefile Processing with State Management
70
+
71
+ The `ShapefileChunkReader` provides robust shapefile processing with built-in state management and progress tracking capabilities.
72
+
73
+ ### Features
74
+
75
+ - **Resumable Processing**: Automatically saves processing state and can resume from the last processed chunk
76
+ - **Progress Tracking**: Real-time progress information including features processed, vertices counted, and time estimates
77
+ - **Metrics Collection**: Optional performance metrics collection for monitoring resource usage
78
+ - **Chunk-based Processing**: Processes large shapefiles in configurable chunks to manage memory usage
79
+
80
+ ### Basic Usage
81
+
82
+ ```typescript
83
+ import { ShapefileChunkReader, ReaderOptions, ChunkProcessor } from '@map-colonies/mc-utils';
84
+
85
+ // Define your chunk processor
86
+ const processor: ChunkProcessor = {
87
+ process: async (chunk) => {
88
+ console.log(`Processing chunk ${chunk.id} with ${chunk.features.length} features`);
89
+ // Your processing logic here
90
+ }
91
+ };
92
+
93
+ // Configure the reader
94
+ const options: ReaderOptions = {
95
+ maxVerticesPerChunk: 10000,
96
+ logger: myLogger,
97
+ stateManager: myStateManager, // Optional: for resumable processing
98
+ metricsCollector: myMetricsCollector, // Optional: for performance monitoring
99
+ };
100
+
101
+ // Create and use the reader
102
+ const reader = new ShapefileChunkReader(options);
103
+ await reader.readAndProcess('/path/to/shapefile.shp', processor);
104
+ ```
105
+
106
+ ### State Management
107
+
108
+ Implement the `StateManager` interface to enable resumable processing:
109
+
110
+ ```typescript
111
+ import { StateManager, ProcessingState } from '@map-colonies/mc-utils';
112
+
113
+ class FileStateManager implements StateManager {
114
+ async saveState(state: ProcessingState): Promise<void> {
115
+ // Save state to file, database, etc.
116
+ await fs.writeFile('processing-state.json', JSON.stringify(state));
117
+ }
118
+
119
+ async loadState(): Promise<ProcessingState | null> {
120
+ try {
121
+ const data = await fs.readFile('processing-state.json', 'utf8');
122
+ return JSON.parse(data);
123
+ } catch {
124
+ return null; // No previous state found
125
+ }
126
+ }
127
+ }
128
+ ```
129
+
130
+ ### Progress Tracking
131
+
132
+ The reader automatically tracks processing progress and provides detailed information:
133
+
134
+ ```typescript
135
+ // Progress information is included in the saved state
136
+ const progressInfo = state.progress; // Contains:
137
+ // - processedFeatures, totalFeatures
138
+ // - processedChunks, totalChunks
139
+ // - processedVertices, totalVertices
140
+ // - percentage, elapsedTimeMs, estimatedRemainingTimeMs
141
+ // - Processing speeds (features/sec, vertices/sec, chunks/sec)
142
+ ```
143
+
144
+ ### Metrics Collection
145
+
146
+ Implement the `MetricsCollector` interface to monitor performance:
147
+
148
+ ```typescript
149
+ import { MetricsCollector, ChunkMetrics, FileMetrics } from '@map-colonies/mc-utils';
150
+
151
+ const metricsCollector: MetricsCollector = {
152
+ onChunkMetrics: (metrics: ChunkMetrics) => {
153
+ console.log(`Chunk ${metrics.chunkIndex}: ${metrics.featuresCount} features, ${metrics.totalTimeMs}ms`);
154
+ },
155
+ onFileMetrics: (metrics: FileMetrics) => {
156
+ console.log(`File complete: ${metrics.totalFeatures} features, ${metrics.totalTimeMs}ms total`);
157
+ }
158
+ };
159
+ ```
160
+
161
+ ### Configuration Options
162
+
163
+ | Option | Type | Default | Description |
164
+ |--------|------|---------|-------------|
165
+ | `maxVerticesPerChunk` | number | Required | Maximum vertices per chunk to control memory usage |
166
+ | `logger` | Logger | undefined | Optional logger for debugging and monitoring |
167
+ | `stateManager` | StateManager | undefined | Optional state manager for resumable processing |
168
+ | `metricsCollector` | MetricsCollector | undefined | Optional metrics collector for performance monitoring |
@@ -0,0 +1,2 @@
1
+ export * from './shapefile';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/files/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./shapefile"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/files/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B"}
@@ -0,0 +1,18 @@
1
+ import { Feature } from 'geojson';
2
+ import { ShapefileChunk } from '../types/index';
3
+ export declare class ChunkBuilder {
4
+ private readonly maxVertices;
5
+ private chunkIndex;
6
+ private features;
7
+ private skippedFeatures;
8
+ private currentVerticesCount;
9
+ constructor(maxVertices: number, chunkIndex?: number);
10
+ get chunkId(): number;
11
+ canAddFeature(feature: Feature): boolean;
12
+ addFeature(feature: Feature): void;
13
+ build(): ShapefileChunk;
14
+ nextChunk(): void;
15
+ private withinSkipped;
16
+ private validateFeatureId;
17
+ }
18
+ //# sourceMappingURL=chunkBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunkBuilder.d.ts","sourceRoot":"","sources":["../../../../src/files/shapefile/core/chunkBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,qBAAa,YAAY;IAKJ,OAAO,CAAC,QAAQ,CAAC,WAAW;IAAU,OAAO,CAAC,UAAU;IAJ3E,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,eAAe,CAAY;IACnC,OAAO,CAAC,oBAAoB,CAAS;gBAED,WAAW,EAAE,MAAM,EAAU,UAAU,GAAE,MAAU;IAMvF,IAAW,OAAO,IAAI,MAAM,CAE3B;IAEM,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAaxC,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAUlC,KAAK,IAAI,cAAc;IASvB,SAAS,IAAI,IAAI;IAOxB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,iBAAiB;CAK1B"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChunkBuilder = void 0;
4
+ const vertices_1 = require("../../../geo/vertices");
5
+ class ChunkBuilder {
6
+ maxVertices;
7
+ chunkIndex;
8
+ features;
9
+ skippedFeatures;
10
+ currentVerticesCount;
11
+ constructor(maxVertices, chunkIndex = 0) {
12
+ this.maxVertices = maxVertices;
13
+ this.chunkIndex = chunkIndex;
14
+ this.features = [];
15
+ this.skippedFeatures = [];
16
+ this.currentVerticesCount = 0;
17
+ }
18
+ get chunkId() {
19
+ return this.chunkIndex;
20
+ }
21
+ canAddFeature(feature) {
22
+ this.validateFeatureId(feature);
23
+ const featureVertices = (0, vertices_1.countVertices)(feature.geometry);
24
+ if (featureVertices > this.maxVertices) {
25
+ this.skippedFeatures.push(feature);
26
+ return false;
27
+ }
28
+ return this.currentVerticesCount + featureVertices <= this.maxVertices;
29
+ }
30
+ addFeature(feature) {
31
+ this.validateFeatureId(feature);
32
+ if (this.withinSkipped(feature)) {
33
+ return;
34
+ }
35
+ this.features.push(feature);
36
+ this.currentVerticesCount += (0, vertices_1.countVertices)(feature.geometry);
37
+ }
38
+ build() {
39
+ return {
40
+ id: this.chunkIndex,
41
+ features: this.features,
42
+ skippedFeatures: this.skippedFeatures,
43
+ verticesCount: this.currentVerticesCount,
44
+ };
45
+ }
46
+ nextChunk() {
47
+ this.features = [];
48
+ this.skippedFeatures = [];
49
+ this.currentVerticesCount = 0;
50
+ this.chunkIndex++;
51
+ }
52
+ withinSkipped(feature) {
53
+ return this.skippedFeatures.some((skipped) => skipped.id === feature.id);
54
+ }
55
+ validateFeatureId(feature) {
56
+ if (feature.id === undefined) {
57
+ throw new Error('Feature must have an id');
58
+ }
59
+ }
60
+ }
61
+ exports.ChunkBuilder = ChunkBuilder;
62
+ //# sourceMappingURL=chunkBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunkBuilder.js","sourceRoot":"","sources":["../../../../src/files/shapefile/core/chunkBuilder.ts"],"names":[],"mappings":";;;AAEA,oDAAsD;AAEtD,MAAa,YAAY;IAKa;IAA6B;IAJzD,QAAQ,CAAY;IACpB,eAAe,CAAY;IAC3B,oBAAoB,CAAS;IAErC,YAAoC,WAAmB,EAAU,aAAqB,CAAC;QAAnD,gBAAW,GAAX,WAAW,CAAQ;QAAU,eAAU,GAAV,UAAU,CAAY;QACrF,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,IAAW,OAAO;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAEM,aAAa,CAAC,OAAgB;QACnC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAEhC,MAAM,eAAe,GAAG,IAAA,wBAAa,EAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAExD,IAAI,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE;YACtC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnC,OAAO,KAAK,CAAC;SACd;QAED,OAAO,IAAI,CAAC,oBAAoB,GAAG,eAAe,IAAI,IAAI,CAAC,WAAW,CAAC;IACzE,CAAC;IAEM,UAAU,CAAC,OAAgB;QAChC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAEhC,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;YAC/B,OAAO;SACR;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,CAAC,oBAAoB,IAAI,IAAA,wBAAa,EAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/D,CAAC;IAEM,KAAK;QACV,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,UAAU;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,aAAa,EAAE,IAAI,CAAC,oBAAoB;SACzC,CAAC;IACJ,CAAC;IAEM,SAAS;QACd,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAEO,aAAa,CAAC,OAAgB;QACpC,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAEO,iBAAiB,CAAC,OAAgB;QACxC,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE;YAC5B,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;IACH,CAAC;CACF;AA/DD,oCA+DC"}
@@ -0,0 +1,25 @@
1
+ import { FileMetrics, MetricsCollector } from '../types';
2
+ import { ShapefileChunk } from '../types';
3
+ export interface IMetricsManager {
4
+ /**
5
+ * Updates metrics with chunk processing information
6
+ * @param chunk The chunk that was processed
7
+ * @param readTime Time spent reading the chunk in milliseconds
8
+ * @param processTime Time spent processing the chunk in milliseconds
9
+ */
10
+ sendChunkMetrics: (chunk: ShapefileChunk, readTime: number, processTime: number) => void;
11
+ /**
12
+ * Finalizes metrics collection and notifies collectors
13
+ * @returns The finalized file metrics
14
+ */
15
+ sendFileMetrics: () => FileMetrics;
16
+ }
17
+ export declare class MetricsManager implements IMetricsManager {
18
+ private readonly metricsCollector?;
19
+ private fileMetrics;
20
+ constructor(metricsCollector?: MetricsCollector | undefined);
21
+ sendChunkMetrics(chunk: ShapefileChunk, readTime: number, processTime: number): void;
22
+ sendFileMetrics(): FileMetrics;
23
+ private initializeFileMetrics;
24
+ }
25
+ //# sourceMappingURL=metricsManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metricsManager.d.ts","sourceRoot":"","sources":["../../../../src/files/shapefile/core/metricsManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,gBAAgB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAEzF;;;OAGG;IACH,eAAe,EAAE,MAAM,WAAW,CAAC;CACpC;AAED,qBAAa,cAAe,YAAW,eAAe;IAGjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAFrD,OAAO,CAAC,WAAW,CAAc;gBAEG,gBAAgB,CAAC,8BAAkB;IAIhE,gBAAgB,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IA4BpF,eAAe,IAAI,WAAW;IAOrC,OAAO,CAAC,qBAAqB;CAY9B"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MetricsManager = void 0;
4
+ class MetricsManager {
5
+ metricsCollector;
6
+ fileMetrics;
7
+ constructor(metricsCollector) {
8
+ this.metricsCollector = metricsCollector;
9
+ this.fileMetrics = this.initializeFileMetrics();
10
+ }
11
+ sendChunkMetrics(chunk, readTime, processTime) {
12
+ const totalTime = readTime + processTime;
13
+ // Update file metrics
14
+ this.fileMetrics.totalFeatures += chunk.features.length;
15
+ this.fileMetrics.totalSkippedFeatures += chunk.skippedFeatures.length;
16
+ this.fileMetrics.totalVertices += chunk.verticesCount;
17
+ this.fileMetrics.totalChunks++;
18
+ this.fileMetrics.totalReadTimeMs += readTime;
19
+ this.fileMetrics.totalProcessTimeMs += processTime;
20
+ this.fileMetrics.totalTimeMs += totalTime;
21
+ // Create chunk metrics
22
+ const chunkMetrics = {
23
+ chunkIndex: chunk.id,
24
+ featuresCount: chunk.features.length,
25
+ skippedFeaturesCount: chunk.skippedFeatures.length,
26
+ verticesCount: chunk.verticesCount,
27
+ readTimeMs: readTime,
28
+ processTimeMs: processTime,
29
+ totalTimeMs: totalTime,
30
+ timestamp: new Date(),
31
+ };
32
+ // Notify metrics collector
33
+ this.metricsCollector?.onChunkMetrics?.(chunkMetrics);
34
+ }
35
+ sendFileMetrics() {
36
+ this.fileMetrics.endTime = new Date();
37
+ this.metricsCollector?.onFileMetrics?.(this.fileMetrics);
38
+ return this.fileMetrics;
39
+ }
40
+ initializeFileMetrics() {
41
+ return {
42
+ totalFeatures: 0,
43
+ totalSkippedFeatures: 0,
44
+ totalVertices: 0,
45
+ totalChunks: 0,
46
+ totalReadTimeMs: 0,
47
+ totalProcessTimeMs: 0,
48
+ totalTimeMs: 0,
49
+ startTime: new Date(),
50
+ };
51
+ }
52
+ }
53
+ exports.MetricsManager = MetricsManager;
54
+ //# sourceMappingURL=metricsManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metricsManager.js","sourceRoot":"","sources":["../../../../src/files/shapefile/core/metricsManager.ts"],"names":[],"mappings":";;;AAmBA,MAAa,cAAc;IAGW;IAF5B,WAAW,CAAc;IAEjC,YAAoC,gBAAmC;QAAnC,qBAAgB,GAAhB,gBAAgB,CAAmB;QACrE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAClD,CAAC;IAEM,gBAAgB,CAAC,KAAqB,EAAE,QAAgB,EAAE,WAAmB;QAClF,MAAM,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;QAEzC,sBAAsB;QACtB,IAAI,CAAC,WAAW,CAAC,aAAa,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACxD,IAAI,CAAC,WAAW,CAAC,oBAAoB,IAAI,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC;QACtE,IAAI,CAAC,WAAW,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,CAAC;QACtD,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,WAAW,CAAC,eAAe,IAAI,QAAQ,CAAC;QAC7C,IAAI,CAAC,WAAW,CAAC,kBAAkB,IAAI,WAAW,CAAC;QACnD,IAAI,CAAC,WAAW,CAAC,WAAW,IAAI,SAAS,CAAC;QAE1C,uBAAuB;QACvB,MAAM,YAAY,GAAiB;YACjC,UAAU,EAAE,KAAK,CAAC,EAAE;YACpB,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;YACpC,oBAAoB,EAAE,KAAK,CAAC,eAAe,CAAC,MAAM;YAClD,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,UAAU,EAAE,QAAQ;YACpB,aAAa,EAAE,WAAW;YAC1B,WAAW,EAAE,SAAS;YACtB,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;QAEF,2BAA2B;QAC3B,IAAI,CAAC,gBAAgB,EAAE,cAAc,EAAE,CAAC,YAAY,CAAC,CAAC;IACxD,CAAC;IAEM,eAAe;QACpB,IAAI,CAAC,WAAW,CAAC,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;QAEtC,IAAI,CAAC,gBAAgB,EAAE,aAAa,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEO,qBAAqB;QAC3B,OAAO;YACL,aAAa,EAAE,CAAC;YAChB,oBAAoB,EAAE,CAAC;YACvB,aAAa,EAAE,CAAC;YAChB,WAAW,EAAE,CAAC;YACd,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE,CAAC;YACrB,WAAW,EAAE,CAAC;YACd,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;IACJ,CAAC;CACF;AAtDD,wCAsDC"}
@@ -0,0 +1,60 @@
1
+ import { InitialProgress, ProgressInfo } from '../types';
2
+ /**
3
+ * Interface for progress tracking functionality
4
+ */
5
+ export interface IProgressTracker {
6
+ /**
7
+ * Increments the features counter vertices processed
8
+ * @param featuresCount Number of features processed in the current operation
9
+ * @param processedVertices Number of vertices processed in the current operation
10
+ */
11
+ addProcessedFeatures: (featuresCount: number, processedVertices: number) => void;
12
+ /**
13
+ * Increments the skipped features counter
14
+ * @param count Number of skipped features
15
+ */
16
+ addSkippedFeatures: (count: number) => void;
17
+ /**
18
+ * Increments the chunks counter
19
+ */
20
+ incrementChunks: () => void;
21
+ /**
22
+ * Gets the number of processed features
23
+ * @returns Number of processed features
24
+ */
25
+ getProcessedFeatures: () => number;
26
+ /**
27
+ * Calculates and returns current progress information
28
+ * @returns Current progress information
29
+ */
30
+ calculateProgress: () => ProgressInfo;
31
+ }
32
+ /**
33
+ * Configuration options for ProgressTracker constructor
34
+ */
35
+ export interface ProgressTrackerOptions {
36
+ totalVertices: number;
37
+ totalFeatures: number;
38
+ maxVerticesPerChunk: number;
39
+ initialProgress?: InitialProgress;
40
+ }
41
+ /**
42
+ * Implementation of progress tracking for shapefile processing
43
+ */
44
+ export declare class ProgressTracker implements IProgressTracker {
45
+ private readonly startTime;
46
+ private readonly totalVertices;
47
+ private readonly totalFeatures;
48
+ private readonly maxVerticesPerChunk;
49
+ private processedVertices;
50
+ private processedFeatures;
51
+ private skippedFeatures;
52
+ private processedChunks;
53
+ constructor(options: ProgressTrackerOptions);
54
+ addProcessedFeatures(featuresCount: number, processedVertices: number): void;
55
+ addSkippedFeatures(count: number): void;
56
+ getProcessedFeatures(): number;
57
+ incrementChunks(): void;
58
+ calculateProgress(): ProgressInfo;
59
+ }
60
+ //# sourceMappingURL=progressTracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressTracker.d.ts","sourceRoot":"","sources":["../../../../src/files/shapefile/core/progressTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,oBAAoB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,KAAK,IAAI,CAAC;IAEjF;;;OAGG;IACH,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAE5C;;OAEG;IACH,eAAe,EAAE,MAAM,IAAI,CAAC;IAE5B;;;OAGG;IACH,oBAAoB,EAAE,MAAM,MAAM,CAAC;IAEnC;;;OAGG;IACH,iBAAiB,EAAE,MAAM,YAAY,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,eAAe,CAAS;gBAEb,OAAO,EAAE,sBAAsB;IAoB3C,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI;IAK5E,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvC,oBAAoB,IAAI,MAAM;IAI9B,eAAe,IAAI,IAAI;IAIvB,iBAAiB,IAAI,YAAY;CA+CzC"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProgressTracker = void 0;
4
+ /**
5
+ * Implementation of progress tracking for shapefile processing
6
+ */
7
+ class ProgressTracker {
8
+ startTime;
9
+ totalVertices;
10
+ totalFeatures;
11
+ maxVerticesPerChunk;
12
+ processedVertices;
13
+ processedFeatures;
14
+ skippedFeatures;
15
+ processedChunks;
16
+ constructor(options) {
17
+ this.totalVertices = options.totalVertices;
18
+ this.totalFeatures = options.totalFeatures;
19
+ this.maxVerticesPerChunk = options.maxVerticesPerChunk;
20
+ const initialProgress = options.initialProgress ?? {
21
+ processedChunks: 0,
22
+ processedFeatures: 0,
23
+ processedVertices: 0,
24
+ skippedFeatures: 0,
25
+ startTime: Date.now(),
26
+ };
27
+ this.startTime = initialProgress.startTime;
28
+ this.processedVertices = initialProgress.processedVertices;
29
+ this.processedFeatures = initialProgress.processedFeatures;
30
+ this.processedChunks = initialProgress.processedChunks;
31
+ this.skippedFeatures = initialProgress.skippedFeatures;
32
+ }
33
+ addProcessedFeatures(featuresCount, processedVertices) {
34
+ this.processedVertices += processedVertices;
35
+ this.processedFeatures += featuresCount;
36
+ }
37
+ addSkippedFeatures(count) {
38
+ this.skippedFeatures += count;
39
+ }
40
+ getProcessedFeatures() {
41
+ return this.processedFeatures;
42
+ }
43
+ incrementChunks() {
44
+ this.processedChunks++;
45
+ }
46
+ calculateProgress() {
47
+ const currentTime = Date.now();
48
+ const elapsedTimeMs = currentTime - this.startTime;
49
+ // Calculate percentage based on vertices processed
50
+ let percentage = 0;
51
+ const maxPercentage = 100;
52
+ if (this.totalVertices > 0) {
53
+ percentage = Math.min((this.processedVertices / this.totalVertices) * maxPercentage, maxPercentage);
54
+ }
55
+ // Calculate processing speeds
56
+ const millisecondsPerSecond = 1000;
57
+ const elapsedSeconds = elapsedTimeMs / millisecondsPerSecond;
58
+ const featuresPerSecond = elapsedSeconds > 0 ? this.processedFeatures / elapsedSeconds : 0;
59
+ const verticesPerSecond = elapsedSeconds > 0 ? this.processedVertices / elapsedSeconds : 0;
60
+ const chunksPerSecond = elapsedSeconds > 0 ? this.processedChunks / elapsedSeconds : 0;
61
+ // Estimate remaining time
62
+ let estimatedRemainingTimeMs = 0;
63
+ if (percentage > 0 && percentage < maxPercentage) {
64
+ const totalEstimatedTimeMs = (elapsedTimeMs / percentage) * maxPercentage;
65
+ estimatedRemainingTimeMs = totalEstimatedTimeMs - elapsedTimeMs;
66
+ }
67
+ const estimatedTotalChunks = this.totalVertices > 0 ? Math.ceil(this.totalVertices / this.maxVerticesPerChunk) : this.processedChunks;
68
+ const endTime = this.processedFeatures === this.totalFeatures ? currentTime : undefined;
69
+ return {
70
+ processedFeatures: this.processedFeatures,
71
+ totalFeatures: this.totalFeatures,
72
+ processedChunks: this.processedChunks,
73
+ totalChunks: estimatedTotalChunks,
74
+ processedVertices: this.processedVertices,
75
+ totalVertices: this.totalVertices,
76
+ skippedFeatures: this.skippedFeatures,
77
+ percentage,
78
+ elapsedTimeMs,
79
+ estimatedRemainingTimeMs,
80
+ featuresPerSecond,
81
+ verticesPerSecond,
82
+ chunksPerSecond,
83
+ startTime: this.startTime,
84
+ endTime,
85
+ };
86
+ }
87
+ }
88
+ exports.ProgressTracker = ProgressTracker;
89
+ //# sourceMappingURL=progressTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressTracker.js","sourceRoot":"","sources":["../../../../src/files/shapefile/core/progressTracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { ReaderOptions, ChunkProcessor, ProgressInfo } from '../types';
2
+ export declare class ShapefileChunkReader {
3
+ private readonly options;
4
+ private metricsManager?;
5
+ private progressTracker?;
6
+ private lastState;
7
+ constructor(options: ReaderOptions);
8
+ /**
9
+ * Reads a shapefile and processes it in chunks.
10
+ * @param shapefilePath Path to the shapefile to read
11
+ * @param processor Processor to handle each chunk of features
12
+ */
13
+ readAndProcess(shapefilePath: string, processor: ChunkProcessor): Promise<void>;
14
+ /**
15
+ * Count total features and vertices in the shapefile for progress calculation
16
+ * @param shapefilePath Path to the shapefile
17
+ * @returns Total number of features and vertices in the shapefile
18
+ */
19
+ getShapefileStats(shapefilePath: string): Promise<Pick<ProgressInfo, 'totalVertices' | 'totalFeatures'>>;
20
+ private processChunk;
21
+ /**
22
+ * Save processing state if state manager is available
23
+ * @param state State object containing the required state information
24
+ */
25
+ private saveProcessingState;
26
+ private initializeReading;
27
+ private shouldSkipFeature;
28
+ private hasContentToProcess;
29
+ }
30
+ //# sourceMappingURL=shapeFileReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shapeFileReader.d.ts","sourceRoot":"","sources":["../../../../src/files/shapefile/core/shapeFileReader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAmC,YAAY,EAAE,MAAM,UAAU,CAAC;AAMxG,qBAAa,oBAAoB;IAKZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ3C,OAAO,CAAC,cAAc,CAAC,CAAkB;IACzC,OAAO,CAAC,eAAe,CAAC,CAAmB;IAC3C,OAAO,CAAC,SAAS,CAAgC;gBAEb,OAAO,EAAE,aAAa;IAE1D;;;;OAIG;IACU,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAgE5F;;;;OAIG;IACU,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,eAAe,CAAC,CAAC;YAyCvG,YAAY;IA6B1B;;;OAGG;YACW,mBAAmB;YAenB,iBAAiB;IAuB/B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,mBAAmB;CAG5B"}
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ShapefileChunkReader = void 0;
4
+ /* eslint-disable @typescript-eslint/no-magic-numbers */
5
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
6
+ const shapefile_1 = require("shapefile");
7
+ const vertices_1 = require("../../../geo/vertices");
8
+ const chunkBuilder_1 = require("./chunkBuilder");
9
+ const progressTracker_1 = require("./progressTracker");
10
+ const metricsManager_1 = require("./metricsManager");
11
+ class ShapefileChunkReader {
12
+ options;
13
+ metricsManager;
14
+ progressTracker;
15
+ lastState = null;
16
+ constructor(options) {
17
+ this.options = options;
18
+ }
19
+ /**
20
+ * Reads a shapefile and processes it in chunks.
21
+ * @param shapefilePath Path to the shapefile to read
22
+ * @param processor Processor to handle each chunk of features
23
+ */
24
+ async readAndProcess(shapefilePath, processor) {
25
+ const chunkIndex = await this.initializeReading(shapefilePath);
26
+ let readFeatureIndex = -1;
27
+ const chunkBuilder = new chunkBuilder_1.ChunkBuilder(this.options.maxVerticesPerChunk, chunkIndex);
28
+ try {
29
+ const reader = await (0, shapefile_1.open)(shapefilePath);
30
+ this.options.logger?.info({ msg: 'Reading started' });
31
+ let readStart = performance.now();
32
+ // eslint-disable-next-line no-constant-condition
33
+ while (true) {
34
+ const { done, value: feature } = await reader.read();
35
+ if (done) {
36
+ break;
37
+ }
38
+ readFeatureIndex++;
39
+ if (this.shouldSkipFeature(readFeatureIndex)) {
40
+ continue;
41
+ }
42
+ if (!chunkBuilder.canAddFeature(feature)) {
43
+ const readTime = performance.now() - readStart;
44
+ const chunk = chunkBuilder.build();
45
+ this.options.logger?.info({ msg: 'Chunk reading finished', readTime, chunkIndex: chunk.id, featuresCount: chunk.features.length });
46
+ if (this.hasContentToProcess(chunk)) {
47
+ await this.processChunk(chunk, processor, shapefilePath, readTime);
48
+ }
49
+ chunkBuilder.nextChunk();
50
+ readStart = performance.now();
51
+ }
52
+ chunkBuilder.addFeature(feature);
53
+ }
54
+ // Process any remaining features
55
+ const readTime = performance.now() - readStart;
56
+ const finalChunk = chunkBuilder.build();
57
+ if (this.hasContentToProcess(finalChunk)) {
58
+ this.options.logger?.info({
59
+ msg: 'Final chunk reading finished',
60
+ });
61
+ await this.processChunk(finalChunk, processor, shapefilePath, readTime);
62
+ }
63
+ this.metricsManager?.sendFileMetrics();
64
+ }
65
+ catch (error) {
66
+ const lastFeatureIndex = (this.progressTracker?.getProcessedFeatures() ?? 0) - 1;
67
+ this.options.logger?.error({ msg: 'Error processing shapefile', shapefilePath, lastFeatureIndex, error });
68
+ await this.saveProcessingState({
69
+ filePath: shapefilePath,
70
+ chunkIndex: chunkBuilder.chunkId,
71
+ lastFeatureIndex,
72
+ });
73
+ throw error;
74
+ }
75
+ }
76
+ /**
77
+ * Count total features and vertices in the shapefile for progress calculation
78
+ * @param shapefilePath Path to the shapefile
79
+ * @returns Total number of features and vertices in the shapefile
80
+ */
81
+ async getShapefileStats(shapefilePath) {
82
+ const reader = await (0, shapefile_1.open)(shapefilePath);
83
+ let totalVertices = 0;
84
+ let totalFeatures = 0;
85
+ try {
86
+ // eslint-disable-next-line no-constant-condition
87
+ while (true) {
88
+ const { done, value: feature } = await reader.read();
89
+ if (done) {
90
+ break;
91
+ }
92
+ const vertices = (0, vertices_1.countVertices)(feature.geometry);
93
+ if (vertices > this.options.maxVerticesPerChunk) {
94
+ this.options.logger?.warn({
95
+ msg: `Feature exceeds maximum vertices limit: ${vertices} > ${this.options.maxVerticesPerChunk}`,
96
+ featureId: feature.id,
97
+ });
98
+ continue; // Skip features that exceed the limit
99
+ }
100
+ totalFeatures++;
101
+ totalVertices += vertices;
102
+ }
103
+ }
104
+ catch (error) {
105
+ this.options.logger?.error({ msg: 'Error counting vertices in shapefile', shapefilePath, error });
106
+ throw error;
107
+ }
108
+ if (totalFeatures === 0 || totalVertices === 0) {
109
+ const message = `Shapefile ${shapefilePath} has no valid features or vertices`;
110
+ this.options.logger?.error({ msg: message });
111
+ throw new Error(message);
112
+ }
113
+ return { totalVertices, totalFeatures };
114
+ }
115
+ async processChunk(chunk, processor, filePath, readTime = 0) {
116
+ const processStart = performance.now();
117
+ try {
118
+ this.options.logger?.info({ msg: 'Processing chunk', chunkIndex: chunk.id, featuresCount: chunk.features.length, filePath, readTime });
119
+ await processor.process(chunk);
120
+ this.options.logger?.info({ msg: 'Chunk processing finished', chunkIndex: chunk.id });
121
+ }
122
+ catch (error) {
123
+ this.options.logger?.error(`Error processing chunk ${chunk.id}`, error);
124
+ throw error;
125
+ }
126
+ const processTime = performance.now() - processStart;
127
+ this.metricsManager?.sendChunkMetrics(chunk, readTime, processTime);
128
+ this.progressTracker?.addProcessedFeatures(chunk.features.length, chunk.verticesCount);
129
+ this.progressTracker?.addSkippedFeatures(chunk.skippedFeatures.length);
130
+ this.progressTracker?.incrementChunks();
131
+ const lastFeatureIndex = (this.progressTracker?.getProcessedFeatures() ?? 0) - 1;
132
+ // Save state after successful processing with progress information
133
+ await this.saveProcessingState({
134
+ filePath,
135
+ chunkIndex: chunk.id,
136
+ lastFeatureIndex,
137
+ });
138
+ }
139
+ /**
140
+ * Save processing state if state manager is available
141
+ * @param state State object containing the required state information
142
+ */
143
+ async saveProcessingState(state) {
144
+ if (!this.options.stateManager) {
145
+ return;
146
+ }
147
+ const currentState = {
148
+ filePath: state.filePath,
149
+ lastProcessedChunkIndex: state.chunkIndex,
150
+ lastProcessedFeatureIndex: state.lastFeatureIndex,
151
+ timestamp: new Date(),
152
+ progress: this.progressTracker?.calculateProgress(),
153
+ };
154
+ await this.options.stateManager.saveState(currentState);
155
+ }
156
+ async initializeReading(shapefilePath) {
157
+ try {
158
+ if (this.options.metricsCollector) {
159
+ this.metricsManager = new metricsManager_1.MetricsManager(this.options.metricsCollector);
160
+ }
161
+ this.lastState = (await this.options.stateManager?.loadState()) ?? null;
162
+ const { totalFeatures, totalVertices } = this.lastState?.progress ?? (await this.getShapefileStats(shapefilePath));
163
+ this.progressTracker = new progressTracker_1.ProgressTracker({
164
+ totalVertices,
165
+ totalFeatures,
166
+ maxVerticesPerChunk: this.options.maxVerticesPerChunk,
167
+ initialProgress: this.lastState?.progress,
168
+ });
169
+ const chunkIndex = this.lastState?.lastProcessedChunkIndex ?? 0;
170
+ return chunkIndex;
171
+ }
172
+ catch (error) {
173
+ this.options.logger?.error({ msg: 'Failed to initialize reading', error });
174
+ throw error;
175
+ }
176
+ }
177
+ shouldSkipFeature(featureIndex) {
178
+ return this.lastState !== null && featureIndex <= this.lastState.lastProcessedFeatureIndex;
179
+ }
180
+ hasContentToProcess(chunk) {
181
+ return chunk.features.length > 0 || chunk.skippedFeatures.length > 0;
182
+ }
183
+ }
184
+ exports.ShapefileChunkReader = ShapefileChunkReader;
185
+ //# sourceMappingURL=shapeFileReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shapeFileReader.js","sourceRoot":"","sources":["../../../../src/files/shapefile/core/shapeFileReader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ShapefileChunkReader } from './core/shapeFileReader';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/files/shapefile/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,cAAc,SAAS,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.ShapefileChunkReader = void 0;
18
+ var shapeFileReader_1 = require("./core/shapeFileReader");
19
+ Object.defineProperty(exports, "ShapefileChunkReader", { enumerable: true, get: function () { return shapeFileReader_1.ShapefileChunkReader; } });
20
+ __exportStar(require("./types"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/files/shapefile/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,0DAA8D;AAArD,uHAAA,oBAAoB,OAAA;AAC7B,0CAAwB"}
@@ -0,0 +1,22 @@
1
+ import { Feature } from 'geojson';
2
+ import { Logger } from '@map-colonies/js-logger';
3
+ import { StateManager } from '../types';
4
+ import { MetricsCollector } from './metrics';
5
+ export * from './metrics';
6
+ export * from './state';
7
+ export interface ShapefileChunk {
8
+ id: number;
9
+ features: Feature[];
10
+ skippedFeatures: Feature[];
11
+ verticesCount: number;
12
+ }
13
+ export interface ChunkProcessor {
14
+ process: (chunk: ShapefileChunk) => Promise<void>;
15
+ }
16
+ export interface ReaderOptions {
17
+ logger?: Logger;
18
+ maxVerticesPerChunk: number;
19
+ stateManager?: StateManager;
20
+ metricsCollector?: MetricsCollector;
21
+ }
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/files/shapefile/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AAExB,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./metrics"), exports);
18
+ __exportStar(require("./state"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/files/shapefile/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAKA,4CAA0B;AAC1B,0CAAwB"}
@@ -0,0 +1,26 @@
1
+ export interface ChunkMetrics {
2
+ chunkIndex: number;
3
+ featuresCount: number;
4
+ skippedFeaturesCount: number;
5
+ verticesCount: number;
6
+ readTimeMs: number;
7
+ processTimeMs: number;
8
+ totalTimeMs: number;
9
+ timestamp: Date;
10
+ }
11
+ export interface FileMetrics {
12
+ totalFeatures: number;
13
+ totalSkippedFeatures: number;
14
+ totalVertices: number;
15
+ totalChunks: number;
16
+ totalReadTimeMs: number;
17
+ totalProcessTimeMs: number;
18
+ totalTimeMs: number;
19
+ startTime: Date;
20
+ endTime?: Date;
21
+ }
22
+ export interface MetricsCollector {
23
+ onChunkMetrics?: (metrics: ChunkMetrics) => void;
24
+ onFileMetrics?: (metrics: FileMetrics) => void;
25
+ }
26
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../../src/files/shapefile/types/metrics.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACjD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAChD"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../../src/files/shapefile/types/metrics.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ export interface StateManager {
2
+ saveState: (state: ProcessingState) => Promise<void> | void;
3
+ loadState: () => (ProcessingState | null) | Promise<ProcessingState | null>;
4
+ }
5
+ export interface ProgressInfo {
6
+ startTime: number;
7
+ endTime?: number;
8
+ processedFeatures: number;
9
+ totalFeatures: number;
10
+ processedChunks: number;
11
+ totalChunks: number;
12
+ processedVertices: number;
13
+ totalVertices: number;
14
+ skippedFeatures: number;
15
+ percentage: number;
16
+ elapsedTimeMs: number;
17
+ estimatedRemainingTimeMs: number;
18
+ featuresPerSecond: number;
19
+ verticesPerSecond: number;
20
+ chunksPerSecond: number;
21
+ }
22
+ export declare type InitialProgress = Pick<ProgressInfo, 'startTime' | 'processedVertices' | 'processedFeatures' | 'processedChunks' | 'skippedFeatures'>;
23
+ export interface ProcessingState {
24
+ filePath: string;
25
+ lastProcessedChunkIndex: number;
26
+ lastProcessedFeatureIndex: number;
27
+ timestamp: Date;
28
+ progress?: ProgressInfo;
29
+ }
30
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/files/shapefile/types/state.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5D,SAAS,EAAE,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,wBAAwB,EAAE,MAAM,CAAC;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,oBAAY,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;AAElJ,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB,EAAE,MAAM,CAAC;IAChC,yBAAyB,EAAE,MAAM,CAAC;IAClC,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/files/shapefile/types/state.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import { Geometry } from 'geojson';
2
+ /**
3
+ * Counts the number of vertices in a given geometry.
4
+ * @param geometry - The geometry object to count vertices in.
5
+ * @returns The total number of vertices in the geometry.
6
+ * @throws Will throw an error if the geometry type is unsupported.
7
+ */
8
+ export declare function countVertices(geometry: Geometry): number;
9
+ //# sourceMappingURL=vertices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vertices.d.ts","sourceRoot":"","sources":["../../src/geo/vertices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAmCxD"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.countVertices = void 0;
4
+ /**
5
+ * Counts the number of vertices in a given geometry.
6
+ * @param geometry - The geometry object to count vertices in.
7
+ * @returns The total number of vertices in the geometry.
8
+ * @throws Will throw an error if the geometry type is unsupported.
9
+ */
10
+ function countVertices(geometry) {
11
+ let count = 0;
12
+ switch (geometry.type) {
13
+ case 'Polygon':
14
+ geometry.coordinates.forEach((ring) => {
15
+ count += ring.length;
16
+ });
17
+ break;
18
+ case 'MultiPolygon':
19
+ geometry.coordinates.forEach((polygon) => {
20
+ polygon.forEach((ring) => {
21
+ count += ring.length;
22
+ });
23
+ });
24
+ break;
25
+ case 'LineString':
26
+ count = geometry.coordinates.length; // Each point in a LineString is a vertex
27
+ break;
28
+ case 'MultiLineString':
29
+ geometry.coordinates.forEach((line) => {
30
+ count += line.length;
31
+ });
32
+ break;
33
+ case 'Point':
34
+ count = 1; // A point is considered to have 1 vertex
35
+ break;
36
+ case 'MultiPoint':
37
+ count = geometry.coordinates.length; // Each point is a vertex
38
+ break;
39
+ default:
40
+ throw new Error(`Unsupported geometry type: ${geometry.type}`);
41
+ }
42
+ return count;
43
+ }
44
+ exports.countVertices = countVertices;
45
+ //# sourceMappingURL=vertices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vertices.js","sourceRoot":"","sources":["../../src/geo/vertices.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,QAAkB;IAC9C,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,QAAQ,QAAQ,CAAC,IAAI,EAAE;QACrB,KAAK,SAAS;YACZ,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACpC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;YACvB,CAAC,CAAC,CAAC;YACH,MAAM;QACR,KAAK,cAAc;YACjB,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACvC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;oBACvB,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;gBACvB,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YACH,MAAM;QACR,KAAK,YAAY;YACf,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,yCAAyC;YAC9E,MAAM;QACR,KAAK,iBAAiB;YACpB,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACpC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;YACvB,CAAC,CAAC,CAAC;YACH,MAAM;QACR,KAAK,OAAO;YACV,KAAK,GAAG,CAAC,CAAC,CAAC,yCAAyC;YACpD,MAAM;QACR,KAAK,YAAY;YACf,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,yBAAyB;YAC9D,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;KAClE;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAnCD,sCAmCC"}
package/dist/index.d.ts CHANGED
@@ -4,4 +4,5 @@ export * from './dateTime';
4
4
  export * from './geo';
5
5
  export * from './arrays';
6
6
  export * from './utils';
7
+ export * from './files';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -20,4 +20,5 @@ __exportStar(require("./dateTime"), exports);
20
20
  __exportStar(require("./geo"), exports);
21
21
  __exportStar(require("./arrays"), exports);
22
22
  __exportStar(require("./utils"), exports);
23
+ __exportStar(require("./files"), exports);
23
24
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,kDAAgC;AAChC,6CAA2B;AAC3B,wCAAsB;AACtB,2CAAyB;AACzB,0CAAwB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,kDAAgC;AAChC,6CAA2B;AAC3B,wCAAsB;AACtB,2CAAyB;AACzB,0CAAwB;AACxB,0CAAwB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@map-colonies/mc-utils",
3
- "version": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "description": "This is template for map colonies typescript packages",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -40,18 +40,20 @@
40
40
  ],
41
41
  "homepage": "https://github.com/MapColonies/mc-utils#readme",
42
42
  "devDependencies": {
43
- "eslint": "^8.36.0",
44
- "commitlint": "^17.4.4",
45
43
  "@commitlint/cli": "^17.4.4",
46
44
  "@commitlint/config-conventional": "^17.4.4",
47
45
  "@map-colonies/eslint-config": "^3.1.3",
48
46
  "@map-colonies/prettier-config": "0.0.1",
49
47
  "@types/express": "^4.17.17",
48
+ "@types/geojson": "^7946.0.16",
50
49
  "@types/jest": "^29.4.0",
51
50
  "@types/lodash": "^4.14.171",
52
51
  "@types/ngeohash": "^0.6.3",
53
52
  "@types/node": "^14.14.12",
53
+ "@types/shapefile": "^0.6.4",
54
+ "commitlint": "^17.4.4",
54
55
  "cz-conventional-changelog": "^3.3.0",
56
+ "eslint": "^8.36.0",
55
57
  "husky": "^8.0.3",
56
58
  "jest": "^29.5.0",
57
59
  "jest-create-mock-instance": "^2.0.0",
@@ -70,7 +72,8 @@
70
72
  "axios-retry": "^3.4.0",
71
73
  "http-status-codes": "^2.2.0",
72
74
  "lodash": "^4.17.21",
73
- "ngeohash": "^0.6.3"
75
+ "ngeohash": "^0.6.3",
76
+ "shapefile": "^0.6.6"
74
77
  },
75
78
  "peerDependencies": {
76
79
  "@map-colonies/error-types": "^1.3.1",