@tileflow/static 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 +91 -17
- package/dist/chunk-6DWVCK64.js +406 -0
- package/dist/chunk-HVVIAOBE.js +175 -0
- package/dist/{chunk-MSQ4OLKA.js → chunk-N63IFMFM.js} +22 -22
- package/dist/{chunk-EMCKSFZV.js → chunk-TBI5AED6.js} +172 -52
- package/dist/{chunk-TQMKOTBE.js → chunk-XMT7VJL5.js} +70 -60
- package/dist/client.d.ts +15 -21
- package/dist/client.js +10 -7
- package/dist/errors-B9rwehK0.d.ts +21 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +35 -23
- package/dist/manifest.d.ts +234 -373
- package/dist/manifest.js +9 -15
- package/dist/overlays.d.ts +9 -3
- package/dist/overlays.js +6 -4
- package/dist/scene-contract-Cr6BNLz0.d.ts +734 -0
- package/dist/scene.d.ts +86 -5
- package/dist/scene.js +17 -3
- package/package.json +3 -6
- package/GENERATED_OUTPUT_LICENSE.md +0 -21
- package/NOTICE +0 -9
- package/TRADEMARKS.md +0 -10
- package/dist/chunk-EPOYQNNT.js +0 -122
- package/dist/chunk-NM2JSFUF.js +0 -252
- package/dist/scene-contract-OMIOisSB.d.ts +0 -204
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeStaticOverlay,
|
|
3
|
+
roundNumber
|
|
4
|
+
} from "./chunk-6DWVCK64.js";
|
|
5
|
+
|
|
6
|
+
// src/overlays.ts
|
|
7
|
+
function line(input) {
|
|
8
|
+
return normalizeStaticOverlay({ ...input, type: "line" });
|
|
9
|
+
}
|
|
10
|
+
function circle(input) {
|
|
11
|
+
return normalizeStaticOverlay({ ...input, type: "circle" });
|
|
12
|
+
}
|
|
13
|
+
function marker(input) {
|
|
14
|
+
return normalizeStaticOverlay({ ...input, type: "marker" });
|
|
15
|
+
}
|
|
16
|
+
function polygon(input) {
|
|
17
|
+
return normalizeStaticOverlay({ ...input, type: "polygon" });
|
|
18
|
+
}
|
|
19
|
+
function symbol(input) {
|
|
20
|
+
return normalizeStaticOverlay({ ...input, type: "symbol" });
|
|
21
|
+
}
|
|
22
|
+
function compileStaticOverlays(overlays, options = {}) {
|
|
23
|
+
if (options.longitudeOffsets !== void 0 && (options.longitudeOffsets.length !== overlays.length || options.longitudeOffsets.some(
|
|
24
|
+
(offset) => !Number.isInteger(offset) || Math.abs(offset) > 360 || offset % 360 !== 0
|
|
25
|
+
))) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
"Static overlay longitude offsets must contain one -360, 0, or 360 per overlay"
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
const sources = {};
|
|
31
|
+
const layers = [];
|
|
32
|
+
const placements = {};
|
|
33
|
+
const symbols = [];
|
|
34
|
+
const pushLayer = (layer, overlay) => {
|
|
35
|
+
const layerId = String(layer.id);
|
|
36
|
+
layers.push(layer);
|
|
37
|
+
placements[layerId] = overlay.placement ?? "above-labels";
|
|
38
|
+
};
|
|
39
|
+
for (const [index, overlay] of overlays.entries()) {
|
|
40
|
+
const longitudeOffset = options.longitudeOffsets?.[index] ?? 0;
|
|
41
|
+
const id = safeLayerId(`tileflow-static-overlay-${index + 1}-${overlay.id ?? overlay.type}`);
|
|
42
|
+
const sourceId = `${id}-source`;
|
|
43
|
+
if (overlay.type === "line") {
|
|
44
|
+
sources[sourceId] = {
|
|
45
|
+
data: feature("LineString", shiftLongitudes(overlay.coordinates, longitudeOffset)),
|
|
46
|
+
type: "geojson"
|
|
47
|
+
};
|
|
48
|
+
pushLayer(
|
|
49
|
+
{
|
|
50
|
+
id,
|
|
51
|
+
layout: { "line-cap": "round", "line-join": "round" },
|
|
52
|
+
paint: {
|
|
53
|
+
"line-color": overlay.color,
|
|
54
|
+
"line-opacity": overlay.opacity,
|
|
55
|
+
"line-width": overlay.width
|
|
56
|
+
},
|
|
57
|
+
source: sourceId,
|
|
58
|
+
type: "line"
|
|
59
|
+
},
|
|
60
|
+
overlay
|
|
61
|
+
);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (overlay.type === "polygon") {
|
|
65
|
+
sources[sourceId] = {
|
|
66
|
+
data: feature("Polygon", shiftLongitudes(overlay.coordinates, longitudeOffset)),
|
|
67
|
+
type: "geojson"
|
|
68
|
+
};
|
|
69
|
+
pushLayer(
|
|
70
|
+
{
|
|
71
|
+
id,
|
|
72
|
+
paint: {
|
|
73
|
+
"fill-color": overlay.fill,
|
|
74
|
+
"fill-opacity": overlay.opacity
|
|
75
|
+
},
|
|
76
|
+
source: sourceId,
|
|
77
|
+
type: "fill"
|
|
78
|
+
},
|
|
79
|
+
overlay
|
|
80
|
+
);
|
|
81
|
+
if (overlay.stroke && overlay.strokeWidth > 0) {
|
|
82
|
+
pushLayer(
|
|
83
|
+
{
|
|
84
|
+
id: `${id}-stroke`,
|
|
85
|
+
layout: { "line-cap": "round", "line-join": "round" },
|
|
86
|
+
paint: {
|
|
87
|
+
"line-color": overlay.stroke,
|
|
88
|
+
"line-width": overlay.strokeWidth
|
|
89
|
+
},
|
|
90
|
+
source: sourceId,
|
|
91
|
+
type: "line"
|
|
92
|
+
},
|
|
93
|
+
overlay
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
sources[sourceId] = {
|
|
99
|
+
data: feature("Point", shiftLongitudes(overlay.coordinate, longitudeOffset)),
|
|
100
|
+
type: "geojson"
|
|
101
|
+
};
|
|
102
|
+
if (overlay.type === "symbol") {
|
|
103
|
+
const composed = overlay.label !== void 0;
|
|
104
|
+
const imageId = composed ? safeLayerId(`__tileflow-static-symbol-${index + 1}-${overlay.id}`) : overlay.icon;
|
|
105
|
+
const alwaysVisible = overlay.collision === "always-visible";
|
|
106
|
+
const iconSize = composed ? 1 : overlay.scale;
|
|
107
|
+
const iconOffset = composed ? overlay.offset : overlay.offset.map((value) => roundNumber(value / overlay.scale));
|
|
108
|
+
pushLayer(
|
|
109
|
+
{
|
|
110
|
+
id,
|
|
111
|
+
layout: {
|
|
112
|
+
"icon-allow-overlap": alwaysVisible,
|
|
113
|
+
"icon-anchor": overlay.anchor,
|
|
114
|
+
"icon-ignore-placement": alwaysVisible,
|
|
115
|
+
"icon-image": imageId,
|
|
116
|
+
"icon-offset": iconOffset,
|
|
117
|
+
"icon-pitch-alignment": "viewport",
|
|
118
|
+
"icon-rotation-alignment": "viewport",
|
|
119
|
+
"icon-size": iconSize,
|
|
120
|
+
"symbol-placement": "point",
|
|
121
|
+
"symbol-z-order": "source"
|
|
122
|
+
},
|
|
123
|
+
paint: { "icon-opacity": overlay.opacity },
|
|
124
|
+
source: sourceId,
|
|
125
|
+
type: "symbol"
|
|
126
|
+
},
|
|
127
|
+
overlay
|
|
128
|
+
);
|
|
129
|
+
symbols.push({ imageId, overlayIndex: index });
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
pushLayer(
|
|
133
|
+
{
|
|
134
|
+
id,
|
|
135
|
+
paint: {
|
|
136
|
+
"circle-color": overlay.color,
|
|
137
|
+
"circle-opacity": overlay.type === "circle" ? overlay.opacity : 1,
|
|
138
|
+
"circle-radius": overlay.radius,
|
|
139
|
+
"circle-stroke-color": overlay.strokeColor ?? overlay.color,
|
|
140
|
+
"circle-stroke-width": overlay.strokeWidth
|
|
141
|
+
},
|
|
142
|
+
source: sourceId,
|
|
143
|
+
type: "circle"
|
|
144
|
+
},
|
|
145
|
+
overlay
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
return { layers, placements, sources, symbols };
|
|
149
|
+
}
|
|
150
|
+
function shiftLongitudes(value, offset) {
|
|
151
|
+
if (!Array.isArray(value)) return value;
|
|
152
|
+
if (value.length === 2 && typeof value[0] === "number" && typeof value[1] === "number") {
|
|
153
|
+
return [roundNumber(value[0] + offset), value[1]];
|
|
154
|
+
}
|
|
155
|
+
return value.map((entry) => shiftLongitudes(entry, offset));
|
|
156
|
+
}
|
|
157
|
+
function feature(type, coordinates) {
|
|
158
|
+
return {
|
|
159
|
+
geometry: { coordinates, type },
|
|
160
|
+
properties: {},
|
|
161
|
+
type: "Feature"
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function safeLayerId(value) {
|
|
165
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, "-").slice(0, 80);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export {
|
|
169
|
+
line,
|
|
170
|
+
circle,
|
|
171
|
+
marker,
|
|
172
|
+
polygon,
|
|
173
|
+
symbol,
|
|
174
|
+
compileStaticOverlays
|
|
175
|
+
};
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
|
+
StaticMapError,
|
|
2
3
|
StaticMapRequestError,
|
|
4
|
+
staticMapErrorResponseSchema,
|
|
3
5
|
staticMapRequestErrorResponseSchema,
|
|
4
6
|
validateStaticScene
|
|
5
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-TBI5AED6.js";
|
|
6
8
|
import {
|
|
7
9
|
isSafeHttpUrl,
|
|
8
10
|
jsonByteLength,
|
|
9
11
|
stableStringify
|
|
10
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-6DWVCK64.js";
|
|
11
13
|
|
|
12
14
|
// src/client.ts
|
|
13
15
|
import { z } from "zod";
|
|
14
16
|
var maxStaticMapResponseBytes = 64 * 1024;
|
|
15
17
|
var staticMapIdempotencyKeyPattern = /^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/;
|
|
16
|
-
var
|
|
18
|
+
var STATIC_MAP_RESULT_MEDIA_TYPE = "application/vnd.tileflow.static-map-result+json;version=1";
|
|
17
19
|
var preparedStaticMapRequestBodies = /* @__PURE__ */ new WeakMap();
|
|
18
|
-
var
|
|
20
|
+
var staticMapReadyResultBaseSchema = z.object({
|
|
19
21
|
cached: z.boolean(),
|
|
20
22
|
hash: z.string().regex(/^[A-Za-z0-9_-]{43}$/),
|
|
21
23
|
imageUrl: z.string().trim().url().max(2048).refine(isSafeHttpUrl, { message: "Expected an http(s) URL without credentials" }),
|
|
@@ -53,9 +55,9 @@ var staticMapAttributionResultSchema = z.object({
|
|
|
53
55
|
context.addIssue({ code: "custom", message: "Attribution result exceeds 32 KiB" });
|
|
54
56
|
}
|
|
55
57
|
});
|
|
56
|
-
var staticMapHostedResultSchema =
|
|
58
|
+
var staticMapHostedResultSchema = staticMapReadyResultBaseSchema.extend({
|
|
57
59
|
attribution: staticMapAttributionResultSchema,
|
|
58
|
-
resultVersion: z.literal(
|
|
60
|
+
resultVersion: z.literal(1)
|
|
59
61
|
}).strict();
|
|
60
62
|
var staticMapProcessingResultSchema = z.object({
|
|
61
63
|
operationId: z.string().min(20).max(68),
|
|
@@ -127,7 +129,7 @@ async function requestStaticMapUntilReady(request, options) {
|
|
|
127
129
|
const fetcher = options.fetch ?? fetch;
|
|
128
130
|
const createUrl = normalizeStaticMapEndpointUrl(options.createUrl);
|
|
129
131
|
const headers = {
|
|
130
|
-
Accept:
|
|
132
|
+
Accept: STATIC_MAP_RESULT_MEDIA_TYPE,
|
|
131
133
|
"Content-Type": "application/json",
|
|
132
134
|
"Idempotency-Key": idempotency.key
|
|
133
135
|
};
|
|
@@ -145,10 +147,17 @@ async function requestStaticMapUntilReady(request, options) {
|
|
|
145
147
|
});
|
|
146
148
|
throwIfAborted(signal);
|
|
147
149
|
if (!response.ok) {
|
|
148
|
-
const
|
|
150
|
+
const errorBody = await readStaticMapErrorBody(response, 8 * 1024);
|
|
149
151
|
throwIfAborted(signal);
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
+
if (response.status === 422) {
|
|
153
|
+
const requestError = staticMapRequestErrorResponseSchema.safeParse(errorBody);
|
|
154
|
+
if (requestError.success) {
|
|
155
|
+
throw new StaticMapRequestError(requestError.data, response.status);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const structured = staticMapErrorResponseSchema.safeParse(errorBody);
|
|
159
|
+
if (structured.success) {
|
|
160
|
+
throw new StaticMapError(structured.data, response.status);
|
|
152
161
|
}
|
|
153
162
|
throw new Error(`Tileflow static map failed (${response.status}).`);
|
|
154
163
|
}
|
|
@@ -199,22 +208,14 @@ async function readJsonResponse(response) {
|
|
|
199
208
|
throw new Error("Tileflow static map returned an invalid response: expected JSON");
|
|
200
209
|
}
|
|
201
210
|
}
|
|
202
|
-
async function
|
|
211
|
+
async function readStaticMapErrorBody(response, maximumBytes) {
|
|
203
212
|
try {
|
|
204
213
|
const source = await readBoundedResponseText(response, maximumBytes, `${maximumBytes} bytes`);
|
|
205
|
-
|
|
206
|
-
return parsed.success ? parsed.data : null;
|
|
214
|
+
return JSON.parse(source);
|
|
207
215
|
} catch {
|
|
208
216
|
return null;
|
|
209
217
|
}
|
|
210
218
|
}
|
|
211
|
-
async function discardBoundedResponse(response, maximumBytes) {
|
|
212
|
-
try {
|
|
213
|
-
await readBoundedResponseText(response, maximumBytes, `${maximumBytes} bytes`);
|
|
214
|
-
} catch {
|
|
215
|
-
}
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
218
219
|
function isStaticMapRequestFailure(value) {
|
|
219
220
|
if (!("code" in value)) return false;
|
|
220
221
|
const { ok: _ok, ...response } = value;
|
|
@@ -359,8 +360,7 @@ function hasControlCharacter(value) {
|
|
|
359
360
|
}
|
|
360
361
|
|
|
361
362
|
export {
|
|
362
|
-
|
|
363
|
-
staticMapReadyResultSchema,
|
|
363
|
+
STATIC_MAP_RESULT_MEDIA_TYPE,
|
|
364
364
|
staticMapAttributionEntrySchema,
|
|
365
365
|
staticMapAttributionResultSchema,
|
|
366
366
|
staticMapHostedResultSchema,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MAX_OVERLAY_LATITUDE,
|
|
3
|
+
isSupportedStaticSymbolCodePoint,
|
|
3
4
|
jsonByteLength,
|
|
4
5
|
normalizeStaticCoordinate,
|
|
5
6
|
normalizeStaticOverlay,
|
|
@@ -8,90 +9,166 @@ import {
|
|
|
8
9
|
staticSceneLimits,
|
|
9
10
|
staticSceneSchema,
|
|
10
11
|
stripUndefined
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-6DWVCK64.js";
|
|
12
13
|
|
|
13
14
|
// src/auto-fit.ts
|
|
15
|
+
import { z as z2 } from "zod";
|
|
16
|
+
|
|
17
|
+
// src/errors.ts
|
|
14
18
|
import { z } from "zod";
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
var safeErrorTextSchema = z.string().min(1).max(512).refine(hasNoControlCharacters, { message: "Expected no control characters" });
|
|
20
|
+
var safeErrorIdentifierSchema = z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/u);
|
|
21
|
+
var staticMapErrorResponseSchema = z.object({
|
|
22
|
+
code: safeErrorIdentifierSchema.optional(),
|
|
23
|
+
error: safeErrorTextSchema,
|
|
24
|
+
remainingUnits: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
25
|
+
requestId: safeErrorIdentifierSchema.optional(),
|
|
26
|
+
retryable: z.boolean().optional()
|
|
27
|
+
}).strip();
|
|
28
|
+
var StaticMapError = class extends Error {
|
|
29
|
+
code;
|
|
30
|
+
remainingUnits;
|
|
31
|
+
requestId;
|
|
32
|
+
response;
|
|
33
|
+
retryable;
|
|
34
|
+
status;
|
|
35
|
+
constructor(response, status) {
|
|
36
|
+
const parsed = staticMapErrorResponseSchema.parse(response);
|
|
37
|
+
super(parsed.error);
|
|
38
|
+
this.name = "StaticMapError";
|
|
39
|
+
this.code = parsed.code ?? null;
|
|
40
|
+
this.remainingUnits = parsed.remainingUnits ?? null;
|
|
41
|
+
this.requestId = parsed.requestId ?? null;
|
|
42
|
+
this.response = Object.freeze(parsed);
|
|
43
|
+
this.retryable = parsed.retryable ?? null;
|
|
44
|
+
this.status = status;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
function hasNoControlCharacters(value) {
|
|
48
|
+
return !Array.from(value).some((character) => {
|
|
49
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
50
|
+
return codePoint <= 31 || codePoint === 127;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/auto-fit.ts
|
|
55
|
+
var autoFitOverlayReferenceSchema = z2.object({
|
|
56
|
+
id: z2.string().min(1).max(64),
|
|
57
|
+
index: z2.number().int().min(0).max(23),
|
|
58
|
+
type: z2.enum(["circle", "line", "marker", "polygon", "symbol"])
|
|
19
59
|
}).strict();
|
|
20
|
-
var autoFitViewportSchema =
|
|
21
|
-
height:
|
|
22
|
-
width:
|
|
60
|
+
var autoFitViewportSchema = z2.object({
|
|
61
|
+
height: z2.number().int().min(64).max(1280),
|
|
62
|
+
width: z2.number().int().min(64).max(1280)
|
|
23
63
|
}).strict();
|
|
24
|
-
var autoFitDetailsSchema =
|
|
64
|
+
var autoFitDetailsSchema = z2.object({
|
|
25
65
|
overlay: autoFitOverlayReferenceSchema.optional(),
|
|
26
66
|
padding: staticPaddingSchema.optional(),
|
|
27
|
-
projection:
|
|
67
|
+
projection: z2.enum(["globe", "mercator"]).optional(),
|
|
28
68
|
requiredInsets: staticPaddingSchema.optional(),
|
|
29
|
-
ringIndex:
|
|
30
|
-
segmentIndex:
|
|
69
|
+
ringIndex: z2.number().int().min(0).max(15).optional(),
|
|
70
|
+
segmentIndex: z2.number().int().min(0).max(1999).optional(),
|
|
31
71
|
viewport: autoFitViewportSchema.optional()
|
|
32
72
|
}).strict();
|
|
33
|
-
var staticOverlayInvalidDetailsSchema =
|
|
34
|
-
latitude:
|
|
35
|
-
limit:
|
|
73
|
+
var staticOverlayInvalidDetailsSchema = z2.object({
|
|
74
|
+
latitude: z2.number().finite(),
|
|
75
|
+
limit: z2.literal(MAX_OVERLAY_LATITUDE),
|
|
36
76
|
overlay: autoFitOverlayReferenceSchema
|
|
37
77
|
}).strict();
|
|
78
|
+
var staticLabelUnsupportedDetailsSchema = z2.object({
|
|
79
|
+
codePoint: z2.number().int().min(0).max(1114111),
|
|
80
|
+
overlay: autoFitOverlayReferenceSchema.extend({ type: z2.literal("symbol") }).strict()
|
|
81
|
+
}).strict();
|
|
82
|
+
var staticIconUnavailableDetailsSchema = z2.object({
|
|
83
|
+
icon: z2.string().max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/u),
|
|
84
|
+
overlay: autoFitOverlayReferenceSchema.extend({ type: z2.literal("symbol") }).strict()
|
|
85
|
+
}).strict();
|
|
86
|
+
var staticSymbolTooLargeDetailsSchema = z2.object({
|
|
87
|
+
height: z2.number().finite().positive().max(16384),
|
|
88
|
+
limit: z2.literal(2048),
|
|
89
|
+
overlay: autoFitOverlayReferenceSchema.extend({ type: z2.literal("symbol") }).strict(),
|
|
90
|
+
width: z2.number().finite().positive().max(16384)
|
|
91
|
+
}).strict();
|
|
38
92
|
var autoFitErrorBase = {
|
|
39
|
-
error:
|
|
40
|
-
retryable:
|
|
93
|
+
error: z2.string().min(1).max(512),
|
|
94
|
+
retryable: z2.literal(false)
|
|
41
95
|
};
|
|
42
|
-
var staticMapRequestErrorResponseSchema =
|
|
43
|
-
|
|
96
|
+
var staticMapRequestErrorResponseSchema = z2.discriminatedUnion("code", [
|
|
97
|
+
z2.object({
|
|
44
98
|
...autoFitErrorBase,
|
|
45
|
-
code:
|
|
46
|
-
reason:
|
|
99
|
+
code: z2.literal("AUTO_FIT_EMPTY"),
|
|
100
|
+
reason: z2.literal("NO_FITTABLE_OVERLAYS")
|
|
47
101
|
}).strict(),
|
|
48
|
-
|
|
102
|
+
z2.object({
|
|
49
103
|
...autoFitErrorBase,
|
|
50
|
-
code:
|
|
104
|
+
code: z2.literal("AUTO_FIT_AMBIGUOUS"),
|
|
51
105
|
details: autoFitDetailsSchema,
|
|
52
|
-
reason:
|
|
106
|
+
reason: z2.literal("ANTIMERIDIAN_WRAP_REQUIRED")
|
|
53
107
|
}).strict(),
|
|
54
|
-
|
|
108
|
+
z2.object({
|
|
55
109
|
...autoFitErrorBase,
|
|
56
|
-
code:
|
|
110
|
+
code: z2.literal("AUTO_FIT_IMPOSSIBLE"),
|
|
57
111
|
details: autoFitDetailsSchema.optional(),
|
|
58
|
-
reason:
|
|
112
|
+
reason: z2.enum([
|
|
59
113
|
"GLOBE_NOT_SIMULTANEOUSLY_VISIBLE",
|
|
60
114
|
"INSUFFICIENT_VIEWPORT",
|
|
61
115
|
"CAMERA_UNRESOLVABLE",
|
|
62
116
|
"PROJECTED_FOOTPRINT_OUTSIDE_VIEWPORT"
|
|
63
117
|
])
|
|
64
118
|
}).strict(),
|
|
65
|
-
|
|
119
|
+
z2.object({
|
|
66
120
|
...autoFitErrorBase,
|
|
67
|
-
code:
|
|
121
|
+
code: z2.literal("STATIC_OVERLAY_INVALID"),
|
|
68
122
|
details: staticOverlayInvalidDetailsSchema,
|
|
69
|
-
reason:
|
|
123
|
+
reason: z2.literal("OVERLAY_LATITUDE_OUT_OF_RANGE")
|
|
124
|
+
}).strict(),
|
|
125
|
+
z2.object({
|
|
126
|
+
...autoFitErrorBase,
|
|
127
|
+
code: z2.literal("STATIC_MAP_LABEL_UNSUPPORTED"),
|
|
128
|
+
details: staticLabelUnsupportedDetailsSchema,
|
|
129
|
+
reason: z2.literal("UNSUPPORTED_GLYPH")
|
|
70
130
|
}).strict(),
|
|
71
|
-
|
|
131
|
+
z2.object({
|
|
72
132
|
...autoFitErrorBase,
|
|
73
|
-
code:
|
|
74
|
-
|
|
133
|
+
code: z2.literal("STATIC_MAP_ICON_UNAVAILABLE"),
|
|
134
|
+
details: staticIconUnavailableDetailsSchema,
|
|
135
|
+
reason: z2.enum(["ICON_NOT_FOUND", "MANAGED_SPRITE_REQUIRED"])
|
|
75
136
|
}).strict(),
|
|
76
|
-
|
|
137
|
+
z2.object({
|
|
77
138
|
...autoFitErrorBase,
|
|
78
|
-
code:
|
|
79
|
-
reason:
|
|
139
|
+
code: z2.literal("STATIC_MAP_PLACEMENT_UNAVAILABLE"),
|
|
140
|
+
reason: z2.literal("MAP_REDEPLOY_REQUIRED")
|
|
80
141
|
}).strict(),
|
|
81
|
-
|
|
142
|
+
z2.object({
|
|
82
143
|
...autoFitErrorBase,
|
|
83
|
-
code:
|
|
84
|
-
|
|
144
|
+
code: z2.literal("STATIC_MAP_SYMBOL_TOO_LARGE"),
|
|
145
|
+
details: staticSymbolTooLargeDetailsSchema,
|
|
146
|
+
reason: z2.literal("COMPOSED_IMAGE_TOO_LARGE")
|
|
147
|
+
}).strict(),
|
|
148
|
+
z2.object({
|
|
149
|
+
...autoFitErrorBase,
|
|
150
|
+
code: z2.literal("STATIC_MAP_ATTRIBUTION_UNSUPPORTED"),
|
|
151
|
+
reason: z2.enum(["UNSUPPORTED_DECLARATION", "UNSUPPORTED_GLYPH"])
|
|
152
|
+
}).strict(),
|
|
153
|
+
z2.object({
|
|
154
|
+
...autoFitErrorBase,
|
|
155
|
+
code: z2.literal("STATIC_MAP_ATTRIBUTION_TOO_LARGE"),
|
|
156
|
+
reason: z2.literal("CONTENT_LIMIT_EXCEEDED")
|
|
157
|
+
}).strict(),
|
|
158
|
+
z2.object({
|
|
159
|
+
...autoFitErrorBase,
|
|
160
|
+
code: z2.literal("STATIC_MAP_ATTRIBUTION_DOES_NOT_FIT"),
|
|
161
|
+
reason: z2.literal("BLOCK_DOES_NOT_FIT")
|
|
85
162
|
}).strict()
|
|
86
163
|
]);
|
|
87
|
-
var StaticMapRequestError = class extends
|
|
164
|
+
var StaticMapRequestError = class extends StaticMapError {
|
|
88
165
|
code;
|
|
89
166
|
details;
|
|
90
167
|
reason;
|
|
91
168
|
retryable = false;
|
|
92
169
|
status;
|
|
93
170
|
constructor(response, status = 422) {
|
|
94
|
-
super(response
|
|
171
|
+
super(response, status);
|
|
95
172
|
this.name = "StaticMapRequestError";
|
|
96
173
|
this.code = response.code;
|
|
97
174
|
this.details = "details" in response ? response.details : void 0;
|
|
@@ -99,14 +176,14 @@ var StaticMapRequestError = class extends Error {
|
|
|
99
176
|
this.status = status;
|
|
100
177
|
}
|
|
101
178
|
};
|
|
102
|
-
var staticAutoFitPlanSchema =
|
|
103
|
-
bounds:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
179
|
+
var staticAutoFitPlanSchema = z2.object({
|
|
180
|
+
bounds: z2.tuple([
|
|
181
|
+
z2.number().finite(),
|
|
182
|
+
z2.number().finite().min(-90).max(90),
|
|
183
|
+
z2.number().finite(),
|
|
184
|
+
z2.number().finite().min(-90).max(90)
|
|
108
185
|
]),
|
|
109
|
-
longitudeOffsets:
|
|
186
|
+
longitudeOffsets: z2.array(z2.number().int().min(-360).max(360)).max(24),
|
|
110
187
|
nominalInsets: staticPaddingSchema,
|
|
111
188
|
requiredInsets: staticPaddingSchema
|
|
112
189
|
}).strict();
|
|
@@ -214,7 +291,7 @@ function failure(response) {
|
|
|
214
291
|
return { ...response, ok: false };
|
|
215
292
|
}
|
|
216
293
|
function overlayCoordinates(overlay) {
|
|
217
|
-
if (overlay.type === "circle" || overlay.type === "marker") {
|
|
294
|
+
if (overlay.type === "circle" || overlay.type === "marker" || overlay.type === "symbol") {
|
|
218
295
|
return [overlay.coordinate];
|
|
219
296
|
}
|
|
220
297
|
if (overlay.type === "line") {
|
|
@@ -223,7 +300,8 @@ function overlayCoordinates(overlay) {
|
|
|
223
300
|
return overlay.coordinates.flat();
|
|
224
301
|
}
|
|
225
302
|
function findAmbiguousSegment(overlay) {
|
|
226
|
-
if (overlay.type === "circle" || overlay.type === "marker"
|
|
303
|
+
if (overlay.type === "circle" || overlay.type === "marker" || overlay.type === "symbol")
|
|
304
|
+
return null;
|
|
227
305
|
const paths = overlay.type === "line" ? [overlay.coordinates] : overlay.coordinates;
|
|
228
306
|
for (const [ringIndex, path] of paths.entries()) {
|
|
229
307
|
for (let segmentIndex = 0; segmentIndex < path.length - 1; segmentIndex += 1) {
|
|
@@ -243,6 +321,7 @@ function nominalOverlayExpansion(overlay) {
|
|
|
243
321
|
if (overlay.type === "circle" || overlay.type === "marker") {
|
|
244
322
|
return overlay.radius + overlay.strokeWidth;
|
|
245
323
|
}
|
|
324
|
+
if (overlay.type === "symbol") return 0;
|
|
246
325
|
if (overlay.type === "line") {
|
|
247
326
|
return overlay.width / 2 + 0.5;
|
|
248
327
|
}
|
|
@@ -335,8 +414,8 @@ function findStaticOverlayLatitudeFailure(input) {
|
|
|
335
414
|
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) continue;
|
|
336
415
|
const overlay = candidate;
|
|
337
416
|
const type = overlay.type;
|
|
338
|
-
if (!["circle", "line", "marker", "polygon"].includes(String(type))) continue;
|
|
339
|
-
const coordinates = type === "circle" || type === "marker" ? [overlay.coordinate] : overlayCoordinateCandidates(type, overlay.coordinates);
|
|
417
|
+
if (!["circle", "line", "marker", "polygon", "symbol"].includes(String(type))) continue;
|
|
418
|
+
const coordinates = type === "circle" || type === "marker" || type === "symbol" ? [overlay.coordinate] : overlayCoordinateCandidates(type, overlay.coordinates);
|
|
340
419
|
for (const coordinate of coordinates) {
|
|
341
420
|
if (!Array.isArray(coordinate) || coordinate.length !== 2 || typeof coordinate[1] !== "number" || !Number.isFinite(coordinate[1]) || Math.abs(coordinate[1]) <= MAX_OVERLAY_LATITUDE) {
|
|
342
421
|
continue;
|
|
@@ -362,6 +441,38 @@ function findStaticOverlayLatitudeFailure(input) {
|
|
|
362
441
|
}
|
|
363
442
|
return null;
|
|
364
443
|
}
|
|
444
|
+
function findStaticSymbolLabelGlyphFailure(input) {
|
|
445
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return null;
|
|
446
|
+
const overlays = input.overlays;
|
|
447
|
+
if (!Array.isArray(overlays)) return null;
|
|
448
|
+
for (const [index, candidate] of overlays.entries()) {
|
|
449
|
+
if (index >= staticSceneLimits.maxOverlays) break;
|
|
450
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) continue;
|
|
451
|
+
const overlay = candidate;
|
|
452
|
+
if (overlay.type !== "symbol") continue;
|
|
453
|
+
const label = overlay.label;
|
|
454
|
+
const text = typeof label === "string" ? label : label && typeof label === "object" && !Array.isArray(label) ? label.text : void 0;
|
|
455
|
+
if (typeof text !== "string") continue;
|
|
456
|
+
const unsupported = Array.from(text).find(
|
|
457
|
+
(character) => !isSupportedStaticSymbolCodePoint(character.codePointAt(0))
|
|
458
|
+
);
|
|
459
|
+
if (!unsupported) continue;
|
|
460
|
+
const codePoint = unsupported.codePointAt(0);
|
|
461
|
+
const id = typeof overlay.id === "string" && overlay.id.trim() ? overlay.id.trim() : `overlay-${index + 1}`;
|
|
462
|
+
return {
|
|
463
|
+
code: "STATIC_MAP_LABEL_UNSUPPORTED",
|
|
464
|
+
details: {
|
|
465
|
+
codePoint,
|
|
466
|
+
overlay: { id: id.slice(0, 64), index, type: "symbol" }
|
|
467
|
+
},
|
|
468
|
+
error: `Overlay overlays.${index} label contains unsupported glyph U+${codePoint.toString(16).toUpperCase().padStart(4, "0")}`,
|
|
469
|
+
ok: false,
|
|
470
|
+
reason: "UNSUPPORTED_GLYPH",
|
|
471
|
+
retryable: false
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
365
476
|
function overlayCoordinateCandidates(type, value) {
|
|
366
477
|
if (!Array.isArray(value)) return [];
|
|
367
478
|
if (type === "line") {
|
|
@@ -376,6 +487,8 @@ function overlayCoordinateCandidates(type, value) {
|
|
|
376
487
|
function validateStaticScene(input) {
|
|
377
488
|
const overlayLatitudeFailure = findStaticOverlayLatitudeFailure(input);
|
|
378
489
|
if (overlayLatitudeFailure) return overlayLatitudeFailure;
|
|
490
|
+
const labelGlyphFailure = findStaticSymbolLabelGlyphFailure(input);
|
|
491
|
+
if (labelGlyphFailure) return labelGlyphFailure;
|
|
379
492
|
const parsed = staticSceneSchema.safeParse(input);
|
|
380
493
|
if (!parsed.success) {
|
|
381
494
|
return {
|
|
@@ -402,6 +515,11 @@ function normalizeStaticScene(scene) {
|
|
|
402
515
|
const { ok: _ok, ...response } = overlayLatitudeFailure;
|
|
403
516
|
throw new StaticMapRequestError(response);
|
|
404
517
|
}
|
|
518
|
+
const labelGlyphFailure = findStaticSymbolLabelGlyphFailure(scene);
|
|
519
|
+
if (labelGlyphFailure) {
|
|
520
|
+
const { ok: _ok, ...response } = labelGlyphFailure;
|
|
521
|
+
throw new StaticMapRequestError(response);
|
|
522
|
+
}
|
|
405
523
|
const normalized = normalizeParsedStaticScene(staticSceneSchema.parse(scene));
|
|
406
524
|
if (normalized.camera.type === "auto") {
|
|
407
525
|
const analysis = analyzeStaticAutoFit(normalized);
|
|
@@ -468,6 +586,8 @@ function normalizeAutoPadding(padding, size) {
|
|
|
468
586
|
}
|
|
469
587
|
|
|
470
588
|
export {
|
|
589
|
+
staticMapErrorResponseSchema,
|
|
590
|
+
StaticMapError,
|
|
471
591
|
staticMapRequestErrorResponseSchema,
|
|
472
592
|
StaticMapRequestError,
|
|
473
593
|
staticAutoFitPlanSchema,
|