tileflow 0.1.0-alpha.22 → 0.1.0-alpha.23

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.
@@ -0,0 +1,20 @@
1
+ import {
2
+ SampleComplete,
3
+ TilesetBuildError,
4
+ featureTooLarge,
5
+ featureTooManyBytes,
6
+ listChoices,
7
+ maximumFeatureBytes,
8
+ maximumFeaturePositions,
9
+ yieldToEventLoop
10
+ } from "./chunk-43VQMAQO.js";
11
+ export {
12
+ SampleComplete,
13
+ TilesetBuildError,
14
+ featureTooLarge,
15
+ featureTooManyBytes,
16
+ listChoices,
17
+ maximumFeatureBytes,
18
+ maximumFeaturePositions,
19
+ yieldToEventLoop
20
+ };
package/dist/index.js CHANGED
@@ -9,8 +9,8 @@ if (isRootCliVersionRequest(process.argv.slice(2))) {
9
9
  process.stdout.write(`${getCliVersion()}
10
10
  `);
11
11
  } else if (process.argv[2] === "tileset") {
12
- const { runTilesetCli } = await import("./tileset-entry-ITUSGCM3.js");
12
+ const { runTilesetCli } = await import("./tileset-entry-V5RUQGZG.js");
13
13
  await runTilesetCli();
14
14
  } else {
15
- await import("./cli-main-HRFGWUWR.js");
15
+ await import("./cli-main-K3PKVCIP.js");
16
16
  }
@@ -0,0 +1,227 @@
1
+ import {
2
+ FeatureIngest,
3
+ FeatureSpool,
4
+ GeoPackageLayer,
5
+ SpoolDirectory,
6
+ ZippedKml,
7
+ ZippedShapefile,
8
+ checkContainerFormat,
9
+ checkInputSignature,
10
+ chooseCrsStatement,
11
+ chooseLayer,
12
+ csvColumnNames,
13
+ csvColumnsNameCoordinates,
14
+ detectFormat,
15
+ fileChunks,
16
+ isKmz,
17
+ isZip,
18
+ readCsv,
19
+ readGeojson,
20
+ readGeojsonSequence,
21
+ readGpx,
22
+ readKml,
23
+ readShapefile
24
+ } from "./chunk-5U4J6E6Y.js";
25
+ import {
26
+ recipeFromSettings,
27
+ resolveCrs
28
+ } from "./chunk-JVTGXPGV.js";
29
+ import {
30
+ SampleComplete,
31
+ TilesetBuildError
32
+ } from "./chunk-43VQMAQO.js";
33
+ import "./chunk-GPPOECR5.js";
34
+
35
+ // src/tileset-build/inspect-source.ts
36
+ import { mkdtempSync, rmSync, statSync } from "fs";
37
+ import { tmpdir } from "os";
38
+ import { join, resolve } from "path";
39
+ var defaultSampleFeatures = 1e4;
40
+ var maximumSampleCoordinates = 2e3;
41
+ async function inspectTilesetSource(options) {
42
+ const input = resolve(options.input);
43
+ if (!statSync(input, { throwIfNoEntry: false })?.isFile()) {
44
+ throw new TilesetBuildError(
45
+ "TF_TILESET_BUILD_INPUT_MISSING",
46
+ "input",
47
+ `Input file not found: ${options.input}.`
48
+ );
49
+ }
50
+ const format = options.format ?? detectFormat(input);
51
+ const zipped = isZip(input);
52
+ const kmz = isKmz(input);
53
+ checkContainerFormat(format, zipped, kmz);
54
+ checkInputSignature(input, format, zipped ? "zip" : kmz ? "kmz" : null);
55
+ const base = { command: "tileset build --inspect", format, schemaVersion: 1 };
56
+ let zip = null;
57
+ let zippedKml = null;
58
+ let geopackage = null;
59
+ try {
60
+ zip = zipped ? await ZippedShapefile.open(input, options.zipEntry) : null;
61
+ zippedKml = kmz ? await ZippedKml.open(input, options.zipEntry) : null;
62
+ geopackage = format === "geopackage" ? GeoPackageLayer.open(input, options.inputLayer) : null;
63
+ } catch (error) {
64
+ if (error instanceof TilesetBuildError && error.choices) {
65
+ const option = error.path === "inputLayer" ? "inputLayer" : "zipEntry";
66
+ return { ...base, choices: { names: error.choices.slice(0, 1e3), option } };
67
+ }
68
+ throw error;
69
+ }
70
+ const temporary = mkdtempSync(join(tmpdir(), "tileflow-tileset-inspect-"));
71
+ try {
72
+ const shapefile = zip ? await zip.extractProjection(temporary) : input;
73
+ const statement = await chooseCrsStatement(format, shapefile, options, geopackage);
74
+ if (format === "csv" && !await csvColumnsNameCoordinates(input, options)) {
75
+ return {
76
+ ...base,
77
+ columns: await csvColumnNames(input),
78
+ crs: { label: statement.label, status: "unknown" }
79
+ };
80
+ }
81
+ const reading = coordinateProbe(statement);
82
+ if (zip) await zip.extractData(temporary);
83
+ const directory = new SpoolDirectory(temporary);
84
+ const ingest = new FeatureIngest(
85
+ new FeatureSpool(directory),
86
+ { exclude: null, include: null },
87
+ reading.transform
88
+ );
89
+ ingest.stopAfter = options.sampleFeatures ?? defaultSampleFeatures;
90
+ let complete = true;
91
+ try {
92
+ await readSample(format, input, shapefile, ingest, options, zippedKml, geopackage);
93
+ } catch (error) {
94
+ if (!(error instanceof SampleComplete)) throw error;
95
+ complete = false;
96
+ }
97
+ const layer = chooseLayer(options.layer, options.inputLayer, input);
98
+ const crs = reading.crs();
99
+ const recipe = recipeFromSettings(
100
+ { ...options, ...crs.status === "needs-reproject" ? { reproject: true } : {} },
101
+ layer
102
+ );
103
+ if (ingest.featureCount === 0) {
104
+ return {
105
+ ...base,
106
+ crs,
107
+ recipe,
108
+ sample: {
109
+ bounds: null,
110
+ complete,
111
+ coordinates: reading.coordinates(),
112
+ features: 0,
113
+ sourceBounds: reading.bounds()
114
+ }
115
+ };
116
+ }
117
+ const summary = ingest.finish();
118
+ return {
119
+ ...base,
120
+ crs,
121
+ fields: summary.fields,
122
+ geometryTypes: summary.geometryTypes,
123
+ recipe,
124
+ sample: {
125
+ bounds: crs.status === "wgs84" || crs.status === "needs-reproject" ? summary.bounds : null,
126
+ complete,
127
+ coordinates: reading.coordinates(),
128
+ features: summary.features,
129
+ sourceBounds: reading.bounds()
130
+ },
131
+ warnings: summary.warnings
132
+ };
133
+ } finally {
134
+ zip?.close();
135
+ zippedKml?.close();
136
+ geopackage?.close();
137
+ rmSync(temporary, { force: true, recursive: true });
138
+ }
139
+ }
140
+ async function readSample(format, input, shapefile, ingest, options, zippedKml, geopackage) {
141
+ switch (format) {
142
+ case "csv":
143
+ return readCsv(input, ingest, options);
144
+ case "geojson":
145
+ return readGeojson(input, ingest, () => {
146
+ });
147
+ case "geojsonseq":
148
+ return readGeojsonSequence(input, ingest);
149
+ case "geopackage":
150
+ return geopackage.read(ingest, options.sourceCrs === void 0);
151
+ case "gpx":
152
+ return readGpx(fileChunks(input), ingest);
153
+ case "kml":
154
+ return readKml(zippedKml ? zippedKml.chunks() : fileChunks(input), ingest);
155
+ case "shapefile":
156
+ return readShapefile(shapefile, ingest);
157
+ }
158
+ }
159
+ function coordinateProbe(statement) {
160
+ let minX = Infinity;
161
+ let minY = Infinity;
162
+ let maxX = -Infinity;
163
+ let maxY = -Infinity;
164
+ let outOfRange = false;
165
+ const coordinates = [];
166
+ let seen = 0;
167
+ let stride = 1;
168
+ let real = null;
169
+ let crs;
170
+ if (statement.definition === null) {
171
+ crs = { label: statement.label, status: "unknown" };
172
+ } else {
173
+ try {
174
+ const resolved = resolveCrs(statement, true);
175
+ real = resolved.transform;
176
+ crs = { label: resolved.label, status: resolved.transform ? "needs-reproject" : "wgs84" };
177
+ } catch (error) {
178
+ if (!(error instanceof TilesetBuildError)) throw error;
179
+ crs = {
180
+ label: statement.label,
181
+ problem: { code: error.code, message: error.message },
182
+ status: "unsupported"
183
+ };
184
+ }
185
+ }
186
+ const usable = crs.status === "wgs84" || crs.status === "needs-reproject";
187
+ const transform = (x, y) => {
188
+ if (x < minX) minX = x;
189
+ if (y < minY) minY = y;
190
+ if (x > maxX) maxX = x;
191
+ if (y > maxY) maxY = y;
192
+ if (seen % stride === 0) {
193
+ if (coordinates.length === maximumSampleCoordinates) {
194
+ for (let index = 0; index < coordinates.length / 2; index += 1) {
195
+ coordinates[index] = coordinates[index * 2];
196
+ }
197
+ coordinates.length /= 2;
198
+ stride *= 2;
199
+ }
200
+ if (seen % stride === 0) coordinates.push([x, y]);
201
+ }
202
+ seen += 1;
203
+ if (!usable) return [0, 0];
204
+ const [longitude, latitude] = real ? real(x, y) : [x, y];
205
+ if (!Number.isFinite(longitude) || !Number.isFinite(latitude) || Math.abs(longitude) > 180 || Math.abs(latitude) > 90) {
206
+ outOfRange = true;
207
+ return [0, 0];
208
+ }
209
+ return [longitude, latitude];
210
+ };
211
+ return {
212
+ coordinates: () => coordinates,
213
+ bounds: () => Number.isFinite(minX) ? [minX, minY, maxX, maxY] : null,
214
+ crs: () => outOfRange ? {
215
+ label: crs.label,
216
+ problem: {
217
+ code: "TF_TILESET_BUILD_COORDINATES_OUT_OF_RANGE",
218
+ message: `Some coordinates are not valid longitude and latitude under ${crs.label}. The stated CRS is probably wrong.`
219
+ },
220
+ status: "out-of-range"
221
+ } : crs,
222
+ transform
223
+ };
224
+ }
225
+ export {
226
+ inspectTilesetSource
227
+ };
@@ -0,0 +1,23 @@
1
+ import {
2
+ layerNamePattern,
3
+ maximumZoom,
4
+ parseTilesetRecipe,
5
+ readTilesetRecipe,
6
+ recipeFromSettings,
7
+ recipeHash,
8
+ settingsFromRecipe,
9
+ tilesetRecipeJsonSchema,
10
+ tilesetRecipeSchemaUrl
11
+ } from "./chunk-JVTGXPGV.js";
12
+ import "./chunk-43VQMAQO.js";
13
+ export {
14
+ layerNamePattern,
15
+ maximumZoom,
16
+ parseTilesetRecipe,
17
+ readTilesetRecipe,
18
+ recipeFromSettings,
19
+ recipeHash,
20
+ settingsFromRecipe,
21
+ tilesetRecipeJsonSchema,
22
+ tilesetRecipeSchemaUrl
23
+ };
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  createCliProgram,
3
+ isRestoreJsonCommand,
3
4
  loadAuthConfig,
5
+ parseRestoreJson,
4
6
  registerTilesetCommands
5
- } from "./chunk-5QK6JCLT.js";
7
+ } from "./chunk-EXDH7EHK.js";
6
8
 
7
9
  // src/tileset-entry.ts
8
10
  import pc from "picocolors";
@@ -10,6 +12,7 @@ import { defaultTileflowApiUrl } from "@tileflow/dev/config";
10
12
  async function runTilesetCli() {
11
13
  const program = createCliProgram();
12
14
  registerTilesetCommands(program, { defaultApiUrl: defaultTileflowApiUrl, loadAuthConfig });
15
+ if (isRestoreJsonCommand(process.argv.slice(2))) return parseRestoreJson(program);
13
16
  try {
14
17
  await program.parseAsync();
15
18
  } catch (error) {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "tileflow",
3
- "version": "0.1.0-alpha.22",
3
+ "version": "0.1.0-alpha.23",
4
4
  "license": "Apache-2.0",
5
- "description": "CLI-only tools for Tileflow config, capture, visual testing, and deploy.",
5
+ "description": "CLI-only tools for Tileflow config, capture, visual testing, tiling, and deploy.",
6
6
  "type": "module",
7
7
  "homepage": "https://tileflow.dev",
8
8
  "repository": {
@@ -25,6 +25,8 @@
25
25
  },
26
26
  "files": [
27
27
  "dist",
28
+ "schemas",
29
+ "REFERENCE.md",
28
30
  "LICENSE"
29
31
  ],
30
32
  "bin": {
@@ -38,16 +40,23 @@
38
40
  "@tileflow/capture": ">=0.1.0-alpha.38 <0.1.0-beta.0",
39
41
  "@tileflow/coordinates": ">=0.1.0-alpha.3 <0.1.0-beta.0",
40
42
  "@tileflow/coordinates-runtime": ">=0.1.0-alpha.6 <0.1.0-beta.0",
41
- "@tileflow/core": ">=0.1.0-alpha.47 <0.1.0-beta.0",
42
- "@tileflow/dev": ">=0.1.0-alpha.42 <0.1.0-beta.0",
43
- "@tileflow/maps": ">=0.1.0-alpha.19 <0.1.0-beta.0",
43
+ "@tileflow/core": ">=0.1.0-alpha.48 <0.1.0-beta.0",
44
+ "@tileflow/dev": ">=0.1.0-alpha.43 <0.1.0-beta.0",
45
+ "@tileflow/maps": ">=0.1.0-alpha.20 <0.1.0-beta.0",
44
46
  "commander": "^15.0.0",
47
+ "fflate": "0.8.3",
45
48
  "hono": "4.13.14",
46
49
  "picocolors": "^1.1.1",
50
+ "pmtiles": "4.5.0",
51
+ "proj4": "2.22.0",
52
+ "yauzl": "3.4.0",
47
53
  "zod": "^4.6.7"
48
54
  },
49
55
  "devDependencies": {
56
+ "@mapbox/vector-tile": "3.0.0",
50
57
  "@types/pngjs": "6.0.5",
58
+ "@types/yauzl": "3.4.0",
59
+ "pbf": "5.1.2",
51
60
  "pngjs": "7.0.0"
52
61
  },
53
62
  "scripts": {
@@ -0,0 +1,171 @@
1
+ {
2
+ "$id": "https://tileflow.dev/schemas/tileset-recipe/v1.json",
3
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
+ "type": "object",
5
+ "properties": {
6
+ "$schema": {
7
+ "type": "string"
8
+ },
9
+ "layers": {
10
+ "type": "object",
11
+ "propertyNames": {
12
+ "type": "string",
13
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,191}$"
14
+ },
15
+ "additionalProperties": {
16
+ "type": "object",
17
+ "properties": {
18
+ "featureId": {
19
+ "type": "object",
20
+ "properties": {
21
+ "field": {
22
+ "type": "string",
23
+ "minLength": 1
24
+ },
25
+ "hash": {
26
+ "type": "boolean"
27
+ }
28
+ },
29
+ "required": ["field"],
30
+ "additionalProperties": false
31
+ },
32
+ "fields": {
33
+ "type": "object",
34
+ "properties": {
35
+ "exclude": {
36
+ "type": "array",
37
+ "items": {
38
+ "type": "string",
39
+ "minLength": 1
40
+ }
41
+ },
42
+ "include": {
43
+ "type": "array",
44
+ "items": {
45
+ "type": "string",
46
+ "minLength": 1
47
+ }
48
+ }
49
+ },
50
+ "additionalProperties": false
51
+ },
52
+ "maxzoom": {
53
+ "anyOf": [
54
+ {
55
+ "type": "string",
56
+ "const": "auto"
57
+ },
58
+ {
59
+ "type": "integer",
60
+ "minimum": 0,
61
+ "maximum": 16
62
+ }
63
+ ]
64
+ },
65
+ "minzoom": {
66
+ "type": "integer",
67
+ "minimum": 0,
68
+ "maximum": 16
69
+ },
70
+ "rank": {
71
+ "type": "object",
72
+ "properties": {
73
+ "by": {
74
+ "type": "string",
75
+ "minLength": 1
76
+ },
77
+ "order": {
78
+ "type": "string",
79
+ "enum": ["ascending", "descending"]
80
+ }
81
+ },
82
+ "required": ["by"],
83
+ "additionalProperties": false
84
+ },
85
+ "source": {
86
+ "type": "string",
87
+ "minLength": 1
88
+ }
89
+ },
90
+ "required": ["source"],
91
+ "additionalProperties": false
92
+ }
93
+ },
94
+ "metadata": {
95
+ "type": "object",
96
+ "properties": {
97
+ "attribution": {
98
+ "type": "string",
99
+ "minLength": 1
100
+ },
101
+ "description": {
102
+ "type": "string",
103
+ "minLength": 1
104
+ },
105
+ "name": {
106
+ "type": "string",
107
+ "minLength": 1
108
+ }
109
+ },
110
+ "additionalProperties": false
111
+ },
112
+ "sources": {
113
+ "type": "object",
114
+ "propertyNames": {
115
+ "type": "string",
116
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,191}$"
117
+ },
118
+ "additionalProperties": {
119
+ "type": "object",
120
+ "properties": {
121
+ "crs": {
122
+ "type": "object",
123
+ "properties": {
124
+ "from": {
125
+ "type": "string",
126
+ "minLength": 1
127
+ },
128
+ "reproject": {
129
+ "type": "boolean"
130
+ }
131
+ },
132
+ "additionalProperties": false
133
+ },
134
+ "csv": {
135
+ "type": "object",
136
+ "properties": {
137
+ "lat": {
138
+ "type": "string",
139
+ "minLength": 1
140
+ },
141
+ "lon": {
142
+ "type": "string",
143
+ "minLength": 1
144
+ }
145
+ },
146
+ "additionalProperties": false
147
+ },
148
+ "format": {
149
+ "type": "string",
150
+ "enum": ["csv", "geojson", "geojsonseq", "geopackage", "gpx", "kml", "shapefile"]
151
+ },
152
+ "layer": {
153
+ "type": "string",
154
+ "minLength": 1
155
+ },
156
+ "zipEntry": {
157
+ "type": "string",
158
+ "minLength": 1
159
+ }
160
+ },
161
+ "additionalProperties": false
162
+ }
163
+ },
164
+ "version": {
165
+ "type": "number",
166
+ "const": 1
167
+ }
168
+ },
169
+ "required": ["layers", "sources", "version"],
170
+ "additionalProperties": false
171
+ }