@nshiab/simple-data-analysis-core 0.0.27 → 0.1.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 (107) hide show
  1. package/esm/class/SimpleDB.d.ts +3 -8
  2. package/esm/class/SimpleDB.d.ts.map +1 -1
  3. package/esm/class/SimpleDB.js +8 -10
  4. package/esm/class/SimpleTable.d.ts +29 -48
  5. package/esm/class/SimpleTable.d.ts.map +1 -1
  6. package/esm/class/SimpleTable.js +87 -179
  7. package/esm/helpers/convertForJS.js +1 -1
  8. package/esm/helpers/findGeoColumn.js +2 -2
  9. package/esm/helpers/hasGeometryColumn.js +1 -1
  10. package/esm/helpers/logData.d.ts.map +1 -1
  11. package/esm/helpers/logData.js +7 -2
  12. package/esm/helpers/parseTypes.d.ts +1 -1
  13. package/esm/helpers/parseTypes.d.ts.map +1 -1
  14. package/esm/helpers/parseTypes.js +3 -1
  15. package/esm/helpers/setDbProps.d.ts +1 -1
  16. package/esm/helpers/setDbProps.d.ts.map +1 -1
  17. package/esm/helpers/setDbProps.js +5 -9
  18. package/esm/helpers/unifyColumns.d.ts +0 -2
  19. package/esm/helpers/unifyColumns.d.ts.map +1 -1
  20. package/esm/helpers/unifyColumns.js +2 -6
  21. package/esm/helpers/writeGeoData.d.ts.map +1 -1
  22. package/esm/helpers/writeGeoData.js +11 -41
  23. package/esm/helpers/writeIndexes.d.ts +3 -0
  24. package/esm/helpers/writeIndexes.d.ts.map +1 -0
  25. package/esm/helpers/writeIndexes.js +16 -0
  26. package/esm/methods/bm25.d.ts.map +1 -1
  27. package/esm/methods/bm25.js +1 -1
  28. package/esm/methods/cache.js +1 -1
  29. package/esm/methods/distanceQuery.d.ts.map +1 -1
  30. package/esm/methods/distanceQuery.js +4 -2
  31. package/esm/methods/fuzzyJoin.d.ts.map +1 -1
  32. package/esm/methods/fuzzyJoin.js +1 -6
  33. package/esm/methods/getGeoData.d.ts.map +1 -1
  34. package/esm/methods/getGeoData.js +1 -10
  35. package/esm/methods/join.d.ts.map +1 -1
  36. package/esm/methods/join.js +1 -7
  37. package/esm/methods/joinGeo.d.ts.map +1 -1
  38. package/esm/methods/joinGeo.js +1 -14
  39. package/esm/methods/joinGeoQuery.js +1 -1
  40. package/esm/methods/summarizeQuery.js +1 -1
  41. package/esm/methods/writeGeoDataQuery.js +2 -2
  42. package/package.json +2 -2
  43. package/script/class/SimpleDB.d.ts +3 -8
  44. package/script/class/SimpleDB.d.ts.map +1 -1
  45. package/script/class/SimpleDB.js +8 -10
  46. package/script/class/SimpleTable.d.ts +29 -48
  47. package/script/class/SimpleTable.d.ts.map +1 -1
  48. package/script/class/SimpleTable.js +87 -179
  49. package/script/helpers/convertForJS.js +1 -1
  50. package/script/helpers/findGeoColumn.js +2 -2
  51. package/script/helpers/hasGeometryColumn.js +1 -1
  52. package/script/helpers/logData.d.ts.map +1 -1
  53. package/script/helpers/logData.js +7 -2
  54. package/script/helpers/parseTypes.d.ts +1 -1
  55. package/script/helpers/parseTypes.d.ts.map +1 -1
  56. package/script/helpers/parseTypes.js +3 -1
  57. package/script/helpers/setDbProps.d.ts +1 -1
  58. package/script/helpers/setDbProps.d.ts.map +1 -1
  59. package/script/helpers/setDbProps.js +5 -9
  60. package/script/helpers/unifyColumns.d.ts +0 -2
  61. package/script/helpers/unifyColumns.d.ts.map +1 -1
  62. package/script/helpers/unifyColumns.js +2 -6
  63. package/script/helpers/writeGeoData.d.ts.map +1 -1
  64. package/script/helpers/writeGeoData.js +11 -41
  65. package/script/helpers/writeIndexes.d.ts +3 -0
  66. package/script/helpers/writeIndexes.d.ts.map +1 -0
  67. package/script/helpers/writeIndexes.js +19 -0
  68. package/script/methods/bm25.d.ts.map +1 -1
  69. package/script/methods/bm25.js +1 -1
  70. package/script/methods/cache.js +1 -1
  71. package/script/methods/distanceQuery.d.ts.map +1 -1
  72. package/script/methods/distanceQuery.js +4 -2
  73. package/script/methods/fuzzyJoin.d.ts.map +1 -1
  74. package/script/methods/fuzzyJoin.js +1 -6
  75. package/script/methods/getGeoData.d.ts.map +1 -1
  76. package/script/methods/getGeoData.js +1 -10
  77. package/script/methods/join.d.ts.map +1 -1
  78. package/script/methods/join.js +1 -7
  79. package/script/methods/joinGeo.d.ts.map +1 -1
  80. package/script/methods/joinGeo.js +1 -14
  81. package/script/methods/joinGeoQuery.js +1 -1
  82. package/script/methods/summarizeQuery.js +1 -1
  83. package/script/methods/writeGeoDataQuery.js +2 -2
  84. package/esm/helpers/getProjection.d.ts +0 -3
  85. package/esm/helpers/getProjection.d.ts.map +0 -1
  86. package/esm/helpers/getProjection.js +0 -25
  87. package/esm/helpers/getProjectionParquet.d.ts +0 -3
  88. package/esm/helpers/getProjectionParquet.d.ts.map +0 -1
  89. package/esm/helpers/getProjectionParquet.js +0 -24
  90. package/esm/helpers/shouldFlipBeforeExport.d.ts +0 -2
  91. package/esm/helpers/shouldFlipBeforeExport.d.ts.map +0 -1
  92. package/esm/helpers/shouldFlipBeforeExport.js +0 -3
  93. package/esm/helpers/writeProjectionsAndIndexes.d.ts +0 -3
  94. package/esm/helpers/writeProjectionsAndIndexes.d.ts.map +0 -1
  95. package/esm/helpers/writeProjectionsAndIndexes.js +0 -29
  96. package/script/helpers/getProjection.d.ts +0 -3
  97. package/script/helpers/getProjection.d.ts.map +0 -1
  98. package/script/helpers/getProjection.js +0 -31
  99. package/script/helpers/getProjectionParquet.d.ts +0 -3
  100. package/script/helpers/getProjectionParquet.d.ts.map +0 -1
  101. package/script/helpers/getProjectionParquet.js +0 -30
  102. package/script/helpers/shouldFlipBeforeExport.d.ts +0 -2
  103. package/script/helpers/shouldFlipBeforeExport.d.ts.map +0 -1
  104. package/script/helpers/shouldFlipBeforeExport.js +0 -6
  105. package/script/helpers/writeProjectionsAndIndexes.d.ts +0 -3
  106. package/script/helpers/writeProjectionsAndIndexes.d.ts.map +0 -1
  107. package/script/helpers/writeProjectionsAndIndexes.js +0 -32
@@ -62,7 +62,6 @@ import summarize from "../methods/summarize.js";
62
62
  import correlations from "../methods/correlations.js";
63
63
  import linearRegressions from "../methods/linearRegressions.js";
64
64
  import joinGeo from "../methods/joinGeo.js";
65
- import getProjection from "../helpers/getProjection.js";
66
65
  import cache from "../methods/cache.js";
67
66
  import camelCase from "../helpers/camelCase.js";
68
67
  import formatNumber from "../helpers/formatNumber.js";
@@ -85,7 +84,6 @@ import getIdenticalColumns from "../helpers/getIdenticalColumns.js";
85
84
  import capitalizeQuery from "../methods/capitalizeQuery.js";
86
85
  import truncateQuery from "../methods/truncateQuery.js";
87
86
  import padQuery from "../methods/padQuery.js";
88
- import getProjectionParquet from "../helpers/getProjectionParquet.js";
89
87
  import hasGeometryColumn from "../helpers/hasGeometryColumn.js";
90
88
  import unifyColumns from "../helpers/unifyColumns.js";
91
89
  import accumulateQuery from "../helpers/accumulateQuery.js";
@@ -147,7 +145,6 @@ export default class SimpleTable extends Simple {
147
145
  * Creates an instance of SimpleTable.
148
146
  *
149
147
  * @param name - The name of the table.
150
- * @param projections - An object mapping column names to their geospatial projections.
151
148
  * @param simpleDB - The SimpleDB instance that this table belongs to.
152
149
  * @param options - An optional object with configuration options:
153
150
  * @param options.debug - A boolean indicating whether to enable debug mode.
@@ -156,7 +153,7 @@ export default class SimpleTable extends Simple {
156
153
  * @param options.types - A boolean indicating whether to include data types when logging a table.
157
154
  * @category Constructor
158
155
  */
159
- constructor(name, projections, simpleDB, options = {}) {
156
+ constructor(name, simpleDB, options = {}) {
160
157
  super(options);
161
158
  /**
162
159
  * Name of the table in the database.
@@ -170,19 +167,7 @@ export default class SimpleTable extends Simple {
170
167
  value: void 0
171
168
  });
172
169
  /**
173
- * The projections of the geospatial data, if any.
174
- *
175
- * @defaultValue `{}`
176
- * @category Properties
177
- */
178
- Object.defineProperty(this, "projections", {
179
- enumerable: true,
180
- configurable: true,
181
- writable: true,
182
- value: void 0
183
- });
184
- /**
185
- * The indexes of the table.
170
+ * The indexes of the table, if any.
186
171
  *
187
172
  * @defaultValue `[]`
188
173
  * @category Properties
@@ -194,7 +179,6 @@ export default class SimpleTable extends Simple {
194
179
  value: void 0
195
180
  });
196
181
  this.name = name;
197
- this.projections = projections;
198
182
  this.sdb = simpleDB;
199
183
  this.runQuery = runQuery;
200
184
  this.indexes = [];
@@ -242,8 +226,9 @@ export default class SimpleTable extends Simple {
242
226
  let spatial = "";
243
227
  if (Object.values(types)
244
228
  .map((d) => d.toLowerCase())
245
- .includes("geometry")) {
246
- spatial = "INSTALL spatial; LOAD spatial;\n";
229
+ .some((d) => d.startsWith("geometry"))) {
230
+ spatial =
231
+ "INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;\n";
247
232
  }
248
233
  await queryDB(this, `${spatial}CREATE OR REPLACE TABLE "${this.name}" (${Object.keys(types)
249
234
  .map((d) => `"${d}" ${parseType(types[d])}`)
@@ -398,12 +383,10 @@ export default class SimpleTable extends Simple {
398
383
  }
399
384
  /**
400
385
  * Loads geospatial data from an external file or URL into the table.
401
- * The coordinates of files or URLs ending with `.json` or `.geojson` are automatically flipped to `[latitude, longitude]` axis order.
402
386
  *
403
387
  * @param file - The URL or absolute path to the external file containing the geospatial data.
404
388
  * @param options - An optional object with configuration options:
405
- * @param options.toWGS84 - If `true`, the method will attempt to reproject the data to WGS84 with `[latitude, longitude]` axis order. If the file is `.json` or `.geojson`, coordinates are automatically flipped, and this option has no additional effect. Defaults to `false`.
406
- * @param options.from - An optional string specifying the original projection of the data, if the method is unable to detect it automatically.
389
+ * @param options.toWGS84 - If `true`, the method will attempt to reproject the data to WGS84.
407
390
  * @returns A promise that resolves to the SimpleTable instance after the geospatial data has been loaded.
408
391
  * @category Geospatial
409
392
  *
@@ -434,7 +417,7 @@ export default class SimpleTable extends Simple {
434
417
  async loadGeoData(file, options = {}) {
435
418
  const fileExtension = getExtension(file);
436
419
  if (fileExtension === "geoparquet" || fileExtension === "parquet") {
437
- await queryDB(this, `INSTALL spatial; LOAD spatial;${file.toLowerCase().includes("http")
420
+ await queryDB(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;${file.toLowerCase().includes("http")
438
421
  ? " INSTALL https; LOAD https;"
439
422
  : ""}
440
423
  CREATE OR REPLACE TABLE "${this.name}" AS SELECT * FROM read_parquet('${cleanPath(file)}');`, mergeOptions(this, {
@@ -442,32 +425,21 @@ export default class SimpleTable extends Simple {
442
425
  method: "loadGeoData()",
443
426
  parameters: { file, options },
444
427
  }));
445
- this.projections = await getProjectionParquet(this, file);
446
- if (options.toWGS84) {
447
- console.log("\nThis file is a parquet. Option toWGS84 has no effect. Use the .reproject() method instead.\n");
448
- }
449
428
  }
450
429
  else {
451
- await queryDB(this, `INSTALL spatial; LOAD spatial;${file.toLowerCase().includes("http")
430
+ await queryDB(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;${file.toLowerCase().includes("http")
452
431
  ? " INSTALL https; LOAD https;"
453
432
  : ""}
454
- CREATE OR REPLACE TABLE "${this.name}" AS SELECT * FROM ST_Read('${file}');`, mergeOptions(this, {
433
+ CREATE OR REPLACE TABLE "${this.name}" AS SELECT * EXCLUDE OGC_FID FROM ST_Read('${file}');`, mergeOptions(this, {
455
434
  table: this.name,
456
435
  method: "loadGeoData()",
457
436
  parameters: { file, options },
458
437
  }));
459
- // column storing geometries is geom by default
460
- this.projections["geom"] = await getProjection(this.sdb, file);
461
- const extension = getExtension(file);
462
- if (extension === "json" || extension === "geojson") {
463
- await this.flipCoordinates("geom"); // column storing geometries
464
- this.projections["geom"] = "+proj=latlong +datum=WGS84 +no_defs";
465
- if (options.toWGS84) {
466
- console.log("This file is a json or geojson. Option toWGS84 has no effect.");
467
- }
468
- }
469
- else if (options.toWGS84) {
470
- await this.reproject("WGS84", { ...options, column: "geom" }); // column storing geometries is geom by default
438
+ }
439
+ if (options.toWGS84) {
440
+ const proj = await this.getProjection("geom");
441
+ if (proj !== "EPSG:4326") {
442
+ await this.reproject("EPSG:4326");
471
443
  }
472
444
  }
473
445
  return this;
@@ -759,9 +731,8 @@ export default class SimpleTable extends Simple {
759
731
  : [tablesToInsert];
760
732
  if (!await this.sdb.hasTable(this.name)) {
761
733
  await this.setTypes((await array[0].getTypes()));
762
- this.projections = structuredClone(array[0].projections);
763
734
  }
764
- // Checking columns, types and projections
735
+ // Checking columns, types
765
736
  if (!options.unifyColumns) {
766
737
  const thisColumns = (await this.getColumns()).sort().join(",");
767
738
  for (const table of array) {
@@ -773,27 +744,22 @@ export default class SimpleTable extends Simple {
773
744
  }
774
745
  const allTables = [this, ...array];
775
746
  const allTypes = {};
776
- const allProjections = {};
777
747
  for (const table of allTables) {
778
748
  const types = await table.getTypes();
779
749
  for (const key in types) {
780
750
  if (!allTypes[key]) {
781
751
  allTypes[key] = types[key];
782
- allProjections[key] = table.projections[key];
783
752
  }
784
753
  else {
785
754
  if (allTypes[key] !== types[key]) {
786
755
  throw new Error(`The column ${key} has different types in the tables.`);
787
756
  }
788
- else if (allProjections[key] !== table.projections[key]) {
789
- throw new Error(`The column ${key} has different projections in the tables.`);
790
- }
791
757
  }
792
758
  }
793
759
  }
794
760
  let columnsAdded = {};
795
761
  if (options.unifyColumns) {
796
- columnsAdded = await unifyColumns(allTables, allTypes, allProjections);
762
+ columnsAdded = await unifyColumns(allTables, allTypes);
797
763
  }
798
764
  await queryDB(this, array
799
765
  .map((tableToInsert) => `INSERT INTO "${this.name}" BY NAME SELECT * FROM "${tableToInsert.name}";`)
@@ -892,29 +858,16 @@ export default class SimpleTable extends Simple {
892
858
  const columns = typeof nameOrOptions === "object" && nameOrOptions.columns
893
859
  ? stringToArray(nameOrOptions.columns)
894
860
  : [];
895
- // Dealing with projections
896
- const clonedProjections = structuredClone(this.projections);
897
- let newProjections = {};
898
- if (columns.length > 0) {
899
- for (const col of columns) {
900
- if (clonedProjections[col]) {
901
- newProjections[col] = clonedProjections[col];
902
- }
903
- }
904
- }
905
- else {
906
- newProjections = clonedProjections;
907
- }
908
861
  // Delegate to sdb.newTable() so subclasses using tableClass work correctly.
909
862
  let clonedTable;
910
863
  const options = typeof nameOrOptions === "string"
911
864
  ? { outputTable: nameOrOptions }
912
865
  : nameOrOptions;
913
866
  if (typeof options.outputTable === "string") {
914
- clonedTable = this.sdb.newTable(options.outputTable, newProjections);
867
+ clonedTable = this.sdb.newTable(options.outputTable);
915
868
  }
916
869
  else {
917
- clonedTable = this.sdb.newTable(undefined, newProjections);
870
+ clonedTable = this.sdb.newTable(undefined);
918
871
  }
919
872
  await queryDB(this, cloneQuery(this.name, clonedTable.name, columns, options), mergeOptions(this, {
920
873
  table: clonedTable.name,
@@ -945,9 +898,6 @@ export default class SimpleTable extends Simple {
945
898
  method: "cloneColumn()",
946
899
  parameters: { originalColumn, newColumn },
947
900
  }));
948
- if (typeof this.projections[originalColumn] === "string") {
949
- this.projections[newColumn] = this.projections[originalColumn];
950
- }
951
901
  }
952
902
  /**
953
903
  * Clones a column in the table and offsets its values by a specified number of rows.
@@ -1012,9 +962,6 @@ export default class SimpleTable extends Simple {
1012
962
  method: "cloneColumnWithOffset()",
1013
963
  parameters: { originalColumn, newColumn },
1014
964
  }));
1015
- if (typeof this.projections[originalColumn] === "string") {
1016
- this.projections[newColumn] = this.projections[originalColumn];
1017
- }
1018
965
  }
1019
966
  /**
1020
967
  * Fills `NULL` values in specified columns. By default, each `NULL` is replaced with the last non-`NULL` value from the preceding row. When `interpolate` is `true`, `NULL` values are replaced using linear interpolation (or extrapolation at the ends). Pass `interpolateBy` with a real numeric or date column name to use it as the X-axis, so that interpolated values are proportional to the actual distances between X-axis values rather than treating every row as equidistant. When `interpolateBy` is set, `interpolate` is automatically assumed `true`.
@@ -1260,7 +1207,7 @@ export default class SimpleTable extends Simple {
1260
1207
  parameters: { count, options },
1261
1208
  }));
1262
1209
  if (typeof options.outputTable === "string") {
1263
- return this.sdb.newTable(options.outputTable, this.projections);
1210
+ return this.sdb.newTable(options.outputTable);
1264
1211
  }
1265
1212
  else {
1266
1213
  return this;
@@ -1533,15 +1480,6 @@ export default class SimpleTable extends Simple {
1533
1480
  method: "renameColumns()",
1534
1481
  parameters: { names },
1535
1482
  }));
1536
- // Taking care of projections
1537
- const types = await this.getTypes();
1538
- for (let i = 0; i < newNames.length; i++) {
1539
- if (types[newNames[i]] === "GEOMETRY") {
1540
- const projection = this.projections[oldNames[i]];
1541
- delete this.projections[oldNames[i]];
1542
- this.projections[newNames[i]] = projection;
1543
- }
1544
- }
1545
1483
  }
1546
1484
  /**
1547
1485
  * Cleans column names by removing non-alphanumeric characters and formatting them to camel case.
@@ -1758,12 +1696,6 @@ export default class SimpleTable extends Simple {
1758
1696
  method: "removeColumns()",
1759
1697
  parameters: { columns },
1760
1698
  }));
1761
- // Taking care of projections
1762
- for (const col of cols) {
1763
- if (Object.prototype.hasOwnProperty.call(this.projections, col)) {
1764
- delete this.projections[col];
1765
- }
1766
- }
1767
1699
  }
1768
1700
  /**
1769
1701
  * Adds a new column to the table based on a specified data type (JavaScript or SQL types) and a SQL definition.
@@ -1772,7 +1704,6 @@ export default class SimpleTable extends Simple {
1772
1704
  * @param type - The data type for the new column. Can be a JavaScript type (e.g., `"number"`, `"string"`) or a SQL type (e.g., `"integer"`, `"varchar"`).
1773
1705
  * @param definition - A SQL expression defining how the values for the new column should be computed (e.g., `"column1 + column2"`, `"ST_Centroid(geom_column)"`).
1774
1706
  * @param options - An optional object with configuration options:
1775
- * @param options.projection - Required if the new column stores geometries. Specifies the geospatial projection of the new geometry column. You can reuse the projection of an existing geometry column (available in `table.projections`).
1776
1707
  * @returns A promise that resolves when the new column has been added.
1777
1708
  * @category Column Operations
1778
1709
  *
@@ -1785,28 +1716,21 @@ export default class SimpleTable extends Simple {
1785
1716
  * @example
1786
1717
  * ```ts
1787
1718
  * // Add a new geometry column 'centroid' using the centroid of an existing 'country' geometry column
1788
- * // The projection of the new 'centroid' column is set to be the same as 'country'.
1789
- * await table.addColumn("centroid", "geometry", `ST_Centroid("country")`, {
1790
- * projection: table.projections.country,
1791
- * });
1719
+ * await table.addColumn("centroid", "geometry('EPSG:4326')", `ST_Centroid("country")`);
1792
1720
  * ```
1793
1721
  */
1794
- async addColumn(newColumn, type, definition, options = {}) {
1722
+ async addColumn(newColumn, type, definition) {
1795
1723
  const newType = parseType(type);
1724
+ // let spatial = "";
1725
+ // if (newType.toLowerCase().includes("geometry")) {
1726
+ // spatial = "INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;";
1727
+ // }
1796
1728
  await queryDB(this, `ALTER TABLE "${this.name}" ADD "${newColumn}" ${newType};
1797
1729
  UPDATE "${this.name}" SET "${newColumn}" = ${definition}`, mergeOptions(this, {
1798
1730
  table: this.name,
1799
1731
  method: "addColumn()",
1800
1732
  parameters: { newColumn, type, definition },
1801
1733
  }));
1802
- if (newType === "GEOMETRY") {
1803
- if (typeof options.projection === "string") {
1804
- this.projections[newColumn] = options.projection;
1805
- }
1806
- else {
1807
- throw new Error("You are creating a new column storing geometries. You must specify a projection. See examples in documentation.");
1808
- }
1809
- }
1810
1734
  }
1811
1735
  /**
1812
1736
  * Adds a new column to the table containing the row number, starting at 0 (like an index).
@@ -1886,15 +1810,10 @@ export default class SimpleTable extends Simple {
1886
1810
  method: "crossJoin()",
1887
1811
  parameters: { rightTable, options },
1888
1812
  }));
1889
- const allProjections = {
1890
- ...this.projections,
1891
- ...rightTable.projections,
1892
- };
1893
1813
  if (typeof options.outputTable === "string") {
1894
- return this.sdb.newTable(options.outputTable, allProjections);
1814
+ return this.sdb.newTable(options.outputTable);
1895
1815
  }
1896
1816
  else {
1897
- this.projections = allProjections;
1898
1817
  return this;
1899
1818
  }
1900
1819
  }
@@ -3029,7 +2948,7 @@ export default class SimpleTable extends Simple {
3029
2948
  }
3030
2949
  await summarize(this, options);
3031
2950
  if (typeof options.outputTable === "string") {
3032
- return this.sdb.newTable(options.outputTable, this.projections);
2951
+ return this.sdb.newTable(options.outputTable);
3033
2952
  }
3034
2953
  else {
3035
2954
  return this;
@@ -3171,7 +3090,7 @@ export default class SimpleTable extends Simple {
3171
3090
  }
3172
3091
  await correlations(this, options);
3173
3092
  if (typeof options.outputTable === "string") {
3174
- return this.sdb.newTable(options.outputTable, this.projections);
3093
+ return this.sdb.newTable(options.outputTable);
3175
3094
  }
3176
3095
  else {
3177
3096
  return this;
@@ -3228,7 +3147,7 @@ export default class SimpleTable extends Simple {
3228
3147
  }
3229
3148
  await linearRegressions(this, options);
3230
3149
  if (typeof options.outputTable === "string") {
3231
- return this.sdb.newTable(options.outputTable, this.projections);
3150
+ return this.sdb.newTable(options.outputTable);
3232
3151
  }
3233
3152
  else {
3234
3153
  return this;
@@ -4083,7 +4002,7 @@ export default class SimpleTable extends Simple {
4083
4002
  }
4084
4003
  // GEOSPATIAL
4085
4004
  /**
4086
- * Creates point geometries from longitude and latitude columns. The geometries will have `[latitude, longitude]` axis order.
4005
+ * Creates point geometries from latitude and longitude columns.
4087
4006
  *
4088
4007
  * @param columnLat - The name of the column storing the latitude values.
4089
4008
  * @param columnLon - The name of the column storing the longitude values.
@@ -4099,13 +4018,12 @@ export default class SimpleTable extends Simple {
4099
4018
  */
4100
4019
  async points(columnLat, columnLon, newColumn) {
4101
4020
  await queryDB(this, (await this.getColumns()).includes(newColumn)
4102
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Point2D("${columnLat}", "${columnLon}")`
4103
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD COLUMN "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Point2D("${columnLat}", "${columnLon}")`, mergeOptions(this, {
4021
+ ? `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; UPDATE "${this.name}" SET "${newColumn}" = ST_Point2D("${columnLon}", "${columnLat}")`
4022
+ : `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD COLUMN "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Point2D("${columnLon}", "${columnLat}")`, mergeOptions(this, {
4104
4023
  table: this.name,
4105
4024
  method: "points()",
4106
4025
  parameters: { columnLat, columnLon, newColumn },
4107
4026
  }));
4108
- this.projections[newColumn] = "+proj=latlong +datum=WGS84 +no_defs";
4109
4027
  }
4110
4028
  /**
4111
4029
  * Adds a column with boolean values indicating the validity of geometries.
@@ -4262,7 +4180,7 @@ export default class SimpleTable extends Simple {
4262
4180
  }
4263
4181
  /**
4264
4182
  * Flips the coordinate order of geometries in a specified column (e.g., from `[lon, lat]` to `[lat, lon]` or vice-versa).
4265
- * **Warning:** This method should be used with caution as it directly manipulates coordinate order and can affect the accuracy of geospatial operations if not used correctly. It also messes up with the projections stored in `table.projections`.
4183
+ * **Warning:** This method should be used with caution as it directly manipulates coordinate order and can affect the accuracy of geospatial operations if not used correctly.
4266
4184
  *
4267
4185
  * @param column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.
4268
4186
  * @returns A promise that resolves when the coordinates have been flipped.
@@ -4321,11 +4239,9 @@ export default class SimpleTable extends Simple {
4321
4239
  }
4322
4240
  /**
4323
4241
  * Reprojects the geometries in a specified column to another Spatial Reference System (SRS).
4324
- * If reprojecting to WGS84 (`"WGS84"` or `"EPSG:4326"`), the resulting geometries will have `[latitude, longitude]` axis order.
4325
4242
  *
4326
4243
  * @param to - The target SRS (e.g., `"EPSG:3347"`, `"WGS84"`).
4327
4244
  * @param options - An optional object with configuration options:
4328
- * @param options.from - The original projection of the geometries. If omitted, the method attempts to automatically detect it. Provide this option if auto-detection fails.
4329
4245
  * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.
4330
4246
  * @returns A promise that resolves when the geometries have been reprojected.
4331
4247
  * @category Geospatial
@@ -4338,43 +4254,24 @@ export default class SimpleTable extends Simple {
4338
4254
  *
4339
4255
  * @example
4340
4256
  * ```ts
4341
- * // Reproject geometries from EPSG:4326 to EPSG:3347, specifying the original projection
4342
- * await table.reproject("EPSG:3347", { from: "EPSG:4326" });
4343
- * ```
4344
- *
4345
- * @example
4346
- * ```ts
4347
4257
  * // Reproject geometries in a specific column named 'myGeom' to EPSG:3347
4348
- * await table.reproject("EPSG:3347", { column: "myGeom", from: "EPSG:4326" });
4258
+ * await table.reproject("EPSG:3347", { column: "myGeom" });
4349
4259
  * ```
4350
4260
  */
4351
4261
  async reproject(to, options = {}) {
4262
+ const cleanedTo = to.replace("WGS84", "EPSG:4326");
4352
4263
  const column = typeof options.column === "string"
4353
4264
  ? options.column
4354
4265
  : await findGeoColumn(this);
4355
- const from = options.from ?? this.projections[column];
4356
- if (typeof from !== "string" || from === "") {
4357
- throw new Error("Method reproject can't determine the original projection. Use the option 'from' to provide one.");
4358
- }
4359
- if (from === "+proj=latlong +datum=WGS84 +no_defs") {
4360
- await this.flipCoordinates(column);
4361
- }
4362
- if (to.toUpperCase() === "WGS84" || to.toUpperCase() === "EPSG:4326") {
4363
- to = "+proj=latlong +datum=WGS84 +no_defs";
4364
- }
4365
- await queryDB(this, `UPDATE "${this.name}" SET "${column}" = ST_Transform("${column}", '${from}', '${to}')`, mergeOptions(this, {
4266
+ await queryDB(this, `ALTER TABLE "${this.name}" ADD COLUMN "${column}_reprojected" GEOMETRY('${cleanedTo}'); UPDATE "${this.name}" SET "${column}_reprojected" = ST_Transform("${column}", '${cleanedTo}'); ALTER TABLE "${this.name}" DROP COLUMN "${column}"; ALTER TABLE "${this.name}" RENAME COLUMN "${column}_reprojected" TO "${column}";`, mergeOptions(this, {
4366
4267
  table: this.name,
4367
4268
  method: "reproject()",
4368
4269
  parameters: { column, to },
4369
4270
  }));
4370
- this.projections[column] = to;
4371
- if (this.projections[column] === "+proj=latlong +datum=WGS84 +no_defs") {
4372
- await this.flipCoordinates(column);
4373
- }
4374
4271
  }
4375
4272
  /**
4376
4273
  * Computes the area of geometries in square meters (`"m2"`) or optionally square kilometers (`"km2"`).
4377
- * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4274
+ * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
4378
4275
  *
4379
4276
  * @param newColumn - The name of the new column where the computed areas will be stored.
4380
4277
  * @param options - An optional object with configuration options:
@@ -4413,7 +4310,7 @@ export default class SimpleTable extends Simple {
4413
4310
  }
4414
4311
  /**
4415
4312
  * Computes the length of line geometries in meters (`"m"`) or optionally kilometers (`"km"`).
4416
- * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4313
+ * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
4417
4314
  *
4418
4315
  * @param newColumn - The name of the new column where the computed lengths will be stored.
4419
4316
  * @param options - An optional object with configuration options:
@@ -4452,7 +4349,7 @@ export default class SimpleTable extends Simple {
4452
4349
  }
4453
4350
  /**
4454
4351
  * Computes the perimeter of polygon geometries in meters (`"m"`) or optionally kilometers (`"km"`).
4455
- * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4352
+ * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
4456
4353
  *
4457
4354
  * @param newColumn - The name of the new column where the computed perimeters will be stored.
4458
4355
  * @param options - An optional object with configuration options:
@@ -4516,14 +4413,14 @@ export default class SimpleTable extends Simple {
4516
4413
  const column = typeof options.column === "string"
4517
4414
  ? options.column
4518
4415
  : await findGeoColumn(this);
4416
+ const proj = await this.getProjection(column);
4519
4417
  await queryDB(this, (await this.getColumns()).includes(newColumn)
4520
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Buffer("${column}", ${distance})`
4521
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Buffer("${column}", ${distance})`, mergeOptions(this, {
4418
+ ? `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; UPDATE "${this.name}" SET "${newColumn}" = ST_Buffer("${column}", ${distance})`
4419
+ : `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY('${proj}'); UPDATE "${this.name}" SET "${newColumn}" = ST_Buffer("${column}", ${distance})`, mergeOptions(this, {
4522
4420
  table: this.name,
4523
4421
  method: "buffer()",
4524
4422
  parameters: { column, newColumn, distance },
4525
4423
  }));
4526
- this.projections[newColumn] = this.projections[column];
4527
4424
  }
4528
4425
  /**
4529
4426
  * Merges the data of this table (considered the left table) with another table (the right table) based on a spatial relationship.
@@ -4601,17 +4498,13 @@ export default class SimpleTable extends Simple {
4601
4498
  * ```
4602
4499
  */
4603
4500
  async intersection(column1, column2, newColumn) {
4604
- if (this.projections[column1] !== this.projections[column2]) {
4605
- throw new Error(`${column1} and ${column2} don't have the same projection.\n${column1}: ${this.projections[column1]}\n${column2}: ${this.projections[column2]}`);
4606
- }
4607
4501
  await queryDB(this, (await this.getColumns()).includes(newColumn)
4608
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Intersection("${column1}", "${column2}")`
4609
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Intersection("${column1}", "${column2}")`, mergeOptions(this, {
4502
+ ? `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; UPDATE "${this.name}" SET "${newColumn}" = ST_Intersection("${column1}", "${column2}")`
4503
+ : `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Intersection("${column1}", "${column2}")`, mergeOptions(this, {
4610
4504
  table: this.name,
4611
4505
  method: "intersection()",
4612
4506
  parameters: { column1, column2, newColumn },
4613
4507
  }));
4614
- this.projections[newColumn] = this.projections[column1];
4615
4508
  }
4616
4509
  /**
4617
4510
  * Removes the intersection of two geometries from the first geometry, effectively computing the geometric difference.
@@ -4629,9 +4522,6 @@ export default class SimpleTable extends Simple {
4629
4522
  * ```
4630
4523
  */
4631
4524
  async removeIntersection(column1, column2, newColumn) {
4632
- if (this.projections[column1] !== this.projections[column2]) {
4633
- throw new Error(`${column1} and ${column2} don't have the same projection.\n${column1}: ${this.projections[column1]}\n${column2}: ${this.projections[column2]}`);
4634
- }
4635
4525
  await queryDB(this, (await this.getColumns()).includes(newColumn)
4636
4526
  ? `UPDATE "${this.name}" SET "${newColumn}" = ST_Difference("${column1}", "${column2}")`
4637
4527
  : `ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Difference("${column1}", "${column2}")`, mergeOptions(this, {
@@ -4639,7 +4529,6 @@ export default class SimpleTable extends Simple {
4639
4529
  method: "removeIntersection()",
4640
4530
  parameters: { column1, column2, newColumn },
4641
4531
  }));
4642
- this.projections[newColumn] = this.projections[column1];
4643
4532
  }
4644
4533
  /**
4645
4534
  * Fills holes in polygon geometries.
@@ -4728,21 +4617,17 @@ export default class SimpleTable extends Simple {
4728
4617
  * ```
4729
4618
  */
4730
4619
  async union(column1, column2, newColumn) {
4731
- if (this.projections[column1] !== this.projections[column2]) {
4732
- throw new Error(`${column1} and ${column2} don't have the same projection.\n${column1}: ${this.projections[column1]}\n${column2}: ${this.projections[column2]}`);
4733
- }
4734
4620
  await queryDB(this, (await this.getColumns()).includes(newColumn)
4735
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Union("${column1}", "${column2}")`
4736
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Union("${column1}", "${column2}")`, mergeOptions(this, {
4621
+ ? `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; UPDATE "${this.name}" SET "${newColumn}" = ST_Union("${column1}", "${column2}")`
4622
+ : `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Union("${column1}", "${column2}")`, mergeOptions(this, {
4737
4623
  table: this.name,
4738
4624
  method: "union()",
4739
4625
  parameters: { column1, column2, newColumn },
4740
4626
  }));
4741
- this.projections[newColumn] = this.projections[column1];
4742
4627
  }
4743
4628
  /**
4744
4629
  * Extracts the latitude and longitude coordinates from point geometries.
4745
- * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4630
+ * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
4746
4631
  *
4747
4632
  * @param column - The name of the column storing the point geometries.
4748
4633
  * @param columnLat - The name of the new column where the extracted latitude values will be stored.
@@ -4757,8 +4642,8 @@ export default class SimpleTable extends Simple {
4757
4642
  * ```
4758
4643
  */
4759
4644
  async latLon(column, columnLat, columnLon) {
4760
- await queryDB(this, `ALTER TABLE "${this.name}" ADD "${columnLat}" DOUBLE; UPDATE "${this.name}" SET "${columnLat}" = ST_X("${column}");
4761
- ALTER TABLE "${this.name}" ADD "${columnLon}" DOUBLE; UPDATE "${this.name}" SET "${columnLon}" = ST_Y("${column}");`, mergeOptions(this, {
4645
+ await queryDB(this, `ALTER TABLE "${this.name}" ADD "${columnLat}" DOUBLE; UPDATE "${this.name}" SET "${columnLat}" = ST_Y("${column}");
4646
+ ALTER TABLE "${this.name}" ADD "${columnLon}" DOUBLE; UPDATE "${this.name}" SET "${columnLon}" = ST_X("${column}");`, mergeOptions(this, {
4762
4647
  table: this.name,
4763
4648
  method: "latLon()",
4764
4649
  parameters: { column, columnLon, columnLat },
@@ -4825,13 +4710,12 @@ export default class SimpleTable extends Simple {
4825
4710
  ? options.column
4826
4711
  : await findGeoColumn(this);
4827
4712
  await queryDB(this, (await this.getColumns()).includes(newColumn)
4828
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Centroid("${column}")`
4829
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Centroid("${column}")`, mergeOptions(this, {
4713
+ ? `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; UPDATE "${this.name}" SET "${newColumn}" = ST_Centroid("${column}")`
4714
+ : `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Centroid("${column}")`, mergeOptions(this, {
4830
4715
  table: this.name,
4831
4716
  method: "centroid()",
4832
4717
  parameters: { column, newColumn },
4833
4718
  }));
4834
- this.projections[newColumn] = this.projections[column];
4835
4719
  }
4836
4720
  /**
4837
4721
  * Generates a random point within the geometries of a specified column.
@@ -4878,13 +4762,12 @@ export default class SimpleTable extends Simple {
4878
4762
  if (nbNulls > 0 && !options.try) {
4879
4763
  throw new Error(`${nbNulls} points could not be generated. Consider increasing nbPointsToTry or set options.try to true.`);
4880
4764
  }
4881
- this.projections[newColumn] = this.projections[column];
4882
4765
  }
4883
4766
  /**
4884
4767
  * Computes the distance between geometries in two specified columns.
4885
4768
  * By default, the distance is calculated in the Spatial Reference System (SRS) unit of the input geometries.
4886
4769
  * You can optionally specify `"spheroid"` or `"haversine"` methods to get results in meters or kilometers.
4887
- * If using `"spheroid"` or `"haversine"`, the input geometries must be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4770
+ * If using `"spheroid"` or `"haversine"`, the input geometries must be in the EPSG:4326 coordinate system (WGS84).
4888
4771
  *
4889
4772
  * @param column1 - The name of the first column storing geometries.
4890
4773
  * @param column2 - The name of the second column storing geometries.
@@ -5000,7 +4883,7 @@ export default class SimpleTable extends Simple {
5000
4883
  parameters: { column, method, options },
5001
4884
  }));
5002
4885
  if (typeof options.outputTable === "string") {
5003
- return this.sdb.newTable(options.outputTable, this.projections);
4886
+ return this.sdb.newTable(options.outputTable);
5004
4887
  }
5005
4888
  else {
5006
4889
  return this;
@@ -5035,7 +4918,7 @@ export default class SimpleTable extends Simple {
5035
4918
  }
5036
4919
  /**
5037
4920
  * Returns the bounding box of geometries in `[minLat, minLon, maxLat, maxLon]` order.
5038
- * By default, the method will try to find the column with the geometries. The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4921
+ * By default, the method will try to find the column with the geometries. The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
5039
4922
  *
5040
4923
  * @param column - The name of the column storing geometries. If omitted, the method will automatically attempt to find a geometry column.
5041
4924
  * @returns A promise that resolves to an array `[minLat, minLon, maxLat, maxLon]` representing the bounding box.
@@ -5058,10 +4941,10 @@ export default class SimpleTable extends Simple {
5058
4941
  async getBoundingBox(column) {
5059
4942
  const col = column ?? (await findGeoColumn(this));
5060
4943
  const result = (await queryDB(this, `SELECT
5061
- MIN(ST_XMin("${col}")) AS minX,
5062
- MIN(ST_YMin("${col}")) AS minY,
5063
- MAX(ST_XMax("${col}")) AS maxX,
5064
- MAX(ST_YMax("${col}")) AS maxY,
4944
+ MIN(ST_YMin("${col}")) AS minX,
4945
+ MIN(ST_XMin("${col}")) AS minY,
4946
+ MAX(ST_YMax("${col}")) AS maxX,
4947
+ MAX(ST_XMax("${col}")) AS maxY,
5065
4948
  from "${this.name}";`, mergeOptions(this, {
5066
4949
  table: this.name,
5067
4950
  method: "getBoundingBox()",
@@ -5073,7 +4956,6 @@ export default class SimpleTable extends Simple {
5073
4956
  /**
5074
4957
  * Returns the table's geospatial data as a GeoJSON object.
5075
4958
  * If the table has multiple geometry columns, you must specify which one to use.
5076
- * If the geometry column's projection is WGS84 or EPSG:4326 (`[latitude, longitude]` axis order), the coordinates will be flipped to follow the RFC7946 standard (`[longitude, latitude]` axis order) in the output GeoJSON.
5077
4959
  *
5078
4960
  * @param column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.
5079
4961
  * @param options - An optional object with configuration options:
@@ -5178,8 +5060,6 @@ export default class SimpleTable extends Simple {
5178
5060
  * Writes the table's geospatial data to a file in GeoJSON, GeoParquet, or Shapefile format.
5179
5061
  * If the specified path does not exist, it will be created.
5180
5062
  *
5181
- * For GeoJSON files (`.geojson` or `.json`), if the projection is WGS84 or EPSG:4326 (`[latitude, longitude]` axis order), the coordinates will be flipped to follow the RFC7946 standard (`[longitude, latitude]` axis order) in the output.
5182
- *
5183
5063
  * @param file - The absolute path to the output file (e.g., `"./output.geojson"`, `"./output.geoparquet"`, `"./shapefile-folder/output.shp"`).
5184
5064
  * @param options - An optional object with configuration options:
5185
5065
  * @param options.precision - For GeoJSON, the maximum number of figures after the decimal separator to write in coordinates. Defaults to `undefined` (full precision).
@@ -5433,6 +5313,22 @@ export default class SimpleTable extends Simple {
5433
5313
  console.table(await getDescription(this));
5434
5314
  }
5435
5315
  }
5316
+ /**
5317
+ * Retrieves the projection of a specified geospatial column.
5318
+ *
5319
+ * @param column - The name of the geospatial column for which to retrieve the projection.
5320
+ * @returns A promise that resolves to the projection of the specified column.
5321
+ * @category Geospatial
5322
+ *
5323
+ * @example
5324
+ * ```ts
5325
+ * // Get the projection of the 'geom' column
5326
+ * const projection = await table.getProjection("geom");
5327
+ * ```
5328
+ */
5329
+ async getProjection(column) {
5330
+ return (await this.sdb.customQuery(`SELECT ST_CRS("${column}") AS proj FROM "${this.name}" LIMIT 1;`, { returnDataFrom: "query" }))[0].proj;
5331
+ }
5436
5332
  /**
5437
5333
  * Logs the projections of the geospatial data (if any) to the console.
5438
5334
  *
@@ -5447,7 +5343,19 @@ export default class SimpleTable extends Simple {
5447
5343
  */
5448
5344
  async logProjections() {
5449
5345
  console.log(`\nTable ${this.name} projections:`);
5450
- console.log(this.projections);
5346
+ const types = await this.getTypes();
5347
+ const geoColumns = Object.entries(types)
5348
+ .filter(([_, type]) => type.toLowerCase().includes("geometry"))
5349
+ .map(([column]) => column);
5350
+ if (geoColumns.length === 0) {
5351
+ console.log("No geometry columns found.");
5352
+ }
5353
+ else {
5354
+ for (const column of geoColumns) {
5355
+ const projection = types[column];
5356
+ console.log(`- Column "${column}": ${projection}`);
5357
+ }
5358
+ }
5451
5359
  return await this;
5452
5360
  }
5453
5361
  /**