@tmlmobilidade/utils 20251103.1255.55 → 20251202.1821.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +239 -9
- package/dist/{src/http.js → http.js} +1 -1
- package/dist/index.d.ts +8 -17
- package/dist/index.js +8 -17
- package/dist/objects/fill-template.d.ts +7 -0
- package/dist/objects/fill-template.js +52 -0
- package/dist/{src/objects → objects}/index.d.ts +1 -0
- package/dist/{src/objects → objects}/index.js +1 -0
- package/dist/permissions.d.ts +46 -0
- package/dist/permissions.js +86 -0
- package/dist/{src/validate-query-params.js → validate-query-params.js} +1 -1
- package/package.json +21 -35
- package/dist/src/css/get-variable-value.d.ts +0 -1
- package/dist/src/css/get-variable-value.js +0 -8
- package/dist/src/css/index.d.ts +0 -1
- package/dist/src/css/index.js +0 -1
- package/dist/src/dates/dates.d.ts +0 -175
- package/dist/src/dates/dates.js +0 -385
- package/dist/src/dates/format.d.ts +0 -27
- package/dist/src/dates/format.js +0 -99
- package/dist/src/dates/index.d.ts +0 -4
- package/dist/src/dates/index.js +0 -4
- package/dist/src/dates/types.d.ts +0 -4
- package/dist/src/dates/types.js +0 -338
- package/dist/src/dates/utils.d.ts +0 -17
- package/dist/src/dates/utils.js +0 -53
- package/dist/src/files/files.d.ts +0 -64
- package/dist/src/files/files.js +0 -152
- package/dist/src/files/utils.d.ts +0 -20
- package/dist/src/files/utils.js +0 -47
- package/dist/src/geo/chunk-line.d.ts +0 -10
- package/dist/src/geo/chunk-line.js +0 -75
- package/dist/src/geo/constants.d.ts +0 -8
- package/dist/src/geo/constants.js +0 -8
- package/dist/src/geo/conversions.d.ts +0 -36
- package/dist/src/geo/conversions.js +0 -79
- package/dist/src/geo/coordinates.d.ts +0 -37
- package/dist/src/geo/coordinates.js +0 -64
- package/dist/src/geo/cut-line-at-length.d.ts +0 -10
- package/dist/src/geo/cut-line-at-length.js +0 -68
- package/dist/src/geo/geojson-collections.d.ts +0 -11
- package/dist/src/geo/geojson-collections.js +0 -29
- package/dist/src/geo/get-geofence-on-point.d.ts +0 -17
- package/dist/src/geo/get-geofence-on-point.js +0 -46
- package/dist/src/geo/index.d.ts +0 -9
- package/dist/src/geo/index.js +0 -9
- package/dist/src/geo/is-point-in-polygon.d.ts +0 -9
- package/dist/src/geo/is-point-in-polygon.js +0 -37
- package/dist/src/geo/measurements.d.ts +0 -42
- package/dist/src/geo/measurements.js +0 -71
- package/dist/src/logs/index.d.ts +0 -1
- package/dist/src/logs/index.js +0 -1
- package/dist/src/logs/logs.d.ts +0 -82
- package/dist/src/logs/logs.js +0 -145
- package/dist/src/math/coefficient-of-variation.d.ts +0 -6
- package/dist/src/math/coefficient-of-variation.js +0 -14
- package/dist/src/math/entropy.d.ts +0 -6
- package/dist/src/math/entropy.js +0 -20
- package/dist/src/math/index.d.ts +0 -3
- package/dist/src/math/index.js +0 -3
- package/dist/src/math/round-number-bias.d.ts +0 -6
- package/dist/src/math/round-number-bias.js +0 -11
- package/dist/src/navigation/index.d.ts +0 -1
- package/dist/src/navigation/index.js +0 -1
- package/dist/src/navigation/keep-url-params.d.ts +0 -8
- package/dist/src/navigation/keep-url-params.js +0 -13
- package/dist/src/nuqs/index.d.ts +0 -1
- package/dist/src/nuqs/index.js +0 -2
- package/dist/src/nuqs/parse-as-array-of-strings.d.ts +0 -1
- package/dist/src/nuqs/parse-as-array-of-strings.js +0 -43
- package/dist/src/permissions.d.ts +0 -46
- package/dist/src/permissions.js +0 -77
- package/dist/src/random/generate-random-number.d.ts +0 -8
- package/dist/src/random/generate-random-number.js +0 -14
- package/dist/src/random/generate-random-string.d.ts +0 -12
- package/dist/src/random/generate-random-string.js +0 -32
- package/dist/src/random/generate-random-token.d.ts +0 -8
- package/dist/src/random/generate-random-token.js +0 -12
- package/dist/src/random/index.d.ts +0 -3
- package/dist/src/random/index.js +0 -3
- package/dist/src/strings/index.d.ts +0 -2
- package/dist/src/strings/index.js +0 -2
- package/dist/src/strings/normalize-string.d.ts +0 -8
- package/dist/src/strings/normalize-string.js +0 -18
- package/dist/src/strings/validation.d.ts +0 -2
- package/dist/src/strings/validation.js +0 -7
- /package/dist/{src/batching → batching}/index.d.ts +0 -0
- /package/dist/{src/batching → batching}/index.js +0 -0
- /package/dist/{src/batching → batching}/perform-in-chunks.d.ts +0 -0
- /package/dist/{src/batching → batching}/perform-in-chunks.js +0 -0
- /package/dist/{src/caching → caching}/cache.d.ts +0 -0
- /package/dist/{src/caching → caching}/cache.js +0 -0
- /package/dist/{src/caching → caching}/index.d.ts +0 -0
- /package/dist/{src/caching → caching}/index.js +0 -0
- /package/dist/{src/generic → generic}/get-value-at-path.d.ts +0 -0
- /package/dist/{src/generic → generic}/get-value-at-path.js +0 -0
- /package/dist/{src/generic → generic}/index.d.ts +0 -0
- /package/dist/{src/generic → generic}/index.js +0 -0
- /package/dist/{src/generic → generic}/set-value-at-path.d.ts +0 -0
- /package/dist/{src/generic → generic}/set-value-at-path.js +0 -0
- /package/dist/{src/http.d.ts → http.d.ts} +0 -0
- /package/dist/{src/objects → objects}/compare-objects.d.ts +0 -0
- /package/dist/{src/objects → objects}/compare-objects.js +0 -0
- /package/dist/{src/objects → objects}/convert-object.d.ts +0 -0
- /package/dist/{src/objects → objects}/convert-object.js +0 -0
- /package/dist/{src/objects → objects}/flatten-object.d.ts +0 -0
- /package/dist/{src/objects → objects}/flatten-object.js +0 -0
- /package/dist/{src/objects → objects}/merge-objects.d.ts +0 -0
- /package/dist/{src/objects → objects}/merge-objects.js +0 -0
- /package/dist/{src/singleton-proxy.d.ts → singleton-proxy.d.ts} +0 -0
- /package/dist/{src/singleton-proxy.js → singleton-proxy.js} +0 -0
- /package/dist/{src/validate-query-params.d.ts → validate-query-params.d.ts} +0 -0
package/dist/src/files/files.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
import { mimeTypes } from '@tmlmobilidade/lib';
|
|
3
|
-
import JSZip from 'jszip';
|
|
4
|
-
import papaparse from 'papaparse';
|
|
5
|
-
import { fetchZipFromUrl, isBrowser, normalizeFileContent, readZipFromFile } from './utils.js';
|
|
6
|
-
/* * */
|
|
7
|
-
export class Files {
|
|
8
|
-
//
|
|
9
|
-
/**
|
|
10
|
-
* Blob to JS File
|
|
11
|
-
*/
|
|
12
|
-
static blobToFile(blob, fileName) {
|
|
13
|
-
return new File([blob], fileName);
|
|
14
|
-
}
|
|
15
|
-
static getFileExtension(fileName) {
|
|
16
|
-
const extension = fileName.split('.').pop();
|
|
17
|
-
if (!extension) {
|
|
18
|
-
throw new Error('File has no extension');
|
|
19
|
-
}
|
|
20
|
-
const mimeType = mimeTypes[extension];
|
|
21
|
-
if (!mimeType) {
|
|
22
|
-
throw new Error(`Unsupported file extension: ${extension}`);
|
|
23
|
-
}
|
|
24
|
-
return extension;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Gets the file extension from a MIME type.
|
|
28
|
-
* @param mimeType The MIME type to get the file extension for.
|
|
29
|
-
* @returns The file extension, or an empty string if not found.
|
|
30
|
-
*/
|
|
31
|
-
static getFileExtensionFromMimeType(mimeType) {
|
|
32
|
-
if (!mimeType)
|
|
33
|
-
return '';
|
|
34
|
-
const extension = Object.keys(mimeTypes).find(key => mimeTypes[key] === mimeType);
|
|
35
|
-
if (!extension)
|
|
36
|
-
return '';
|
|
37
|
-
return extension;
|
|
38
|
-
}
|
|
39
|
-
static getMimeTypeFromFileExtension(fileName) {
|
|
40
|
-
const extension = Files.getFileExtension(fileName);
|
|
41
|
-
return mimeTypes[extension];
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Parses a CSV string into an array of objects using PapaParse.
|
|
45
|
-
* @param csvString - The CSV string to parse
|
|
46
|
-
* @param options - Parse configuration options
|
|
47
|
-
* @param options.header - Whether to interpret first row as field names. Defaults to true.
|
|
48
|
-
* @param options.skipEmptyLines - Whether to skip empty lines in the CSV. Defaults to true.
|
|
49
|
-
* @param options.rest - Additional PapaParse configuration options
|
|
50
|
-
* @returns Promise resolving to array of parsed objects
|
|
51
|
-
* @throws Error if parsing fails with details of parsing errors
|
|
52
|
-
*/
|
|
53
|
-
static async parseCsv(csvString, { header = true, skipEmptyLines = true, ...options }) {
|
|
54
|
-
const parse = papaparse.parse(csvString, { header, skipEmptyLines, ...options });
|
|
55
|
-
if (parse.errors.length > 0) {
|
|
56
|
-
throw new Error(`Failed to parse CSV: ${parse.errors.map(error => `${error.message} [${error.code}]`).join(', ')}`);
|
|
57
|
-
}
|
|
58
|
-
return parse.data;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Reads and extracts a single file from a ZIP archive.
|
|
62
|
-
* @param zipFilePath - The ZIP file to read from, can be a File object (browser), string path (Node.js), or URL
|
|
63
|
-
* @param fileName - The name of the file to extract from the ZIP
|
|
64
|
-
* @param encoding - The encoding to use when reading the file. See JSZip documentation for supported formats.
|
|
65
|
-
* @returns A Promise resolving to the file contents in the specified encoding
|
|
66
|
-
* @throws Error if the file is not found in the ZIP
|
|
67
|
-
*/
|
|
68
|
-
static async readFileFromZip(zipFilePath, fileName, encoding) {
|
|
69
|
-
const zip = await Files.unzip(zipFilePath);
|
|
70
|
-
const file = zip.file(fileName);
|
|
71
|
-
if (!file) {
|
|
72
|
-
throw new Error(`File ${fileName} not found in ZIP`);
|
|
73
|
-
}
|
|
74
|
-
return await file.async(encoding);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Unzips a ZIP file from a File (browser), string path (Node.js), or URL.
|
|
78
|
-
* @param zipFilePath The path, URL, or File object representing the ZIP file to extract.
|
|
79
|
-
* @returns A Promise that resolves to a JSZip instance representing the unzipped contents.
|
|
80
|
-
*/
|
|
81
|
-
static async unzip(zipFilePath) {
|
|
82
|
-
try {
|
|
83
|
-
let data = null;
|
|
84
|
-
if (isBrowser && zipFilePath instanceof File) {
|
|
85
|
-
data = await zipFilePath.arrayBuffer();
|
|
86
|
-
}
|
|
87
|
-
if (typeof zipFilePath === 'string' || zipFilePath instanceof URL) {
|
|
88
|
-
const pathOrUrl = zipFilePath.toString();
|
|
89
|
-
if (isBrowser || pathOrUrl.startsWith('http')) {
|
|
90
|
-
data = await fetchZipFromUrl(pathOrUrl);
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
data = await readZipFromFile(pathOrUrl);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (!data || data.byteLength === 0) {
|
|
97
|
-
throw new Error('ZIP file is empty');
|
|
98
|
-
}
|
|
99
|
-
const zip = await JSZip.loadAsync(data);
|
|
100
|
-
if (Object.keys(zip.files).length === 0) {
|
|
101
|
-
throw new Error('ZIP file contains no files');
|
|
102
|
-
}
|
|
103
|
-
return zip;
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
if (error instanceof Error && error.message.includes('Central Directory')) {
|
|
107
|
-
throw new Error('Invalid or corrupted ZIP file');
|
|
108
|
-
}
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Updates a CSV string with an object.
|
|
114
|
-
* @param csvString - The CSV string to update
|
|
115
|
-
* @param column - The column name to update
|
|
116
|
-
* @param row - The row index to update
|
|
117
|
-
* @param value - The value to update the column with
|
|
118
|
-
* @returns A Promise resolving to the updated CSV string
|
|
119
|
-
*/
|
|
120
|
-
static async updateCsvField(params) {
|
|
121
|
-
let csv = params[0].csvString;
|
|
122
|
-
for (const param of params) {
|
|
123
|
-
const { column, rowIndex, value } = param;
|
|
124
|
-
const data = await this.parseCsv(csv, { header: true });
|
|
125
|
-
const updatedData = data.map((row, index) => (index === rowIndex ? { ...row, [column]: value } : row));
|
|
126
|
-
csv = papaparse.unparse(updatedData, { header: true });
|
|
127
|
-
}
|
|
128
|
-
return csv;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Zips multiple files into a ZIP archive.
|
|
132
|
-
* @param files An object where keys are filenames and values are either File (browser) or Buffer/Uint8Array (Node.js).
|
|
133
|
-
* @returns A Promise resolving to a Uint8Array representing the ZIP file content.
|
|
134
|
-
*/
|
|
135
|
-
static async zip(files) {
|
|
136
|
-
try {
|
|
137
|
-
const zip = new JSZip();
|
|
138
|
-
await Promise.all(Object.entries(files).map(async ([filename, content]) => {
|
|
139
|
-
const fileData = await normalizeFileContent(content);
|
|
140
|
-
zip.file(filename, fileData);
|
|
141
|
-
}));
|
|
142
|
-
const zipContent = await zip.generateAsync({ type: 'uint8array' });
|
|
143
|
-
if (!zipContent || zipContent.length === 0) {
|
|
144
|
-
throw new Error('Failed to generate ZIP: output is empty');
|
|
145
|
-
}
|
|
146
|
-
return zipContent;
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
throw new Error(`Failed to create ZIP archive: ${error.message}`);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare const isBrowser: boolean;
|
|
2
|
-
/**
|
|
3
|
-
* Fetches a ZIP file from a URL and returns it as an ArrayBuffer.
|
|
4
|
-
* @param url The URL of the ZIP file to fetch
|
|
5
|
-
* @returns A Promise that resolves to an ArrayBuffer containing the ZIP file data
|
|
6
|
-
* @throws {Error} If the HTTP request fails or returns a non-200 status code
|
|
7
|
-
*/
|
|
8
|
-
export declare function fetchZipFromUrl(url: string): Promise<ArrayBuffer>;
|
|
9
|
-
/**
|
|
10
|
-
* Reads a ZIP file from the local filesystem and returns it as an ArrayBuffer.
|
|
11
|
-
* @param path The file system path to the ZIP file
|
|
12
|
-
* @returns A Promise that resolves to an ArrayBuffer containing the ZIP file data
|
|
13
|
-
* @throws {Error} If there is an error reading the file
|
|
14
|
-
*/
|
|
15
|
-
export declare function readZipFromFile(path: string): Promise<ArrayBuffer>;
|
|
16
|
-
/**
|
|
17
|
-
* Converts the input file data into an ArrayBuffer or Uint8Array suitable for JSZip.
|
|
18
|
-
* @param content A File (browser) or Buffer/Uint8Array (Node.js)
|
|
19
|
-
*/
|
|
20
|
-
export declare function normalizeFileContent(content: Buffer | File | Uint8Array): Promise<ArrayBuffer | Uint8Array>;
|
package/dist/src/files/utils.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
2
|
-
/**
|
|
3
|
-
* Fetches a ZIP file from a URL and returns it as an ArrayBuffer.
|
|
4
|
-
* @param url The URL of the ZIP file to fetch
|
|
5
|
-
* @returns A Promise that resolves to an ArrayBuffer containing the ZIP file data
|
|
6
|
-
* @throws {Error} If the HTTP request fails or returns a non-200 status code
|
|
7
|
-
*/
|
|
8
|
-
export async function fetchZipFromUrl(url) {
|
|
9
|
-
const response = await fetch(url);
|
|
10
|
-
if (!response.ok) {
|
|
11
|
-
throw new Error(`Failed to fetch ZIP file: HTTP ${response.status} - ${response.statusText}`);
|
|
12
|
-
}
|
|
13
|
-
return await response.arrayBuffer();
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Reads a ZIP file from the local filesystem and returns it as an ArrayBuffer.
|
|
17
|
-
* @param path The file system path to the ZIP file
|
|
18
|
-
* @returns A Promise that resolves to an ArrayBuffer containing the ZIP file data
|
|
19
|
-
* @throws {Error} If there is an error reading the file
|
|
20
|
-
*/
|
|
21
|
-
export async function readZipFromFile(path) {
|
|
22
|
-
if (isBrowser) {
|
|
23
|
-
throw new Error('readZipFromFile is not supported in the browser');
|
|
24
|
-
}
|
|
25
|
-
// Only require fs/promises in Node.js
|
|
26
|
-
const { readFile } = await (Function('return import("fs/promises")')());
|
|
27
|
-
try {
|
|
28
|
-
const buffer = await readFile(path);
|
|
29
|
-
return buffer.buffer;
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
throw new Error(`Failed to read ZIP file: ${err.message}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Converts the input file data into an ArrayBuffer or Uint8Array suitable for JSZip.
|
|
37
|
-
* @param content A File (browser) or Buffer/Uint8Array (Node.js)
|
|
38
|
-
*/
|
|
39
|
-
export async function normalizeFileContent(content) {
|
|
40
|
-
if (isBrowser && content instanceof File) {
|
|
41
|
-
return await content.arrayBuffer();
|
|
42
|
-
}
|
|
43
|
-
if (content instanceof Buffer || content instanceof Uint8Array) {
|
|
44
|
-
return content;
|
|
45
|
-
}
|
|
46
|
-
throw new TypeError('Unsupported file content type for zipping');
|
|
47
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type LineString } from 'geojson';
|
|
2
|
-
/**
|
|
3
|
-
* This function takes a GeoJSON LineString and splits it into equal chunks of a given precision
|
|
4
|
-
* using a custom implementation. This is useful to ensure greater precision when calculating the nearest
|
|
5
|
-
* point on a path, as some paths may have very long "straight" segments with only two points.
|
|
6
|
-
* @param line The LineString to be split into chunks.
|
|
7
|
-
* @param segmentLength The length of each segment in meters.
|
|
8
|
-
* @returns A GeoJSON LineString with the split chunks.
|
|
9
|
-
*/
|
|
10
|
-
export declare function chunkLineByDistance(line: LineString, segmentLength: number): LineString;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
import { toLineStringFromPositions } from './conversions.js';
|
|
3
|
-
import { getDistanceBetweenPositions, interpolatePositions } from './measurements.js';
|
|
4
|
-
/**
|
|
5
|
-
* This function takes a GeoJSON LineString and splits it into equal chunks of a given precision
|
|
6
|
-
* using a custom implementation. This is useful to ensure greater precision when calculating the nearest
|
|
7
|
-
* point on a path, as some paths may have very long "straight" segments with only two points.
|
|
8
|
-
* @param line The LineString to be split into chunks.
|
|
9
|
-
* @param segmentLength The length of each segment in meters.
|
|
10
|
-
* @returns A GeoJSON LineString with the split chunks.
|
|
11
|
-
*/
|
|
12
|
-
export function chunkLineByDistance(line, segmentLength) {
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// Exit early if the line is empty
|
|
16
|
-
if (line.coordinates.length < 2)
|
|
17
|
-
return line;
|
|
18
|
-
//
|
|
19
|
-
// Setup variables to hold the coordinates of the chunked line
|
|
20
|
-
const chunkedLineCoordinates = [];
|
|
21
|
-
//
|
|
22
|
-
// Add the first point to the chunked line
|
|
23
|
-
chunkedLineCoordinates.push(line.coordinates[0]);
|
|
24
|
-
//
|
|
25
|
-
// Loop through the coordinates of the line
|
|
26
|
-
for (let i = 0; i < line.coordinates.length - 1; i++) {
|
|
27
|
-
// Extract the coordinates of the current and the next point
|
|
28
|
-
const [lngA, latA] = line.coordinates[i];
|
|
29
|
-
const [lngB, latB] = line.coordinates[i + 1];
|
|
30
|
-
// Calculate the length of the current segment
|
|
31
|
-
const currentSegmentLength = getDistanceBetweenPositions(line.coordinates[i], line.coordinates[i + 1]);
|
|
32
|
-
// If the current segment length is greater than the desired segment length
|
|
33
|
-
if (currentSegmentLength > segmentLength) {
|
|
34
|
-
// Calculate the number of segments needed to fill the current segment
|
|
35
|
-
const segmentsNeeded = Math.floor(currentSegmentLength / segmentLength);
|
|
36
|
-
// Calculate the length of each chunked segment
|
|
37
|
-
const chunkedSegmentLength = currentSegmentLength / segmentsNeeded;
|
|
38
|
-
// Calculate the remaining distance to be filled
|
|
39
|
-
let remainingDist = segmentLength;
|
|
40
|
-
// Loop through the segments needed
|
|
41
|
-
for (let j = 0; j < segmentsNeeded; j++) {
|
|
42
|
-
// Calculate the ratio of the segment
|
|
43
|
-
const ratio = remainingDist / chunkedSegmentLength;
|
|
44
|
-
// Interpolate the coordinates of the segment
|
|
45
|
-
const interpolated = interpolatePositions([lngA, latA], [lngB, latB], ratio);
|
|
46
|
-
// Add the interpolated coordinates to the chunked line
|
|
47
|
-
chunkedLineCoordinates.push(interpolated);
|
|
48
|
-
// Update the remaining distance to be filled
|
|
49
|
-
remainingDist -= chunkedSegmentLength;
|
|
50
|
-
}
|
|
51
|
-
// Add the last point of the segment to the chunked line
|
|
52
|
-
const lastPoint = line.coordinates[i + 1];
|
|
53
|
-
if (chunkedLineCoordinates[chunkedLineCoordinates.length - 1][0] !== lastPoint[0] || chunkedLineCoordinates[chunkedLineCoordinates.length - 1][1] !== lastPoint[1]) {
|
|
54
|
-
chunkedLineCoordinates.push(lastPoint);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
// If the current segment length is less than or equal to the desired segment length
|
|
59
|
-
// Add the current point to the chunked line
|
|
60
|
-
if (chunkedLineCoordinates[chunkedLineCoordinates.length - 1][0] !== line.coordinates[i][0] || chunkedLineCoordinates[chunkedLineCoordinates.length - 1][1] !== line.coordinates[i][1]) {
|
|
61
|
-
chunkedLineCoordinates.push(line.coordinates[i]);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
//
|
|
66
|
-
// Add the last point of the line to the chunked line
|
|
67
|
-
const lastPoint = line.coordinates[line.coordinates.length - 1];
|
|
68
|
-
if (chunkedLineCoordinates[chunkedLineCoordinates.length - 1][0] !== lastPoint[0] || chunkedLineCoordinates[chunkedLineCoordinates.length - 1][1] !== lastPoint[1]) {
|
|
69
|
-
chunkedLineCoordinates.push(lastPoint);
|
|
70
|
-
}
|
|
71
|
-
//
|
|
72
|
-
// Return the chunked line as a GeoJSON LineString
|
|
73
|
-
return toLineStringFromPositions(chunkedLineCoordinates);
|
|
74
|
-
//
|
|
75
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { type HashedShape } from '@tmlmobilidade/types';
|
|
2
|
-
import { type Feature, type GeoJsonProperties, type LineString, type Point, type Polygon, type Position } from 'geojson';
|
|
3
|
-
/**
|
|
4
|
-
* Converts a list of GTFS shape points into a GeoJSON LineString.
|
|
5
|
-
* @param hashedShape The hashed shape containing GTFS shape points.
|
|
6
|
-
* @returns GeoJSON LineString feature
|
|
7
|
-
*/
|
|
8
|
-
export declare function toLineStringFromHashedShape(hashedShape: HashedShape): LineString;
|
|
9
|
-
/**
|
|
10
|
-
* Creates a new LineString from the given set of coordinates.
|
|
11
|
-
* @param positions An array of coordinate positions for the LineString. Defaults to an empty array.
|
|
12
|
-
* @returns A GeoJSON LineString with the specified coordinates.
|
|
13
|
-
*/
|
|
14
|
-
export declare function toLineStringFromPositions(positions?: Position[]): LineString;
|
|
15
|
-
/**
|
|
16
|
-
* Creates a new Point from the given coordinates.
|
|
17
|
-
* @param position A coordinate position for the Point. Defaults to an empty array.
|
|
18
|
-
* @returns A GeoJSON Point with the specified coordinates.
|
|
19
|
-
*/
|
|
20
|
-
export declare function toPointFromPositions(position?: Position): Point;
|
|
21
|
-
/**
|
|
22
|
-
* Creates a new Feature from the given object and properties.
|
|
23
|
-
* @param object The object to convert to a Feature. Can be a LineString, Point, or Polygon.
|
|
24
|
-
* @param properties Optional properties to attach to the Feature. Defaults to an empty object.
|
|
25
|
-
* @returns A GeoJSON Feature with the specified object and properties.
|
|
26
|
-
*/
|
|
27
|
-
export declare function toFeatureFromObject<T extends LineString | Point | Polygon>(object: T, properties?: GeoJsonProperties): Feature<T>;
|
|
28
|
-
/**
|
|
29
|
-
* Converts a value in kilometers or meters to meters based on a ballpark value.
|
|
30
|
-
* If the ballpark value is greater than 800 meters, it assumes the value is in meters.
|
|
31
|
-
* Otherwise, it assumes the value is in kilometers and converts it to meters.
|
|
32
|
-
* @param value The value to be converted, which can be a number or a string that can be converted to a number.
|
|
33
|
-
* @param ballpark The ballpark value to determine the unit of the value, which can also be a number or a string that can be converted to a number.
|
|
34
|
-
* @returns The converted value in meters.
|
|
35
|
-
*/
|
|
36
|
-
export declare function toMetersFromKilometersOrMeters(value: number | string, ballpark: number | string): number;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
/**
|
|
3
|
-
* Converts a list of GTFS shape points into a GeoJSON LineString.
|
|
4
|
-
* @param hashedShape The hashed shape containing GTFS shape points.
|
|
5
|
-
* @returns GeoJSON LineString feature
|
|
6
|
-
*/
|
|
7
|
-
export function toLineStringFromHashedShape(hashedShape) {
|
|
8
|
-
// Exit if no points are provided
|
|
9
|
-
if (!hashedShape.points?.length)
|
|
10
|
-
return toLineStringFromPositions([]);
|
|
11
|
-
// Sort points by shape_pt_sequence
|
|
12
|
-
const sortedPoints = [...hashedShape.points].sort((a, b) => a.shape_pt_sequence - b.shape_pt_sequence);
|
|
13
|
-
// Create a LineString feature
|
|
14
|
-
const coordinates = sortedPoints.map(p => [Number(p.shape_pt_lon), Number(p.shape_pt_lat)]);
|
|
15
|
-
// Return the LineString feature
|
|
16
|
-
return toLineStringFromPositions(coordinates);
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Creates a new LineString from the given set of coordinates.
|
|
20
|
-
* @param positions An array of coordinate positions for the LineString. Defaults to an empty array.
|
|
21
|
-
* @returns A GeoJSON LineString with the specified coordinates.
|
|
22
|
-
*/
|
|
23
|
-
export function toLineStringFromPositions(positions = []) {
|
|
24
|
-
return {
|
|
25
|
-
coordinates: positions,
|
|
26
|
-
type: 'LineString',
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Creates a new Point from the given coordinates.
|
|
31
|
-
* @param position A coordinate position for the Point. Defaults to an empty array.
|
|
32
|
-
* @returns A GeoJSON Point with the specified coordinates.
|
|
33
|
-
*/
|
|
34
|
-
export function toPointFromPositions(position = []) {
|
|
35
|
-
return {
|
|
36
|
-
coordinates: position,
|
|
37
|
-
type: 'Point',
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Creates a new Feature from the given object and properties.
|
|
42
|
-
* @param object The object to convert to a Feature. Can be a LineString, Point, or Polygon.
|
|
43
|
-
* @param properties Optional properties to attach to the Feature. Defaults to an empty object.
|
|
44
|
-
* @returns A GeoJSON Feature with the specified object and properties.
|
|
45
|
-
*/
|
|
46
|
-
export function toFeatureFromObject(object, properties) {
|
|
47
|
-
return {
|
|
48
|
-
geometry: object,
|
|
49
|
-
properties: properties || {},
|
|
50
|
-
type: 'Feature',
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Converts a value in kilometers or meters to meters based on a ballpark value.
|
|
55
|
-
* If the ballpark value is greater than 800 meters, it assumes the value is in meters.
|
|
56
|
-
* Otherwise, it assumes the value is in kilometers and converts it to meters.
|
|
57
|
-
* @param value The value to be converted, which can be a number or a string that can be converted to a number.
|
|
58
|
-
* @param ballpark The ballpark value to determine the unit of the value, which can also be a number or a string that can be converted to a number.
|
|
59
|
-
* @returns The converted value in meters.
|
|
60
|
-
*/
|
|
61
|
-
export function toMetersFromKilometersOrMeters(value, ballpark) {
|
|
62
|
-
//
|
|
63
|
-
const BALLPARK_THRESHOLD = 800; // meters
|
|
64
|
-
const valueAsNumber = Number(value);
|
|
65
|
-
const ballparkAsNumber = Number(ballpark);
|
|
66
|
-
if (Number.isNaN(valueAsNumber))
|
|
67
|
-
throw new Error('Value must be a number or a string that can be converted to a number.');
|
|
68
|
-
if (Number.isNaN(ballparkAsNumber))
|
|
69
|
-
throw new Error('Ballpark must be a number or a string that can be converted to a number.');
|
|
70
|
-
// If the ballpark is bigger than 800, then the value is in meters
|
|
71
|
-
// Otherwise, the value is in kilometers. This is because it is unlikely
|
|
72
|
-
// that a trip will be smaller than 800 meters, and longer than 800 kilometers.
|
|
73
|
-
if (ballparkAsNumber > BALLPARK_THRESHOLD) {
|
|
74
|
-
return valueAsNumber;
|
|
75
|
-
}
|
|
76
|
-
return valueAsNumber * 1000;
|
|
77
|
-
//
|
|
78
|
-
}
|
|
79
|
-
;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checks if the given latitude value is valid given Portugal limits.
|
|
3
|
-
* @param value The latitude value to check.
|
|
4
|
-
* @returns The clamped latitude value if valid, false otherwise.
|
|
5
|
-
*/
|
|
6
|
-
export declare function isValidLatitude(value: number): false | number;
|
|
7
|
-
/**
|
|
8
|
-
* Checks if the given longitude value is valid given Portugal limits.
|
|
9
|
-
* @param value The longitude value to check.
|
|
10
|
-
* @returns The clamped longitude value if valid, false otherwise.
|
|
11
|
-
*/
|
|
12
|
-
export declare function isValidLongitude(value: number): false | number;
|
|
13
|
-
/**
|
|
14
|
-
* Checks if the given latitude and longitude values form a valid coordinate pair.
|
|
15
|
-
* @param lat The latitude value to check.
|
|
16
|
-
* @param lng The longitude value to check.
|
|
17
|
-
* @returns True if the coordinate pair is valid, false otherwise.
|
|
18
|
-
*/
|
|
19
|
-
export declare function isValidCoordinatePair(lat: number, lng: number): boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Clamps a coordinate value to 6 decimal places.
|
|
22
|
-
* @param value The coordinate value to clamp.
|
|
23
|
-
* @returns The clamped coordinate value.
|
|
24
|
-
*/
|
|
25
|
-
export declare function clampCoordinate(value: number): number;
|
|
26
|
-
/**
|
|
27
|
-
* Parses a coordinate pair string in the following formats:
|
|
28
|
-
* - `lat, lng`
|
|
29
|
-
* - `lat lng` (with a space or a tab)
|
|
30
|
-
* @param input The coordinate pair string to parse.
|
|
31
|
-
* @param clamp Whether to clamp the latitude and longitude values to 6 decimal places.
|
|
32
|
-
* @returns The parsed coordinates as an object, or null if the input is invalid.
|
|
33
|
-
*/
|
|
34
|
-
export declare const parseCoordinatePairString: (input: string, clamp?: boolean) => null | {
|
|
35
|
-
lat: number;
|
|
36
|
-
lng: number;
|
|
37
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
/**
|
|
3
|
-
* Checks if the given latitude value is valid given Portugal limits.
|
|
4
|
-
* @param value The latitude value to check.
|
|
5
|
-
* @returns The clamped latitude value if valid, false otherwise.
|
|
6
|
-
*/
|
|
7
|
-
export function isValidLatitude(value) {
|
|
8
|
-
const hasValue = value !== undefined && value !== null;
|
|
9
|
-
const isWithinPortugal = value >= 36.9 && value <= 42.0;
|
|
10
|
-
if (!hasValue || !isWithinPortugal)
|
|
11
|
-
return false;
|
|
12
|
-
return clampCoordinate(value);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Checks if the given longitude value is valid given Portugal limits.
|
|
16
|
-
* @param value The longitude value to check.
|
|
17
|
-
* @returns The clamped longitude value if valid, false otherwise.
|
|
18
|
-
*/
|
|
19
|
-
export function isValidLongitude(value) {
|
|
20
|
-
const hasValue = value !== undefined && value !== null;
|
|
21
|
-
const isWithinPortugal = value >= -9.5 && value <= -6.0;
|
|
22
|
-
if (!hasValue || !isWithinPortugal)
|
|
23
|
-
return false;
|
|
24
|
-
return clampCoordinate(value);
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Checks if the given latitude and longitude values form a valid coordinate pair.
|
|
28
|
-
* @param lat The latitude value to check.
|
|
29
|
-
* @param lng The longitude value to check.
|
|
30
|
-
* @returns True if the coordinate pair is valid, false otherwise.
|
|
31
|
-
*/
|
|
32
|
-
export function isValidCoordinatePair(lat, lng) {
|
|
33
|
-
const isValidLat = isValidLatitude(lat);
|
|
34
|
-
const isValidLng = isValidLongitude(lng);
|
|
35
|
-
return !!isValidLat && !!isValidLng;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Clamps a coordinate value to 6 decimal places.
|
|
39
|
-
* @param value The coordinate value to clamp.
|
|
40
|
-
* @returns The clamped coordinate value.
|
|
41
|
-
*/
|
|
42
|
-
export function clampCoordinate(value) {
|
|
43
|
-
return parseFloat(value.toFixed(6));
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Parses a coordinate pair string in the following formats:
|
|
47
|
-
* - `lat, lng`
|
|
48
|
-
* - `lat lng` (with a space or a tab)
|
|
49
|
-
* @param input The coordinate pair string to parse.
|
|
50
|
-
* @param clamp Whether to clamp the latitude and longitude values to 6 decimal places.
|
|
51
|
-
* @returns The parsed coordinates as an object, or null if the input is invalid.
|
|
52
|
-
*/
|
|
53
|
-
export const parseCoordinatePairString = (input, clamp = true) => {
|
|
54
|
-
const regex = /^\s*([+-]?\d+(?:\.\d+)?)\s*(?:,|\s)\s*([+-]?\d+(?:\.\d+)?)\s*$/;
|
|
55
|
-
const match = input.match(regex);
|
|
56
|
-
if (!match)
|
|
57
|
-
return null;
|
|
58
|
-
const lat = parseFloat(match[1]);
|
|
59
|
-
const lng = parseFloat(match[2]);
|
|
60
|
-
if (clamp)
|
|
61
|
-
return isValidCoordinatePair(lat, lng) ? { lat: clampCoordinate(lat), lng: clampCoordinate(lng) } : null;
|
|
62
|
-
else
|
|
63
|
-
return isValidCoordinatePair(lat, lng) ? { lat, lng } : null;
|
|
64
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type LineString } from 'geojson';
|
|
2
|
-
/**
|
|
3
|
-
* Cuts a LineString at a specified length.
|
|
4
|
-
* If the line is shorter than the specified length, it returns the entire line.
|
|
5
|
-
* @param line The LineString to cut.
|
|
6
|
-
* @param length The length at which to cut the line, in meters, from the start of the line.
|
|
7
|
-
* @param direction The direction in which to cut the line. If 'forward', it cuts from the start of the line.
|
|
8
|
-
* @returns A new LineString that is cut at the specified length.
|
|
9
|
-
*/
|
|
10
|
-
export declare function cutLineStringAtLength(line: LineString, length: number, direction?: 'forward' | 'reversed'): LineString;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
import { toLineStringFromPositions } from './conversions.js';
|
|
3
|
-
import { getDistanceBetweenPositions, interpolatePositions } from './measurements.js';
|
|
4
|
-
/**
|
|
5
|
-
* Cuts a LineString at a specified length.
|
|
6
|
-
* If the line is shorter than the specified length, it returns the entire line.
|
|
7
|
-
* @param line The LineString to cut.
|
|
8
|
-
* @param length The length at which to cut the line, in meters, from the start of the line.
|
|
9
|
-
* @param direction The direction in which to cut the line. If 'forward', it cuts from the start of the line.
|
|
10
|
-
* @returns A new LineString that is cut at the specified length.
|
|
11
|
-
*/
|
|
12
|
-
export function cutLineStringAtLength(line, length, direction = 'forward') {
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// Return the line if it is empty
|
|
16
|
-
if (line.coordinates.length < 2) {
|
|
17
|
-
return line;
|
|
18
|
-
}
|
|
19
|
-
//
|
|
20
|
-
// Return an empty line if the length is equal to 0
|
|
21
|
-
if (length <= 0) {
|
|
22
|
-
return toLineStringFromPositions([]);
|
|
23
|
-
}
|
|
24
|
-
//
|
|
25
|
-
// Reverse the line if the direction is 'reversed'
|
|
26
|
-
if (direction === 'reversed') {
|
|
27
|
-
line.coordinates = line.coordinates.slice().reverse();
|
|
28
|
-
}
|
|
29
|
-
//
|
|
30
|
-
// Hold the cumulative distance between points
|
|
31
|
-
// and the coordinates of the new line
|
|
32
|
-
let cumulativeLength = 0;
|
|
33
|
-
const newLinePositions = [];
|
|
34
|
-
//
|
|
35
|
-
// Loop through the coordinates of the line
|
|
36
|
-
for (let i = 0; i < line.coordinates.length - 1; i++) {
|
|
37
|
-
// Get the coordinates of the current and the next point
|
|
38
|
-
const coordA = line.coordinates[i];
|
|
39
|
-
const coordB = line.coordinates[i + 1];
|
|
40
|
-
// Calculate the distance between the two points
|
|
41
|
-
const segmentLength = getDistanceBetweenPositions(coordA, coordB);
|
|
42
|
-
// If the current segment length plus the cumulative length
|
|
43
|
-
// extends the desired length of the resulting string
|
|
44
|
-
// then the line should be cut at the interpolation point
|
|
45
|
-
if (cumulativeLength + segmentLength >= length) {
|
|
46
|
-
const remainingLength = length - cumulativeLength;
|
|
47
|
-
const relativePositionOnSegment = remainingLength / segmentLength;
|
|
48
|
-
const interpolated = interpolatePositions(coordA, coordB, relativePositionOnSegment);
|
|
49
|
-
newLinePositions.push(coordA, interpolated);
|
|
50
|
-
return toLineStringFromPositions(newLinePositions);
|
|
51
|
-
}
|
|
52
|
-
// Add the length of the current segment to the
|
|
53
|
-
// cumulative length of the line up until this point
|
|
54
|
-
cumulativeLength += segmentLength;
|
|
55
|
-
// If the cumulative length is already greater than the desired length
|
|
56
|
-
// then the line should be cut at this point. Break the loop now.
|
|
57
|
-
if (cumulativeLength > length)
|
|
58
|
-
break;
|
|
59
|
-
// If the cumulative length is not yet up to the desired length
|
|
60
|
-
// then the current point should be added to the new line
|
|
61
|
-
newLinePositions.push(coordA);
|
|
62
|
-
}
|
|
63
|
-
//
|
|
64
|
-
// If the entire line is shorter than the target length
|
|
65
|
-
newLinePositions.push(line.coordinates[line.coordinates.length - 1]);
|
|
66
|
-
return toLineStringFromPositions(newLinePositions);
|
|
67
|
-
//
|
|
68
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type Feature, type FeatureCollection, type Geometry } from 'geojson';
|
|
2
|
-
/**
|
|
3
|
-
* Creates a base GeoJSON feature collection for the given feature type.
|
|
4
|
-
* @returns A base GeoJSON feature collection with an empty features array.
|
|
5
|
-
*/
|
|
6
|
-
export declare function getBaseGeoJsonFeature<T extends Geometry, K>(type: T['type'], properties?: K): Feature<T, K>;
|
|
7
|
-
/**
|
|
8
|
-
* Creates a base GeoJSON feature collection for the given feature type.
|
|
9
|
-
* @returns A base GeoJSON feature collection with an empty features array.
|
|
10
|
-
*/
|
|
11
|
-
export declare function getBaseGeoJsonFeatureCollection<T extends Geometry, K>(): FeatureCollection<T, K>;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
/**
|
|
3
|
-
* Creates a base GeoJSON feature collection for the given feature type.
|
|
4
|
-
* @returns A base GeoJSON feature collection with an empty features array.
|
|
5
|
-
*/
|
|
6
|
-
export function getBaseGeoJsonFeature(type, properties) {
|
|
7
|
-
const emptyGeometries = {
|
|
8
|
-
GeometryCollection: { geometries: [], type: 'GeometryCollection' },
|
|
9
|
-
LineString: { coordinates: [], type: 'LineString' },
|
|
10
|
-
MultiLineString: { coordinates: [], type: 'MultiLineString' },
|
|
11
|
-
MultiPoint: { coordinates: [], type: 'MultiPoint' },
|
|
12
|
-
MultiPolygon: { coordinates: [], type: 'MultiPolygon' },
|
|
13
|
-
Point: { coordinates: [0, 0], type: 'Point' },
|
|
14
|
-
Polygon: { coordinates: [], type: 'Polygon' },
|
|
15
|
-
};
|
|
16
|
-
return {
|
|
17
|
-
geometry: emptyGeometries[type],
|
|
18
|
-
properties: (properties ?? {}),
|
|
19
|
-
type: 'Feature',
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Creates a base GeoJSON feature collection for the given feature type.
|
|
24
|
-
* @returns A base GeoJSON feature collection with an empty features array.
|
|
25
|
-
*/
|
|
26
|
-
export function getBaseGeoJsonFeatureCollection() {
|
|
27
|
-
return Object.assign({ features: [], type: 'FeatureCollection' });
|
|
28
|
-
}
|
|
29
|
-
;
|