@tileflow/static 0.1.0-alpha.26 → 0.1.0-alpha.28

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.
@@ -1,380 +0,0 @@
1
- import {
2
- StaticMapError,
3
- StaticMapRequestError,
4
- staticMapErrorResponseSchema,
5
- staticMapRequestErrorResponseSchema,
6
- validateStaticScene
7
- } from "./chunk-TBI5AED6.js";
8
- import {
9
- isSafeHttpUrl,
10
- jsonByteLength,
11
- stableStringify
12
- } from "./chunk-6DWVCK64.js";
13
-
14
- // src/client.ts
15
- import { z } from "zod";
16
- var maxStaticMapResponseBytes = 64 * 1024;
17
- var staticMapIdempotencyKeyPattern = /^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/;
18
- var STATIC_MAP_RESULT_MEDIA_TYPE = "application/vnd.tileflow.static-map-result+json;version=1";
19
- var preparedStaticMapRequestBodies = /* @__PURE__ */ new WeakMap();
20
- var staticMapReadyResultBaseSchema = z.object({
21
- cached: z.boolean(),
22
- hash: z.string().regex(/^[A-Za-z0-9_-]{43}$/),
23
- imageUrl: z.string().trim().url().max(2048).refine(isSafeHttpUrl, { message: "Expected an http(s) URL without credentials" }),
24
- operationId: z.string().min(20).max(68),
25
- remainingUnits: z.number().int().nonnegative().nullable(),
26
- status: z.literal("ready"),
27
- unitCost: z.literal(15)
28
- }).strict();
29
- var safeAttributionTextSchema = z.string().min(1).max(16384).refine(hasNoControlCharacters, { message: "Attribution text contains control characters" });
30
- var staticMapAttributionEntrySchema = z.object({
31
- authority: z.enum(["platform-notice", "team-declared"]),
32
- links: z.array(
33
- z.object({
34
- label: safeAttributionTextSchema,
35
- url: z.string().trim().url().max(2048).refine(isSafeHttpUrl, {
36
- message: "Expected an http(s) URL without credentials or a fragment"
37
- })
38
- }).strict()
39
- ).max(8),
40
- text: safeAttributionTextSchema
41
- }).strict();
42
- var staticMapAttributionResultSchema = z.object({
43
- entries: z.array(staticMapAttributionEntrySchema).max(18),
44
- mode: z.enum(["embedded", "external"]),
45
- position: z.enum(["top-left", "top-right", "bottom-left", "bottom-right"]).nullable()
46
- }).strict().superRefine((result, context) => {
47
- if (result.mode === "external" && result.position !== null || result.mode === "embedded" && result.position === null) {
48
- context.addIssue({
49
- code: "custom",
50
- message: "Attribution position must match its mode",
51
- path: ["position"]
52
- });
53
- }
54
- if (jsonByteLength(result) > 32 * 1024) {
55
- context.addIssue({ code: "custom", message: "Attribution result exceeds 32 KiB" });
56
- }
57
- });
58
- var staticMapHostedResultSchema = staticMapReadyResultBaseSchema.extend({
59
- attribution: staticMapAttributionResultSchema,
60
- resultVersion: z.literal(1)
61
- }).strict();
62
- var staticMapProcessingResultSchema = z.object({
63
- operationId: z.string().min(20).max(68),
64
- retryAfterMs: z.number().int().min(0).max(5e3),
65
- status: z.literal("processing")
66
- }).strict();
67
- function validateStaticMapIdempotencyKey(value) {
68
- if (typeof value !== "string" || !staticMapIdempotencyKeyPattern.test(value)) {
69
- return {
70
- error: "Idempotency key must contain 8-128 ASCII letters, digits, dot, underscore, colon, or hyphen and start with a letter or digit",
71
- ok: false
72
- };
73
- }
74
- return { key: value, ok: true };
75
- }
76
- function createStaticMapIdempotencyKey() {
77
- const key = `static_${crypto.randomUUID()}`;
78
- if (!validateStaticMapIdempotencyKey(key).ok) {
79
- throw new Error("Unable to create a valid Tileflow Static Maps idempotency key");
80
- }
81
- return key;
82
- }
83
- function prepareStaticMapRequest(scene) {
84
- const validation = validateStaticScene(scene);
85
- if (!validation.ok) {
86
- if (isStaticMapRequestFailure(validation)) {
87
- const { ok: _ok, ...response } = validation;
88
- throw new StaticMapRequestError(response);
89
- }
90
- throw new Error(`Invalid Tileflow static scene: ${validation.error}`);
91
- }
92
- const prepared = Object.freeze({
93
- sceneKey: stableStringify(validation.scene)
94
- });
95
- preparedStaticMapRequestBodies.set(prepared, JSON.stringify(validation.scene));
96
- return prepared;
97
- }
98
- async function createStaticMap(scene, options) {
99
- return requestStaticMap(scene, options, "/v1/static/maps");
100
- }
101
- async function precacheStaticMap(scene, options) {
102
- return requestStaticMap(scene, options, "/v1/static/maps/precache");
103
- }
104
- async function requestStaticMap(scene, options, path) {
105
- const preparedRequest = prepareStaticMapRequest(scene);
106
- const { apiUrl = "https://api.tileflow.dev", ...requestOptions } = options;
107
- return requestStaticMapUntilReady(preparedRequest, {
108
- ...requestOptions,
109
- createUrl: `${normalizeUrl(apiUrl)}${path}`
110
- });
111
- }
112
- async function requestStaticMapUntilReady(request, options) {
113
- const body = preparedStaticMapRequestBodies.get(request);
114
- if (body === void 0) {
115
- throw new Error("Tileflow static map request must be created with prepareStaticMapRequest");
116
- }
117
- const idempotency = validateStaticMapIdempotencyKey(options.idempotencyKey);
118
- if (!idempotency.ok) {
119
- throw new Error(`Invalid Tileflow Static Maps idempotency key: ${idempotency.error}`);
120
- }
121
- const maxWaitMs = boundedClientDuration(options.maxWaitMs, 3e4, 100, 12e4, "maxWaitMs");
122
- const pollIntervalMs = boundedClientDuration(
123
- options.pollIntervalMs,
124
- 500,
125
- 0,
126
- 5e3,
127
- "pollIntervalMs"
128
- );
129
- const fetcher = options.fetch ?? fetch;
130
- const createUrl = normalizeStaticMapEndpointUrl(options.createUrl);
131
- const headers = {
132
- Accept: STATIC_MAP_RESULT_MEDIA_TYPE,
133
- "Content-Type": "application/json",
134
- "Idempotency-Key": idempotency.key
135
- };
136
- if (options.apiKey) {
137
- headers.Authorization = `Bearer ${options.apiKey}`;
138
- }
139
- if (options.mapId !== void 0) {
140
- if (!/^map_[A-Za-z0-9_-]{16}$/u.test(options.mapId)) {
141
- throw new Error("Invalid Tileflow Map ID.");
142
- }
143
- headers["X-Tileflow-Map-Id"] = options.mapId;
144
- }
145
- return runWithinStaticMapBudget(maxWaitMs, options.signal, async (signal) => {
146
- let operationId = null;
147
- while (true) {
148
- const response = await fetcher(createUrl, {
149
- body,
150
- headers,
151
- method: "POST",
152
- signal
153
- });
154
- throwIfAborted(signal);
155
- if (!response.ok) {
156
- const errorBody = await readStaticMapErrorBody(response, 8 * 1024);
157
- throwIfAborted(signal);
158
- if (response.status === 422) {
159
- const requestError = staticMapRequestErrorResponseSchema.safeParse(errorBody);
160
- if (requestError.success) {
161
- throw new StaticMapRequestError(requestError.data, response.status);
162
- }
163
- }
164
- const structured = staticMapErrorResponseSchema.safeParse(errorBody);
165
- if (structured.success) {
166
- throw new StaticMapError(structured.data, response.status);
167
- }
168
- throw new Error(`Tileflow static map failed (${response.status}).`);
169
- }
170
- const json = await readJsonResponse(response);
171
- throwIfAborted(signal);
172
- if (response.status !== 202) {
173
- const parsed = staticMapHostedResultSchema.safeParse(json);
174
- if (!parsed.success) {
175
- throw new Error(
176
- `Tileflow static map returned an invalid response: ${parsed.error.message}`
177
- );
178
- }
179
- assertStaticMapOperationIdentity(operationId, parsed.data.operationId);
180
- return parsed.data;
181
- }
182
- const pending = staticMapProcessingResultSchema.safeParse(json);
183
- if (!pending.success) {
184
- throw new Error(
185
- `Tileflow static map returned an invalid response: ${pending.error.message}`
186
- );
187
- }
188
- assertStaticMapOperationIdentity(operationId, pending.data.operationId);
189
- operationId ??= pending.data.operationId;
190
- await delay(Math.max(pollIntervalMs, pending.data.retryAfterMs), signal);
191
- }
192
- });
193
- }
194
- function hasNoControlCharacters(value) {
195
- return !Array.from(value).some((character) => {
196
- const codePoint = character.codePointAt(0) ?? 0;
197
- return codePoint <= 31 || codePoint === 127;
198
- });
199
- }
200
- function boundedClientDuration(value, fallback, minimum, maximum, name) {
201
- const resolved = value ?? fallback;
202
- if (!Number.isSafeInteger(resolved) || resolved < minimum || resolved > maximum) {
203
- throw new Error(
204
- `Tileflow Static Maps ${name} must be an integer from ${minimum} to ${maximum}`
205
- );
206
- }
207
- return resolved;
208
- }
209
- async function readJsonResponse(response) {
210
- const source = await readBoundedResponseText(response, maxStaticMapResponseBytes, "64 KiB");
211
- try {
212
- return JSON.parse(source);
213
- } catch {
214
- throw new Error("Tileflow static map returned an invalid response: expected JSON");
215
- }
216
- }
217
- async function readStaticMapErrorBody(response, maximumBytes) {
218
- try {
219
- const source = await readBoundedResponseText(response, maximumBytes, `${maximumBytes} bytes`);
220
- return JSON.parse(source);
221
- } catch {
222
- return null;
223
- }
224
- }
225
- function isStaticMapRequestFailure(value) {
226
- if (!("code" in value)) return false;
227
- const { ok: _ok, ...response } = value;
228
- return staticMapRequestErrorResponseSchema.safeParse(response).success;
229
- }
230
- async function readBoundedResponseText(response, maximumBytes, displayLimit) {
231
- if (!response.body) return "";
232
- const reader = response.body.getReader();
233
- const chunks = [];
234
- let byteLength = 0;
235
- while (true) {
236
- const { done, value } = await reader.read();
237
- if (done) break;
238
- byteLength += value.byteLength;
239
- if (byteLength > maximumBytes) {
240
- await reader.cancel();
241
- throw new Error(
242
- `Tileflow static map returned an invalid response: response exceeded ${displayLimit}`
243
- );
244
- }
245
- chunks.push(value);
246
- }
247
- const bytes = new Uint8Array(byteLength);
248
- let offset = 0;
249
- for (const chunk of chunks) {
250
- bytes.set(chunk, offset);
251
- offset += chunk.byteLength;
252
- }
253
- try {
254
- return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
255
- } catch {
256
- throw new Error("Tileflow static map returned an invalid response: expected UTF-8 JSON");
257
- }
258
- }
259
- async function runWithinStaticMapBudget(maxWaitMs, externalSignal, operation) {
260
- const controller = new AbortController();
261
- const timeoutError = new Error(`Tileflow static map timed out after ${maxWaitMs}ms`);
262
- const abortFromCaller = () => controller.abort(externalSignal?.reason);
263
- if (externalSignal?.aborted) {
264
- abortFromCaller();
265
- } else {
266
- externalSignal?.addEventListener("abort", abortFromCaller, { once: true });
267
- }
268
- const timeout = setTimeout(() => controller.abort(timeoutError), maxWaitMs);
269
- try {
270
- throwIfAborted(controller.signal);
271
- const pending = operation(controller.signal);
272
- return await raceWithAbort(pending, controller.signal);
273
- } finally {
274
- clearTimeout(timeout);
275
- externalSignal?.removeEventListener("abort", abortFromCaller);
276
- }
277
- }
278
- function delay(milliseconds, signal) {
279
- if (milliseconds === 0) {
280
- throwIfAborted(signal);
281
- return Promise.resolve();
282
- }
283
- return new Promise((resolve, reject) => {
284
- const timeout = setTimeout(() => {
285
- signal.removeEventListener("abort", onAbort);
286
- resolve();
287
- }, milliseconds);
288
- const onAbort = () => {
289
- clearTimeout(timeout);
290
- reject(abortReason(signal));
291
- };
292
- if (signal.aborted) {
293
- onAbort();
294
- } else {
295
- signal.addEventListener("abort", onAbort, { once: true });
296
- }
297
- });
298
- }
299
- function raceWithAbort(operation, signal) {
300
- if (signal.aborted) return Promise.reject(abortReason(signal));
301
- return new Promise((resolve, reject) => {
302
- const onAbort = () => {
303
- cleanup();
304
- reject(abortReason(signal));
305
- };
306
- const cleanup = () => signal.removeEventListener("abort", onAbort);
307
- signal.addEventListener("abort", onAbort, { once: true });
308
- operation.then(
309
- (value) => {
310
- cleanup();
311
- resolve(value);
312
- },
313
- (error) => {
314
- cleanup();
315
- reject(error);
316
- }
317
- );
318
- });
319
- }
320
- function throwIfAborted(signal) {
321
- if (signal.aborted) throw abortReason(signal);
322
- }
323
- function abortReason(signal) {
324
- if (signal.reason instanceof Error) return signal.reason;
325
- const error = new Error("Tileflow static map request was aborted");
326
- error.name = "AbortError";
327
- return error;
328
- }
329
- function assertStaticMapOperationIdentity(expected, actual) {
330
- if (expected !== null && actual !== expected) {
331
- throw new Error("Tileflow static map changed operation identity while polling");
332
- }
333
- }
334
- function normalizeUrl(value) {
335
- const url = new URL(value);
336
- if (!isSafeHttpUrl(value) || url.search) {
337
- throw new TypeError(
338
- "Tileflow Static Maps apiUrl must be HTTP(S) without credentials, query, or fragment"
339
- );
340
- }
341
- return url.toString().replace(/\/+$/, "");
342
- }
343
- function normalizeStaticMapEndpointUrl(value) {
344
- if (value.startsWith("/")) {
345
- if (value.startsWith("//") || value.length > 2048 || /[\\?#]/u.test(value) || hasControlCharacter(value)) {
346
- throw new TypeError(
347
- "Tileflow Static Maps createUrl must be HTTP(S) without credentials, query, or fragment or a safe root-relative path"
348
- );
349
- }
350
- return value;
351
- }
352
- const url = new URL(value);
353
- if (!isSafeHttpUrl(value) || url.search) {
354
- throw new TypeError(
355
- "Tileflow Static Maps createUrl must be HTTP(S) without credentials, query, or fragment or a safe root-relative path"
356
- );
357
- }
358
- return url.toString();
359
- }
360
- function hasControlCharacter(value) {
361
- for (let index = 0; index < value.length; index += 1) {
362
- const codePoint = value.charCodeAt(index);
363
- if (codePoint <= 31 || codePoint === 127) return true;
364
- }
365
- return false;
366
- }
367
-
368
- export {
369
- STATIC_MAP_RESULT_MEDIA_TYPE,
370
- staticMapAttributionEntrySchema,
371
- staticMapAttributionResultSchema,
372
- staticMapHostedResultSchema,
373
- staticMapProcessingResultSchema,
374
- validateStaticMapIdempotencyKey,
375
- createStaticMapIdempotencyKey,
376
- prepareStaticMapRequest,
377
- createStaticMap,
378
- precacheStaticMap,
379
- requestStaticMapUntilReady
380
- };
@@ -1,297 +0,0 @@
1
- import {
2
- analyzeStaticAutoFit,
3
- normalizeStaticScene,
4
- staticAutoFitPlanSchema,
5
- validateStaticScene
6
- } from "./chunk-TBI5AED6.js";
7
- import {
8
- hashStableValue,
9
- isSafeHttpUrl,
10
- jsonByteLength,
11
- stableStringify,
12
- staticOverlayPlacements,
13
- staticSceneSchema,
14
- stripUndefined
15
- } from "./chunk-6DWVCK64.js";
16
-
17
- // src/manifest.ts
18
- import { z } from "zod";
19
- var staticRendererSchemaVersion = 1;
20
- var staticAttributionPlanSchemaVersion = 1;
21
- var staticRenderCompositionSchemaVersion = 1;
22
- var staticAttributionLimits = {
23
- maxBytes: 32 * 1024,
24
- maxEntries: 18,
25
- maxLinksPerEntry: 8,
26
- maxTextLength: 16384,
27
- maxUrlLength: 2048
28
- };
29
- var sha256HexSchema = z.string().regex(/^[0-9a-f]{64}$/u);
30
- var sourceIdSchema = z.string().min(1).max(128);
31
- var boundedIdentitySchema = z.string().min(1).max(512).refine(hasNoControlCharacters, {
32
- message: "Expected no control characters"
33
- });
34
- var staticResolvedAttributionPositionSchema = z.enum([
35
- "top-left",
36
- "top-right",
37
- "bottom-left",
38
- "bottom-right"
39
- ]);
40
- var staticAttributionSegmentSchema = z.discriminatedUnion("kind", [
41
- z.object({
42
- kind: z.literal("text"),
43
- text: z.string().min(1).max(staticAttributionLimits.maxTextLength).refine(hasNoControlCharacters, { message: "Attribution text contains control characters" })
44
- }).strict(),
45
- z.object({
46
- kind: z.literal("link"),
47
- label: z.string().min(1).max(staticAttributionLimits.maxTextLength).refine(hasNoControlCharacters, {
48
- message: "Attribution link label contains control characters"
49
- }),
50
- url: z.string().trim().url().max(staticAttributionLimits.maxUrlLength).refine(isSafeHttpUrl, {
51
- message: "Expected an http(s) URL without credentials or a fragment"
52
- })
53
- }).strict()
54
- ]);
55
- var attributionSourceSchema = z.object({
56
- sourceId: sourceIdSchema,
57
- sourceSelectionIdentity: boundedIdentitySchema
58
- }).strict();
59
- var attributionSourcesSchema = z.array(attributionSourceSchema).min(1).max(18).refine(isUniqueSortedSources, {
60
- message: "Attribution sources must be unique and sorted"
61
- });
62
- var staticAttributionProvenanceSchema = z.discriminatedUnion("authority", [
63
- z.object({
64
- authority: z.literal("platform-notice"),
65
- noticeId: boundedIdentitySchema,
66
- noticeSha256: sha256HexSchema,
67
- resource: z.enum(["terrain", "world"]),
68
- sources: attributionSourcesSchema
69
- }).strict(),
70
- z.object({
71
- authority: z.literal("team-declared"),
72
- sources: z.array(
73
- attributionSourceSchema.extend({
74
- mapRevision: boundedIdentitySchema,
75
- resourceId: boundedIdentitySchema
76
- }).strict()
77
- ).min(1).max(18).refine(isUniqueSortedSources, {
78
- message: "Attribution sources must be unique and sorted"
79
- })
80
- }).strict()
81
- ]);
82
- var staticAttributionEntrySchema = z.object({
83
- authority: z.enum(["platform-notice", "team-declared"]),
84
- provenance: staticAttributionProvenanceSchema,
85
- segments: z.array(staticAttributionSegmentSchema).min(1).max(17)
86
- }).strict().superRefine((entry, context) => {
87
- if (entry.authority !== entry.provenance.authority) {
88
- context.addIssue({
89
- code: "custom",
90
- message: "Attribution entry authority must match its provenance",
91
- path: ["authority"]
92
- });
93
- }
94
- const links = entry.segments.filter((segment) => segment.kind === "link").length;
95
- if (links > staticAttributionLimits.maxLinksPerEntry) {
96
- context.addIssue({
97
- code: "custom",
98
- message: `Attribution entries can contain at most ${staticAttributionLimits.maxLinksPerEntry} links`,
99
- path: ["segments"]
100
- });
101
- }
102
- });
103
- var staticAttributionPlanSchema = z.object({
104
- entries: z.array(staticAttributionEntrySchema).max(staticAttributionLimits.maxEntries),
105
- mode: z.enum(["embedded", "external"]),
106
- position: z.union([z.literal("auto"), staticResolvedAttributionPositionSchema, z.null()]),
107
- schemaVersion: z.literal(staticAttributionPlanSchemaVersion)
108
- }).strict().superRefine((plan, context) => {
109
- if (plan.mode === "external" && plan.position !== null || plan.mode === "embedded" && plan.position === null) {
110
- context.addIssue({
111
- code: "custom",
112
- message: "Attribution position must match its mode",
113
- path: ["position"]
114
- });
115
- }
116
- if (jsonByteLength(plan) > staticAttributionLimits.maxBytes) {
117
- context.addIssue({
118
- code: "custom",
119
- message: `Attribution plan exceeds ${staticAttributionLimits.maxBytes} bytes`
120
- });
121
- }
122
- });
123
- var placementAnchorsSchema = z.object({
124
- "above-water": z.string().min(1).max(256).nullable(),
125
- "below-roads": z.string().min(1).max(256).nullable(),
126
- "above-roads": z.string().min(1).max(256).nullable(),
127
- "above-buildings": z.string().min(1).max(256).nullable(),
128
- "below-labels": z.string().min(1).max(256).nullable(),
129
- "above-labels": z.null()
130
- }).strict().refine(anchorsHaveTerminalNulls, {
131
- message: "Placement anchors may become null only at the end of semantic order"
132
- });
133
- var resolvedIconSchema = z.object({
134
- height: z.number().int().positive().max(2048),
135
- icon: z.string().max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/u),
136
- overlayIndex: z.number().int().min(0).max(23),
137
- width: z.number().int().positive().max(2048)
138
- }).strict();
139
- var staticRenderCompositionSchema = z.object({
140
- anchors: placementAnchorsSchema,
141
- icons: z.array(resolvedIconSchema).max(24),
142
- schemaVersion: z.literal(staticRenderCompositionSchemaVersion)
143
- }).strict().refine(
144
- (composition) => composition.icons.every(
145
- (icon, index) => index === 0 || composition.icons[index - 1].overlayIndex < icon.overlayIndex
146
- ),
147
- { message: "Resolved symbol icons must be unique and sorted by overlay index" }
148
- );
149
- var staticRenderManifestBaseShape = {
150
- attribution: staticAttributionPlanSchema,
151
- autoFit: staticAutoFitPlanSchema.optional(),
152
- composition: staticRenderCompositionSchema,
153
- mapId: z.string().trim().min(1).max(128),
154
- rendererVersion: z.string().trim().min(1).max(64),
155
- schemaVersion: z.literal(staticRendererSchemaVersion),
156
- scene: staticSceneSchema,
157
- styleId: z.string().trim().min(1).max(128).optional(),
158
- styleRevision: z.string().trim().min(1).max(128),
159
- styleUrl: z.string().trim().url().max(512).refine(isSafeHttpUrl, {
160
- message: "Expected an http(s) style URL without credentials or a fragment"
161
- })
162
- };
163
- var staticRenderManifestSchema = z.object(staticRenderManifestBaseShape).strict();
164
- function validateStaticRenderManifest(input) {
165
- if (!input || typeof input !== "object" || Array.isArray(input)) {
166
- return { error: "manifest: Expected an object", ok: false };
167
- }
168
- if (input.schemaVersion !== staticRendererSchemaVersion) {
169
- return { error: "manifest.schemaVersion: Unsupported renderer schema version", ok: false };
170
- }
171
- const rawScene = input.scene;
172
- const sceneValidation = validateStaticScene(rawScene);
173
- if (!sceneValidation.ok) return sceneValidation;
174
- const parsed = staticRenderManifestSchema.safeParse({
175
- ...input,
176
- scene: sceneValidation.scene
177
- });
178
- if (!parsed.success) return zodFailure(parsed.error);
179
- const autoFit = expectedAutoFit(sceneValidation.scene);
180
- if (autoFit === void 0 !== (parsed.data.autoFit === void 0) || autoFit !== void 0 && stableStringify(autoFit) !== stableStringify(parsed.data.autoFit)) {
181
- return { error: "manifest.autoFit: Expected the exact plan derived from scene", ok: false };
182
- }
183
- if (!attributionMatchesScene(parsed.data.attribution, sceneValidation.scene)) {
184
- return {
185
- error: "manifest.attribution: Expected the exact request resolved from scene",
186
- ok: false
187
- };
188
- }
189
- if (!compositionMatchesScene(parsed.data.composition, sceneValidation.scene)) {
190
- return {
191
- error: "manifest.composition: Expected exact resolved symbol icon references",
192
- ok: false
193
- };
194
- }
195
- return {
196
- manifest: {
197
- ...parsed.data,
198
- ...autoFit === void 0 ? {} : { autoFit },
199
- scene: sceneValidation.scene
200
- },
201
- ok: true
202
- };
203
- }
204
- function createRenderManifest(input) {
205
- const scene = normalizeStaticScene(input.scene);
206
- const autoFit = expectedAutoFit(scene);
207
- return staticRenderManifestSchema.parse(
208
- stripUndefined({
209
- attribution: input.attribution,
210
- autoFit,
211
- composition: input.composition,
212
- mapId: input.mapId,
213
- rendererVersion: input.rendererVersion,
214
- schemaVersion: staticRendererSchemaVersion,
215
- scene,
216
- styleId: input.styleId,
217
- styleRevision: input.styleRevision,
218
- styleUrl: input.styleUrl
219
- })
220
- );
221
- }
222
- async function hashRenderManifest(manifest) {
223
- const validation = validateStaticRenderManifest(manifest);
224
- if (!validation.ok) throw new Error(`Invalid Tileflow render manifest: ${validation.error}`);
225
- return hashStableValue(validation.manifest);
226
- }
227
- async function hashStaticSceneRequest(scene) {
228
- const validation = validateStaticScene(scene);
229
- if (!validation.ok) throw new Error(`Invalid Tileflow static scene: ${validation.error}`);
230
- return hashStableValue(validation.scene);
231
- }
232
- function attributionMatchesScene(plan, scene) {
233
- const request = scene.attribution;
234
- const expectedMode = request?.mode === "external" ? "external" : "embedded";
235
- const expectedPosition = expectedMode === "external" ? null : request && "position" in request ? request.position ?? "auto" : "auto";
236
- return plan.mode === expectedMode && plan.position === expectedPosition;
237
- }
238
- function compositionMatchesScene(composition, scene) {
239
- const expected = scene.overlays.flatMap(
240
- (overlay, overlayIndex) => overlay.type === "symbol" && overlay.icon ? [{ icon: overlay.icon, overlayIndex }] : []
241
- );
242
- return expected.length === composition.icons.length && expected.every(
243
- (icon, index) => composition.icons[index]?.icon === icon.icon && composition.icons[index]?.overlayIndex === icon.overlayIndex
244
- );
245
- }
246
- function expectedAutoFit(scene) {
247
- if (scene.camera.type !== "auto") return void 0;
248
- const analysis = analyzeStaticAutoFit(scene);
249
- if (!analysis.ok) throw new Error(`Invalid Tileflow auto-fit scene: ${analysis.error}`);
250
- return analysis.plan;
251
- }
252
- function anchorsHaveTerminalNulls(anchors) {
253
- let sawNull = false;
254
- for (const placement of staticOverlayPlacements) {
255
- const anchor = anchors[placement];
256
- if (anchor === null) sawNull = true;
257
- else if (sawNull) return false;
258
- }
259
- return true;
260
- }
261
- function hasNoControlCharacters(value) {
262
- return !Array.from(value).some((character) => {
263
- const codePoint = character.codePointAt(0) ?? 0;
264
- return codePoint <= 31 || codePoint === 127;
265
- });
266
- }
267
- function isUniqueSortedSources(values) {
268
- return values.every(
269
- (value, index) => index === 0 || compareCodeUnits(values[index - 1].sourceId, value.sourceId) < 0
270
- );
271
- }
272
- function compareCodeUnits(left, right) {
273
- return left < right ? -1 : left > right ? 1 : 0;
274
- }
275
- function zodFailure(error) {
276
- return {
277
- error: error.issues.map((issue) => `${issue.path.join(".") || "manifest"}: ${issue.message}`).join("; "),
278
- ok: false
279
- };
280
- }
281
-
282
- export {
283
- staticRendererSchemaVersion,
284
- staticAttributionPlanSchemaVersion,
285
- staticRenderCompositionSchemaVersion,
286
- staticAttributionLimits,
287
- staticAttributionSegmentSchema,
288
- staticAttributionProvenanceSchema,
289
- staticAttributionEntrySchema,
290
- staticAttributionPlanSchema,
291
- staticRenderCompositionSchema,
292
- staticRenderManifestSchema,
293
- validateStaticRenderManifest,
294
- createRenderManifest,
295
- hashRenderManifest,
296
- hashStaticSceneRequest
297
- };
package/dist/index.d.ts DELETED
@@ -1,7 +0,0 @@
1
- export { StaticAutoFitErrorResponse, StaticAutoFitFailure, StaticMapRequestError, StaticMapRequestErrorResponse, StaticMapRequestFailure, normalizeStaticScene, staticMapRequestErrorResponseSchema, validateStaticScene } from './scene.js';
2
- export { circle, compileStaticOverlays, line, marker, polygon, symbol } from './overlays.js';
3
- export { StaticAttributionEntry, StaticAttributionPlan, StaticAttributionProvenance, StaticAttributionSegment, StaticRenderComposition, StaticRenderManifest, StaticResolvedAttributionPosition, createRenderManifest, hashRenderManifest, hashStaticSceneRequest, staticAttributionEntrySchema, staticAttributionLimits, staticAttributionPlanSchema, staticAttributionPlanSchemaVersion, staticAttributionProvenanceSchema, staticAttributionSegmentSchema, staticRenderCompositionSchema, staticRenderCompositionSchemaVersion, staticRenderManifestSchema, staticRendererSchemaVersion, validateStaticRenderManifest } from './manifest.js';
4
- export { PreparedStaticMapRequest, STATIC_MAP_RESULT_MEDIA_TYPE, StaticMapAttributionEntry, StaticMapAttributionResult, StaticMapCreateOptions, StaticMapEndpointRequestOptions, StaticMapHostedResult, StaticMapImageResult, StaticMapResult, createStaticMap, createStaticMapIdempotencyKey, precacheStaticMap, prepareStaticMapRequest, requestStaticMapUntilReady, stableStringify, staticMapAttributionEntrySchema, staticMapAttributionResultSchema, staticMapHostedResultSchema, staticMapProcessingResultSchema, validateStaticMapIdempotencyKey } from './client.js';
5
- export { M as MAX_OVERLAY_LATITUDE, S as StaticAttributionMode, a as StaticAttributionPosition, b as StaticAttributionRequest, c as StaticCoordinate, d as StaticMapFormat, e as StaticOverlay, f as StaticOverlayInput, g as StaticOverlayPlacement, h as StaticPadding, i as StaticScene, j as StaticSceneInput, k as StaticSymbolAnchor, l as StaticSymbolCollision, m as StaticSymbolLabelAppearance, n as StaticSymbolLabelPosition, o as StaticSymbolLanguage, p as isSupportedStaticSymbolCodePoint, s as staticAttributionPositionSchema, q as staticAttributionRequestSchema, r as staticOverlayPlacements, t as staticOverlaySchema, u as staticSceneLimits, v as staticSceneSchema, w as staticSceneSchemaVersion, x as staticSymbolAnchors, y as staticSymbolCollisions, z as staticSymbolLabelAppearances, A as staticSymbolLabelPositions, B as staticSymbolLanguages } from './scene-contract-Cr6BNLz0.js';
6
- export { S as StaticMapError, a as StaticMapErrorResponse, s as staticMapErrorResponseSchema } from './errors-B9rwehK0.js';
7
- import 'zod';