@tileflow/static 0.1.0-alpha.20 → 0.1.0-alpha.21
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 +38 -1
- package/dist/{chunk-QCR76BUO.js → chunk-A23RC4BE.js} +27 -3
- package/dist/{chunk-LGEYA6FQ.js → chunk-KPT7PASB.js} +22 -6
- package/dist/{chunk-YUG3PBK2.js → chunk-MGQCHCU3.js} +35 -5
- package/dist/chunk-NHQK5UZ2.js +455 -0
- package/dist/{chunk-HKYA7ZIU.js → chunk-S3WXE5P4.js} +32 -12
- package/dist/client.d.ts +1 -1
- package/dist/client.js +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -5
- package/dist/manifest.d.ts +27 -1
- package/dist/manifest.js +3 -3
- package/dist/overlays.d.ts +5 -3
- package/dist/overlays.js +2 -2
- package/dist/{scene-contract-DzsUeJ_V.d.ts → scene-contract-DZMhLDnf.d.ts} +19 -1
- package/dist/scene.d.ts +182 -5
- package/dist/scene.js +8 -2
- package/package.json +1 -1
- package/dist/chunk-ROBEGDDY.js +0 -63
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MAX_OVERLAY_LATITUDE,
|
|
3
|
+
jsonByteLength,
|
|
4
|
+
normalizeStaticCoordinate,
|
|
5
|
+
normalizeStaticOverlay,
|
|
6
|
+
roundNumber,
|
|
7
|
+
staticPaddingSchema,
|
|
8
|
+
staticSceneLimits,
|
|
9
|
+
staticSceneSchema,
|
|
10
|
+
stripUndefined
|
|
11
|
+
} from "./chunk-MGQCHCU3.js";
|
|
12
|
+
|
|
13
|
+
// src/auto-fit.ts
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
var autoFitOverlayReferenceSchema = z.object({
|
|
16
|
+
id: z.string().min(1).max(64),
|
|
17
|
+
index: z.number().int().min(0).max(23),
|
|
18
|
+
type: z.enum(["circle", "line", "marker", "polygon"])
|
|
19
|
+
}).strict();
|
|
20
|
+
var autoFitViewportSchema = z.object({
|
|
21
|
+
height: z.number().int().min(64).max(1280),
|
|
22
|
+
width: z.number().int().min(64).max(1280)
|
|
23
|
+
}).strict();
|
|
24
|
+
var autoFitDetailsSchema = z.object({
|
|
25
|
+
overlay: autoFitOverlayReferenceSchema.optional(),
|
|
26
|
+
padding: staticPaddingSchema.optional(),
|
|
27
|
+
projection: z.enum(["globe", "mercator"]).optional(),
|
|
28
|
+
requiredInsets: staticPaddingSchema.optional(),
|
|
29
|
+
ringIndex: z.number().int().min(0).max(15).optional(),
|
|
30
|
+
segmentIndex: z.number().int().min(0).max(1999).optional(),
|
|
31
|
+
viewport: autoFitViewportSchema.optional()
|
|
32
|
+
}).strict();
|
|
33
|
+
var staticOverlayInvalidDetailsSchema = z.object({
|
|
34
|
+
latitude: z.number().finite(),
|
|
35
|
+
limit: z.literal(MAX_OVERLAY_LATITUDE),
|
|
36
|
+
overlay: autoFitOverlayReferenceSchema
|
|
37
|
+
}).strict();
|
|
38
|
+
var autoFitErrorBase = {
|
|
39
|
+
error: z.string().min(1).max(512),
|
|
40
|
+
retryable: z.literal(false)
|
|
41
|
+
};
|
|
42
|
+
var staticMapRequestErrorResponseSchema = z.discriminatedUnion("code", [
|
|
43
|
+
z.object({
|
|
44
|
+
...autoFitErrorBase,
|
|
45
|
+
code: z.literal("AUTO_FIT_EMPTY"),
|
|
46
|
+
reason: z.literal("NO_FITTABLE_OVERLAYS")
|
|
47
|
+
}).strict(),
|
|
48
|
+
z.object({
|
|
49
|
+
...autoFitErrorBase,
|
|
50
|
+
code: z.literal("AUTO_FIT_AMBIGUOUS"),
|
|
51
|
+
details: autoFitDetailsSchema,
|
|
52
|
+
reason: z.literal("ANTIMERIDIAN_WRAP_REQUIRED")
|
|
53
|
+
}).strict(),
|
|
54
|
+
z.object({
|
|
55
|
+
...autoFitErrorBase,
|
|
56
|
+
code: z.literal("AUTO_FIT_IMPOSSIBLE"),
|
|
57
|
+
details: autoFitDetailsSchema.optional(),
|
|
58
|
+
reason: z.enum([
|
|
59
|
+
"GLOBE_NOT_SIMULTANEOUSLY_VISIBLE",
|
|
60
|
+
"INSUFFICIENT_VIEWPORT",
|
|
61
|
+
"CAMERA_UNRESOLVABLE",
|
|
62
|
+
"PROJECTED_FOOTPRINT_OUTSIDE_VIEWPORT"
|
|
63
|
+
])
|
|
64
|
+
}).strict(),
|
|
65
|
+
z.object({
|
|
66
|
+
...autoFitErrorBase,
|
|
67
|
+
code: z.literal("STATIC_OVERLAY_INVALID"),
|
|
68
|
+
details: staticOverlayInvalidDetailsSchema,
|
|
69
|
+
reason: z.literal("OVERLAY_LATITUDE_OUT_OF_RANGE")
|
|
70
|
+
}).strict()
|
|
71
|
+
]);
|
|
72
|
+
var StaticMapRequestError = class extends Error {
|
|
73
|
+
code;
|
|
74
|
+
details;
|
|
75
|
+
reason;
|
|
76
|
+
retryable = false;
|
|
77
|
+
status;
|
|
78
|
+
constructor(response, status = 422) {
|
|
79
|
+
super(response.error);
|
|
80
|
+
this.name = "StaticMapRequestError";
|
|
81
|
+
this.code = response.code;
|
|
82
|
+
this.details = "details" in response ? response.details : void 0;
|
|
83
|
+
this.reason = response.reason;
|
|
84
|
+
this.status = status;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var staticAutoFitPlanSchema = z.object({
|
|
88
|
+
bounds: z.tuple([
|
|
89
|
+
z.number().finite(),
|
|
90
|
+
z.number().finite().min(-90).max(90),
|
|
91
|
+
z.number().finite(),
|
|
92
|
+
z.number().finite().min(-90).max(90)
|
|
93
|
+
]),
|
|
94
|
+
longitudeOffsets: z.array(z.number().int().min(-360).max(360)).max(24),
|
|
95
|
+
nominalInsets: staticPaddingSchema,
|
|
96
|
+
requiredInsets: staticPaddingSchema
|
|
97
|
+
}).strict();
|
|
98
|
+
function analyzeStaticAutoFit(scene) {
|
|
99
|
+
if (scene.camera.type !== "auto") {
|
|
100
|
+
throw new Error("Static auto-fit analysis requires an auto camera");
|
|
101
|
+
}
|
|
102
|
+
if (scene.overlays.length === 0) {
|
|
103
|
+
return failure({
|
|
104
|
+
code: "AUTO_FIT_EMPTY",
|
|
105
|
+
error: "Auto-fit requires at least one overlay",
|
|
106
|
+
reason: "NO_FITTABLE_OVERLAYS",
|
|
107
|
+
retryable: false
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const components = [];
|
|
111
|
+
let south = Number.POSITIVE_INFINITY;
|
|
112
|
+
let north = Number.NEGATIVE_INFINITY;
|
|
113
|
+
let nominalExpansion = 0;
|
|
114
|
+
for (const [overlayIndex, overlay] of scene.overlays.entries()) {
|
|
115
|
+
const coordinates = overlayCoordinates(overlay);
|
|
116
|
+
const ambiguity = findAmbiguousSegment(overlay);
|
|
117
|
+
if (ambiguity) {
|
|
118
|
+
return failure({
|
|
119
|
+
code: "AUTO_FIT_AMBIGUOUS",
|
|
120
|
+
details: {
|
|
121
|
+
overlay: {
|
|
122
|
+
id: overlay.id ?? `overlay-${overlayIndex + 1}`,
|
|
123
|
+
index: overlayIndex,
|
|
124
|
+
type: overlay.type
|
|
125
|
+
},
|
|
126
|
+
...ambiguity.ringIndex === void 0 ? {} : { ringIndex: ambiguity.ringIndex },
|
|
127
|
+
segmentIndex: ambiguity.segmentIndex
|
|
128
|
+
},
|
|
129
|
+
error: `Overlay overlays.${overlayIndex} requires an explicit antimeridian wrap decision`,
|
|
130
|
+
reason: "ANTIMERIDIAN_WRAP_REQUIRED",
|
|
131
|
+
retryable: false
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const longitudes = coordinates.map(([longitude]) => longitude);
|
|
135
|
+
components.push({
|
|
136
|
+
east: Math.max(...longitudes),
|
|
137
|
+
overlayIndex,
|
|
138
|
+
west: Math.min(...longitudes)
|
|
139
|
+
});
|
|
140
|
+
for (const [, latitude] of coordinates) {
|
|
141
|
+
south = Math.min(south, latitude);
|
|
142
|
+
north = Math.max(north, latitude);
|
|
143
|
+
}
|
|
144
|
+
nominalExpansion = Math.max(nominalExpansion, nominalOverlayExpansion(overlay));
|
|
145
|
+
}
|
|
146
|
+
const longitudePlan = fitLongitudeComponents(components);
|
|
147
|
+
const nominalInset = Math.ceil(nominalExpansion);
|
|
148
|
+
const nominalInsets = allSides(nominalInset);
|
|
149
|
+
const padding = normalizedPadding(scene.camera.padding, scene.size);
|
|
150
|
+
if ([padding.bottom, padding.left, padding.right, padding.top].some(
|
|
151
|
+
(value) => !Number.isSafeInteger(value + nominalInset)
|
|
152
|
+
)) {
|
|
153
|
+
return failure({
|
|
154
|
+
code: "AUTO_FIT_IMPOSSIBLE",
|
|
155
|
+
details: {
|
|
156
|
+
padding,
|
|
157
|
+
viewport: { height: scene.size.height, width: scene.size.width }
|
|
158
|
+
},
|
|
159
|
+
error: "Auto-fit nominal footprint leaves no usable viewport",
|
|
160
|
+
reason: "INSUFFICIENT_VIEWPORT",
|
|
161
|
+
retryable: false
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const requiredInsets = {
|
|
165
|
+
bottom: padding.bottom + nominalInset,
|
|
166
|
+
left: padding.left + nominalInset,
|
|
167
|
+
right: padding.right + nominalInset,
|
|
168
|
+
top: padding.top + nominalInset
|
|
169
|
+
};
|
|
170
|
+
if (requiredInsets.left + requiredInsets.right >= scene.size.width || requiredInsets.top + requiredInsets.bottom >= scene.size.height) {
|
|
171
|
+
return failure({
|
|
172
|
+
code: "AUTO_FIT_IMPOSSIBLE",
|
|
173
|
+
details: {
|
|
174
|
+
padding,
|
|
175
|
+
requiredInsets,
|
|
176
|
+
viewport: { height: scene.size.height, width: scene.size.width }
|
|
177
|
+
},
|
|
178
|
+
error: "Auto-fit nominal footprint leaves no usable viewport",
|
|
179
|
+
reason: "INSUFFICIENT_VIEWPORT",
|
|
180
|
+
retryable: false
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
ok: true,
|
|
185
|
+
plan: {
|
|
186
|
+
bounds: [
|
|
187
|
+
roundNumber(longitudePlan.west),
|
|
188
|
+
roundNumber(south),
|
|
189
|
+
roundNumber(longitudePlan.east),
|
|
190
|
+
roundNumber(north)
|
|
191
|
+
],
|
|
192
|
+
longitudeOffsets: longitudePlan.offsets,
|
|
193
|
+
nominalInsets,
|
|
194
|
+
requiredInsets
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function failure(response) {
|
|
199
|
+
return { ...response, ok: false };
|
|
200
|
+
}
|
|
201
|
+
function overlayCoordinates(overlay) {
|
|
202
|
+
if (overlay.type === "circle" || overlay.type === "marker") {
|
|
203
|
+
return [overlay.coordinate];
|
|
204
|
+
}
|
|
205
|
+
if (overlay.type === "line") {
|
|
206
|
+
return overlay.coordinates;
|
|
207
|
+
}
|
|
208
|
+
return overlay.coordinates.flat();
|
|
209
|
+
}
|
|
210
|
+
function findAmbiguousSegment(overlay) {
|
|
211
|
+
if (overlay.type === "circle" || overlay.type === "marker") return null;
|
|
212
|
+
const paths = overlay.type === "line" ? [overlay.coordinates] : overlay.coordinates;
|
|
213
|
+
for (const [ringIndex, path] of paths.entries()) {
|
|
214
|
+
for (let segmentIndex = 0; segmentIndex < path.length - 1; segmentIndex += 1) {
|
|
215
|
+
const start = path[segmentIndex];
|
|
216
|
+
const end = path[segmentIndex + 1];
|
|
217
|
+
if (start && end && Math.abs(end[0] - start[0]) >= 180) {
|
|
218
|
+
return {
|
|
219
|
+
...overlay.type === "polygon" ? { ringIndex } : {},
|
|
220
|
+
segmentIndex
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
function nominalOverlayExpansion(overlay) {
|
|
228
|
+
if (overlay.type === "circle" || overlay.type === "marker") {
|
|
229
|
+
return overlay.radius + overlay.strokeWidth;
|
|
230
|
+
}
|
|
231
|
+
if (overlay.type === "line") {
|
|
232
|
+
return overlay.width / 2 + 0.5;
|
|
233
|
+
}
|
|
234
|
+
return overlay.stroke && overlay.strokeWidth > 0 ? overlay.strokeWidth / 2 + 0.5 : 0;
|
|
235
|
+
}
|
|
236
|
+
function fitLongitudeComponents(components) {
|
|
237
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
238
|
+
for (const component of components) {
|
|
239
|
+
candidates.add(toCircle(component.west));
|
|
240
|
+
candidates.add(toCircle(component.east));
|
|
241
|
+
}
|
|
242
|
+
let best;
|
|
243
|
+
for (const cut of [...candidates].sort((left, right) => left - right)) {
|
|
244
|
+
const assignedStarts = [];
|
|
245
|
+
let west = Number.POSITIVE_INFINITY;
|
|
246
|
+
let east = Number.NEGATIVE_INFINITY;
|
|
247
|
+
let valid = true;
|
|
248
|
+
for (const component of components) {
|
|
249
|
+
const width = component.east - component.west;
|
|
250
|
+
let start = toCircle(component.west);
|
|
251
|
+
if (start < cut) start += 360;
|
|
252
|
+
const end = start + width;
|
|
253
|
+
if (end > cut + 360 + 1e-9) {
|
|
254
|
+
valid = false;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
assignedStarts.push(start);
|
|
258
|
+
west = Math.min(west, start);
|
|
259
|
+
east = Math.max(east, end);
|
|
260
|
+
}
|
|
261
|
+
if (!valid) continue;
|
|
262
|
+
const span = east - west;
|
|
263
|
+
const canonicalWest2 = canonicalLongitude(west - 180);
|
|
264
|
+
const bestCanonicalWest = best ? canonicalLongitude(best.west - 180) : Number.POSITIVE_INFINITY;
|
|
265
|
+
if (!best || span < best.span - 1e-9 || Math.abs(span - best.span) <= 1e-9 && canonicalWest2 < bestCanonicalWest) {
|
|
266
|
+
best = { assignedStarts, east, span, west };
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (!best) {
|
|
270
|
+
const west = Math.min(...components.map((component) => component.west));
|
|
271
|
+
const east = Math.max(...components.map((component) => component.east));
|
|
272
|
+
return { east, offsets: components.map(() => 0), west };
|
|
273
|
+
}
|
|
274
|
+
const unshiftedWest = best.west - 180;
|
|
275
|
+
const canonicalWest = canonicalLongitude(unshiftedWest);
|
|
276
|
+
const globalOffset = canonicalWest - unshiftedWest;
|
|
277
|
+
const offsets = components.map((component, index) => {
|
|
278
|
+
const assignedLongitude = (best?.assignedStarts[index] ?? 0) - 180 + globalOffset;
|
|
279
|
+
return Math.round(assignedLongitude - component.west);
|
|
280
|
+
});
|
|
281
|
+
return {
|
|
282
|
+
east: canonicalWest + best.span,
|
|
283
|
+
offsets,
|
|
284
|
+
west: canonicalWest
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function toCircle(longitude) {
|
|
288
|
+
const value = (longitude + 180) % 360;
|
|
289
|
+
return value < 0 ? value + 360 : value;
|
|
290
|
+
}
|
|
291
|
+
function canonicalLongitude(longitude) {
|
|
292
|
+
const value = ((longitude + 180) % 360 + 360) % 360;
|
|
293
|
+
return value - 180;
|
|
294
|
+
}
|
|
295
|
+
function allSides(value) {
|
|
296
|
+
return { bottom: value, left: value, right: value, top: value };
|
|
297
|
+
}
|
|
298
|
+
function normalizedPadding(padding, size) {
|
|
299
|
+
if (padding === void 0) {
|
|
300
|
+
return allSides(Math.min(32, Math.ceil(Math.min(size.width, size.height) * 0.05)));
|
|
301
|
+
}
|
|
302
|
+
if (typeof padding === "number") return allSides(padding);
|
|
303
|
+
return {
|
|
304
|
+
bottom: padding.bottom ?? 0,
|
|
305
|
+
left: padding.left ?? 0,
|
|
306
|
+
right: padding.right ?? 0,
|
|
307
|
+
top: padding.top ?? 0
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function autoFitErrorResponse(failure2) {
|
|
311
|
+
const { ok: _ok, ...response } = failure2;
|
|
312
|
+
return response;
|
|
313
|
+
}
|
|
314
|
+
function findStaticOverlayLatitudeFailure(input) {
|
|
315
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return null;
|
|
316
|
+
const overlays = input.overlays;
|
|
317
|
+
if (!Array.isArray(overlays)) return null;
|
|
318
|
+
for (const [index, candidate] of overlays.entries()) {
|
|
319
|
+
if (index >= staticSceneLimits.maxOverlays) break;
|
|
320
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) continue;
|
|
321
|
+
const overlay = candidate;
|
|
322
|
+
const type = overlay.type;
|
|
323
|
+
if (!["circle", "line", "marker", "polygon"].includes(String(type))) continue;
|
|
324
|
+
const coordinates = type === "circle" || type === "marker" ? [overlay.coordinate] : overlayCoordinateCandidates(type, overlay.coordinates);
|
|
325
|
+
for (const coordinate of coordinates) {
|
|
326
|
+
if (!Array.isArray(coordinate) || coordinate.length !== 2 || typeof coordinate[1] !== "number" || !Number.isFinite(coordinate[1]) || Math.abs(coordinate[1]) <= MAX_OVERLAY_LATITUDE) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const id = typeof overlay.id === "string" && overlay.id.trim() ? overlay.id.trim() : `overlay-${index + 1}`;
|
|
330
|
+
const response = {
|
|
331
|
+
code: "STATIC_OVERLAY_INVALID",
|
|
332
|
+
details: {
|
|
333
|
+
latitude: coordinate[1],
|
|
334
|
+
limit: MAX_OVERLAY_LATITUDE,
|
|
335
|
+
overlay: {
|
|
336
|
+
id: id.slice(0, 64),
|
|
337
|
+
index,
|
|
338
|
+
type
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
error: `Overlay overlays.${index} latitude ${coordinate[1]} exceeds the supported \xB1${MAX_OVERLAY_LATITUDE}\xB0 range`,
|
|
342
|
+
reason: "OVERLAY_LATITUDE_OUT_OF_RANGE",
|
|
343
|
+
retryable: false
|
|
344
|
+
};
|
|
345
|
+
return { ...response, ok: false };
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
function overlayCoordinateCandidates(type, value) {
|
|
351
|
+
if (!Array.isArray(value)) return [];
|
|
352
|
+
if (type === "line") {
|
|
353
|
+
return value.slice(0, staticSceneLimits.maxPathCoordinates);
|
|
354
|
+
}
|
|
355
|
+
return value.slice(0, 16).flatMap(
|
|
356
|
+
(ring) => Array.isArray(ring) ? ring.slice(0, staticSceneLimits.maxPathCoordinates) : []
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// src/scene.ts
|
|
361
|
+
function validateStaticScene(input) {
|
|
362
|
+
const overlayLatitudeFailure = findStaticOverlayLatitudeFailure(input);
|
|
363
|
+
if (overlayLatitudeFailure) return overlayLatitudeFailure;
|
|
364
|
+
const parsed = staticSceneSchema.safeParse(input);
|
|
365
|
+
if (!parsed.success) {
|
|
366
|
+
return {
|
|
367
|
+
error: parsed.error.issues.map((issue) => `${issue.path.join(".") || "scene"}: ${issue.message}`).join("; "),
|
|
368
|
+
ok: false
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
if (jsonByteLength(parsed.data.overlays) > staticSceneLimits.maxGeoJsonBytes) {
|
|
372
|
+
return {
|
|
373
|
+
error: `overlays exceed ${staticSceneLimits.maxGeoJsonBytes} bytes`,
|
|
374
|
+
ok: false
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
const scene = normalizeParsedStaticScene(parsed.data);
|
|
378
|
+
if (scene.camera.type === "auto") {
|
|
379
|
+
const analysis = analyzeStaticAutoFit(scene);
|
|
380
|
+
if (!analysis.ok) return analysis;
|
|
381
|
+
}
|
|
382
|
+
return { ok: true, scene };
|
|
383
|
+
}
|
|
384
|
+
function normalizeStaticScene(scene) {
|
|
385
|
+
const overlayLatitudeFailure = findStaticOverlayLatitudeFailure(scene);
|
|
386
|
+
if (overlayLatitudeFailure) {
|
|
387
|
+
const { ok: _ok, ...response } = overlayLatitudeFailure;
|
|
388
|
+
throw new StaticMapRequestError(response);
|
|
389
|
+
}
|
|
390
|
+
const normalized = normalizeParsedStaticScene(staticSceneSchema.parse(scene));
|
|
391
|
+
if (normalized.camera.type === "auto") {
|
|
392
|
+
const analysis = analyzeStaticAutoFit(normalized);
|
|
393
|
+
if (!analysis.ok) {
|
|
394
|
+
throw new StaticMapRequestError(autoFitErrorResponse(analysis));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return normalized;
|
|
398
|
+
}
|
|
399
|
+
function normalizeParsedStaticScene(parsed) {
|
|
400
|
+
return stripUndefined({
|
|
401
|
+
camera: parsed.camera.type === "center" ? {
|
|
402
|
+
bearing: roundNumber(parsed.camera.bearing ?? 0),
|
|
403
|
+
center: normalizeStaticCoordinate(parsed.camera.center),
|
|
404
|
+
type: "center",
|
|
405
|
+
zoom: roundNumber(parsed.camera.zoom)
|
|
406
|
+
} : parsed.camera.type === "bounds" ? {
|
|
407
|
+
bearing: roundNumber(parsed.camera.bearing ?? 0),
|
|
408
|
+
bounds: parsed.camera.bounds.map(roundNumber),
|
|
409
|
+
padding: parsed.camera.padding ?? 32,
|
|
410
|
+
type: "bounds"
|
|
411
|
+
} : {
|
|
412
|
+
bearing: roundNumber(parsed.camera.bearing ?? 0),
|
|
413
|
+
maxZoom: roundNumber(parsed.camera.maxZoom ?? 16),
|
|
414
|
+
padding: normalizeAutoPadding(parsed.camera.padding, parsed.size),
|
|
415
|
+
type: "auto"
|
|
416
|
+
},
|
|
417
|
+
map: parsed.map,
|
|
418
|
+
overlays: parsed.overlays.map(
|
|
419
|
+
(overlay, index) => normalizeStaticOverlay({
|
|
420
|
+
...overlay,
|
|
421
|
+
id: overlay.id ?? `overlay-${index + 1}`
|
|
422
|
+
})
|
|
423
|
+
),
|
|
424
|
+
size: {
|
|
425
|
+
dpr: parsed.size.dpr ?? 1,
|
|
426
|
+
height: parsed.size.height,
|
|
427
|
+
width: parsed.size.width
|
|
428
|
+
},
|
|
429
|
+
theme: parsed.theme
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
function normalizeAutoPadding(padding, size) {
|
|
433
|
+
if (padding === void 0) {
|
|
434
|
+
const value = Math.min(32, Math.ceil(Math.min(size.width, size.height) * 0.05));
|
|
435
|
+
return { bottom: value, left: value, right: value, top: value };
|
|
436
|
+
}
|
|
437
|
+
if (typeof padding === "number") {
|
|
438
|
+
return { bottom: padding, left: padding, right: padding, top: padding };
|
|
439
|
+
}
|
|
440
|
+
return {
|
|
441
|
+
bottom: padding.bottom ?? 0,
|
|
442
|
+
left: padding.left ?? 0,
|
|
443
|
+
right: padding.right ?? 0,
|
|
444
|
+
top: padding.top ?? 0
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export {
|
|
449
|
+
staticMapRequestErrorResponseSchema,
|
|
450
|
+
StaticMapRequestError,
|
|
451
|
+
staticAutoFitPlanSchema,
|
|
452
|
+
analyzeStaticAutoFit,
|
|
453
|
+
validateStaticScene,
|
|
454
|
+
normalizeStaticScene
|
|
455
|
+
};
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
+
analyzeStaticAutoFit,
|
|
2
3
|
normalizeStaticScene,
|
|
4
|
+
staticAutoFitPlanSchema,
|
|
3
5
|
validateStaticScene
|
|
4
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NHQK5UZ2.js";
|
|
5
7
|
import {
|
|
6
8
|
hashStableValue,
|
|
7
9
|
isSafeHttpUrl,
|
|
10
|
+
stableStringify,
|
|
8
11
|
staticSceneSchema,
|
|
9
12
|
stripUndefined
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-MGQCHCU3.js";
|
|
11
14
|
|
|
12
15
|
// src/manifest.ts
|
|
13
16
|
import { z } from "zod";
|
|
14
17
|
var staticRendererSchemaVersion = 1;
|
|
15
18
|
var staticRenderManifestSchema = z.object({
|
|
19
|
+
autoFit: staticAutoFitPlanSchema.optional(),
|
|
16
20
|
mapId: z.string().trim().min(1).max(128),
|
|
17
21
|
rendererVersion: z.string().trim().min(1).max(64),
|
|
18
22
|
schemaVersion: z.literal(staticRendererSchemaVersion),
|
|
@@ -24,32 +28,44 @@ var staticRenderManifestSchema = z.object({
|
|
|
24
28
|
})
|
|
25
29
|
});
|
|
26
30
|
function validateStaticRenderManifest(input) {
|
|
27
|
-
const
|
|
31
|
+
const rawScene = input && typeof input === "object" && !Array.isArray(input) && "scene" in input ? input.scene : void 0;
|
|
32
|
+
const sceneValidation = validateStaticScene(rawScene);
|
|
33
|
+
if (!sceneValidation.ok) {
|
|
34
|
+
return sceneValidation;
|
|
35
|
+
}
|
|
36
|
+
const parsed = staticRenderManifestSchema.safeParse({
|
|
37
|
+
...input,
|
|
38
|
+
scene: sceneValidation.scene
|
|
39
|
+
});
|
|
28
40
|
if (!parsed.success) {
|
|
29
41
|
return {
|
|
30
42
|
error: parsed.error.issues.map((issue) => `${issue.path.join(".") || "manifest"}: ${issue.message}`).join("; "),
|
|
31
43
|
ok: false
|
|
32
44
|
};
|
|
33
45
|
}
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
return
|
|
46
|
+
const autoFit = expectedAutoFit(sceneValidation.scene);
|
|
47
|
+
if (autoFit === void 0 !== (parsed.data.autoFit === void 0) || autoFit !== void 0 && stableStringify(autoFit) !== stableStringify(parsed.data.autoFit)) {
|
|
48
|
+
return { error: "manifest.autoFit: Expected the exact plan derived from scene", ok: false };
|
|
37
49
|
}
|
|
38
50
|
return {
|
|
39
51
|
manifest: {
|
|
40
52
|
...parsed.data,
|
|
53
|
+
...autoFit === void 0 ? {} : { autoFit },
|
|
41
54
|
scene: sceneValidation.scene
|
|
42
55
|
},
|
|
43
56
|
ok: true
|
|
44
57
|
};
|
|
45
58
|
}
|
|
46
59
|
function createRenderManifest(input) {
|
|
60
|
+
const scene = normalizeStaticScene(input.scene);
|
|
61
|
+
const autoFit = expectedAutoFit(scene);
|
|
47
62
|
return staticRenderManifestSchema.parse(
|
|
48
63
|
stripUndefined({
|
|
64
|
+
autoFit,
|
|
49
65
|
mapId: input.mapId,
|
|
50
66
|
rendererVersion: input.rendererVersion,
|
|
51
67
|
schemaVersion: staticRendererSchemaVersion,
|
|
52
|
-
scene
|
|
68
|
+
scene,
|
|
53
69
|
styleId: input.styleId,
|
|
54
70
|
styleRevision: input.styleRevision,
|
|
55
71
|
styleUrl: input.styleUrl
|
|
@@ -57,17 +73,21 @@ function createRenderManifest(input) {
|
|
|
57
73
|
);
|
|
58
74
|
}
|
|
59
75
|
async function hashRenderManifest(manifest) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
});
|
|
64
|
-
return hashStableValue(normalized);
|
|
76
|
+
const validation = validateStaticRenderManifest(manifest);
|
|
77
|
+
if (!validation.ok) throw new Error(`Invalid Tileflow render manifest: ${validation.error}`);
|
|
78
|
+
return hashStableValue(validation.manifest);
|
|
65
79
|
}
|
|
66
80
|
async function hashStaticSceneRequest(scene) {
|
|
67
81
|
const validation = validateStaticScene(scene);
|
|
68
82
|
if (!validation.ok) throw new Error(`Invalid Tileflow static scene: ${validation.error}`);
|
|
69
83
|
return hashStableValue(validation.scene);
|
|
70
84
|
}
|
|
85
|
+
function expectedAutoFit(scene) {
|
|
86
|
+
if (scene.camera.type !== "auto") return void 0;
|
|
87
|
+
const analysis = analyzeStaticAutoFit(scene);
|
|
88
|
+
if (!analysis.ok) throw new Error(`Invalid Tileflow auto-fit scene: ${analysis.error}`);
|
|
89
|
+
return analysis.plan;
|
|
90
|
+
}
|
|
71
91
|
|
|
72
92
|
export {
|
|
73
93
|
staticRendererSchemaVersion,
|
package/dist/client.d.ts
CHANGED
package/dist/client.js
CHANGED
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
staticMapProcessingResultSchema,
|
|
8
8
|
staticMapReadyResultSchema,
|
|
9
9
|
validateStaticMapIdempotencyKey
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-A23RC4BE.js";
|
|
11
|
+
import "./chunk-NHQK5UZ2.js";
|
|
12
12
|
import {
|
|
13
13
|
stableStringify
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-MGQCHCU3.js";
|
|
15
15
|
export {
|
|
16
16
|
createStaticMap,
|
|
17
17
|
createStaticMapIdempotencyKey,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { normalizeStaticScene, validateStaticScene } from './scene.js';
|
|
1
|
+
export { StaticAutoFitErrorResponse, StaticAutoFitFailure, StaticMapRequestError, StaticMapRequestErrorResponse, StaticMapRequestFailure, normalizeStaticScene, staticMapRequestErrorResponseSchema, validateStaticScene } from './scene.js';
|
|
2
2
|
export { circle, compileStaticOverlays, line, marker, polygon } from './overlays.js';
|
|
3
3
|
export { StaticRenderManifest, createRenderManifest, hashRenderManifest, hashStaticSceneRequest, staticRenderManifestSchema, staticRendererSchemaVersion, validateStaticRenderManifest } from './manifest.js';
|
|
4
4
|
export { PreparedStaticMapRequest, StaticMapCreateOptions, StaticMapEndpointRequestOptions, StaticMapResult, createStaticMap, createStaticMapIdempotencyKey, precacheStaticMap, prepareStaticMapRequest, requestStaticMapUntilReady, stableStringify, staticMapProcessingResultSchema, staticMapReadyResultSchema, validateStaticMapIdempotencyKey } from './client.js';
|
|
5
|
-
export { S as StaticCoordinate, a as StaticOverlay, b as StaticOverlayInput, c as
|
|
5
|
+
export { M as MAX_OVERLAY_LATITUDE, S as StaticCoordinate, a as StaticOverlay, b as StaticOverlayInput, c as StaticPadding, d as StaticScene, e as StaticSceneInput, s as staticOverlaySchema, f as staticSceneLimits, g as staticSceneSchema, h as staticSceneSchemaVersion } from './scene-contract-DZMhLDnf.js';
|
|
6
6
|
import 'zod';
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
staticMapProcessingResultSchema,
|
|
8
8
|
staticMapReadyResultSchema,
|
|
9
9
|
validateStaticMapIdempotencyKey
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-A23RC4BE.js";
|
|
11
11
|
import {
|
|
12
12
|
createRenderManifest,
|
|
13
13
|
hashRenderManifest,
|
|
@@ -15,26 +15,31 @@ import {
|
|
|
15
15
|
staticRenderManifestSchema,
|
|
16
16
|
staticRendererSchemaVersion,
|
|
17
17
|
validateStaticRenderManifest
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-S3WXE5P4.js";
|
|
19
19
|
import {
|
|
20
20
|
circle,
|
|
21
21
|
compileStaticOverlays,
|
|
22
22
|
line,
|
|
23
23
|
marker,
|
|
24
24
|
polygon
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-KPT7PASB.js";
|
|
26
26
|
import {
|
|
27
|
+
StaticMapRequestError,
|
|
27
28
|
normalizeStaticScene,
|
|
29
|
+
staticMapRequestErrorResponseSchema,
|
|
28
30
|
validateStaticScene
|
|
29
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-NHQK5UZ2.js";
|
|
30
32
|
import {
|
|
33
|
+
MAX_OVERLAY_LATITUDE,
|
|
31
34
|
stableStringify,
|
|
32
35
|
staticOverlaySchema,
|
|
33
36
|
staticSceneLimits,
|
|
34
37
|
staticSceneSchema,
|
|
35
38
|
staticSceneSchemaVersion
|
|
36
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-MGQCHCU3.js";
|
|
37
40
|
export {
|
|
41
|
+
MAX_OVERLAY_LATITUDE,
|
|
42
|
+
StaticMapRequestError,
|
|
38
43
|
circle,
|
|
39
44
|
compileStaticOverlays,
|
|
40
45
|
createRenderManifest,
|
|
@@ -52,6 +57,7 @@ export {
|
|
|
52
57
|
stableStringify,
|
|
53
58
|
staticMapProcessingResultSchema,
|
|
54
59
|
staticMapReadyResultSchema,
|
|
60
|
+
staticMapRequestErrorResponseSchema,
|
|
55
61
|
staticOverlaySchema,
|
|
56
62
|
staticRenderManifestSchema,
|
|
57
63
|
staticRendererSchemaVersion,
|
package/dist/manifest.d.ts
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { e as StaticSceneInput } from './scene-contract-DZMhLDnf.js';
|
|
3
3
|
|
|
4
4
|
declare const staticRendererSchemaVersion = 1;
|
|
5
5
|
declare const staticRenderManifestSchema: z.ZodObject<{
|
|
6
|
+
autoFit: z.ZodOptional<z.ZodObject<{
|
|
7
|
+
bounds: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
|
|
8
|
+
longitudeOffsets: z.ZodArray<z.ZodNumber>;
|
|
9
|
+
nominalInsets: z.ZodObject<{
|
|
10
|
+
bottom: z.ZodNumber;
|
|
11
|
+
left: z.ZodNumber;
|
|
12
|
+
right: z.ZodNumber;
|
|
13
|
+
top: z.ZodNumber;
|
|
14
|
+
}, z.core.$strict>;
|
|
15
|
+
requiredInsets: z.ZodObject<{
|
|
16
|
+
bottom: z.ZodNumber;
|
|
17
|
+
left: z.ZodNumber;
|
|
18
|
+
right: z.ZodNumber;
|
|
19
|
+
top: z.ZodNumber;
|
|
20
|
+
}, z.core.$strict>;
|
|
21
|
+
}, z.core.$strict>>;
|
|
6
22
|
mapId: z.ZodString;
|
|
7
23
|
rendererVersion: z.ZodString;
|
|
8
24
|
schemaVersion: z.ZodLiteral<1>;
|
|
@@ -17,6 +33,16 @@ declare const staticRenderManifestSchema: z.ZodObject<{
|
|
|
17
33
|
bounds: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
|
|
18
34
|
padding: z.ZodOptional<z.ZodNumber>;
|
|
19
35
|
type: z.ZodLiteral<"bounds">;
|
|
36
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
37
|
+
bearing: z.ZodOptional<z.ZodNumber>;
|
|
38
|
+
maxZoom: z.ZodOptional<z.ZodNumber>;
|
|
39
|
+
padding: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
|
|
40
|
+
bottom: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
left: z.ZodOptional<z.ZodNumber>;
|
|
42
|
+
right: z.ZodOptional<z.ZodNumber>;
|
|
43
|
+
top: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
}, z.core.$strict>]>>;
|
|
45
|
+
type: z.ZodLiteral<"auto">;
|
|
20
46
|
}, z.core.$strip>], "type">;
|
|
21
47
|
map: z.ZodString;
|
|
22
48
|
overlays: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|