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.
- package/README.md +26 -20
- package/REFERENCE.md +429 -0
- package/dist/build-RQF35KW6.js +21 -0
- package/dist/chunk-43VQMAQO.js +52 -0
- package/dist/chunk-5U4J6E6Y.js +4911 -0
- package/dist/{chunk-5QK6JCLT.js → chunk-EXDH7EHK.js} +726 -68
- package/dist/chunk-JVTGXPGV.js +382 -0
- package/dist/{cli-main-HRFGWUWR.js → cli-main-K3PKVCIP.js} +1099 -351
- package/dist/errors-C3VZMCM5.js +20 -0
- package/dist/index.js +2 -2
- package/dist/inspect-source-5CD3AV5J.js +227 -0
- package/dist/recipe-3BPMNDPX.js +23 -0
- package/dist/{tileset-entry-ITUSGCM3.js → tileset-entry-V5RUQGZG.js} +4 -1
- package/package.json +14 -5
- package/schemas/tileset-recipe.v1.json +171 -0
|
@@ -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-
|
|
12
|
+
const { runTilesetCli } = await import("./tileset-entry-V5RUQGZG.js");
|
|
13
13
|
await runTilesetCli();
|
|
14
14
|
} else {
|
|
15
|
-
await import("./cli-main-
|
|
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-
|
|
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.
|
|
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.
|
|
42
|
-
"@tileflow/dev": ">=0.1.0-alpha.
|
|
43
|
-
"@tileflow/maps": ">=0.1.0-alpha.
|
|
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
|
+
}
|