@tileflow/core 0.1.0-alpha.25 → 0.1.0-alpha.27

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/dist/runtime.d.ts CHANGED
@@ -1,2 +1 @@
1
- export { t as TileflowAnalytics, U as TileflowManifestFetchOptions, W as TileflowManifestLoadOptions, X as TileflowMapMode, Y as TileflowMapModeOptions, a8 as TileflowResolvedRuntimeTheme, av as TileflowRuntimeCenterLike, aw as TileflowRuntimeColorScheme, T as TileflowRuntimeManifest, ax as TileflowRuntimeManifestMap, ay as TileflowRuntimeManifestMapEntry, az as TileflowRuntimeManifestTheme, aA as TileflowRuntimeSource, aB as TileflowRuntimeSourceValidation, aC as TileflowRuntimeStyle, aD as TileflowRuntimeStyleOptions, aE as TileflowRuntimeSystemThemes, aF as TileflowRuntimeViewOptions, aG as TileflowSessionController, aH as TileflowSessionGrantResponse, aK as TileflowStyleFontFace, b7 as TileflowThemeSelection, bf as assertValidTileflowRuntimeSource, bg as clearTileflowManifestCache, bi as createTileflowSessionController, bj as createTileflowSessionId, bk as defaultTileflowManifestUrl, bl as defaultTileflowRuntimeView, bn as getTileflowAnalyticsApiUrl, bo as getTileflowStyleFontFaces, bp as inferTileflowAnalyticsFromStyleUrl, bq as loadTileflowManifest, br as mergeTileflowAnalytics, bs as normalizeTileflowRuntimeCenter, bt as normalizeTileflowStaticImageSize, bT as normalizeTileflowSurfaceId, bu as normalizeTileflowUrl, bw as resolveTileflowAnalyticsRequestUrl, bx as resolveTileflowManifestMap, by as resolveTileflowMapMode, bz as resolveTileflowRuntimeStyle, bA as resolveTileflowRuntimeTheme, bB as resolveTileflowRuntimeView, bC as resolveTileflowStaticImageUrl, bE as shouldLoadTileflowManifest, bF as startTileflowSession, bK as tileflowStyleFontFaceLimits, bL as tileflowStyleFontFacesMetadataKey, bO as validateTileflowRuntimeSource, bP as validateTileflowThemeSelection } from './manifest-B5GKVMFE.js';
2
- import 'zod';
1
+ export { z as TileflowAnalytics, $ as TileflowManifestFetchOptions, a0 as TileflowManifestLoadOptions, a1 as TileflowMapMode, a2 as TileflowMapModeOptions, ae as TileflowResolvedRuntimeTheme, aB as TileflowRuntimeCenterLike, a as TileflowRuntimeColorScheme, T as TileflowRuntimeManifest, aC as TileflowRuntimeManifestMap, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, aD as TileflowRuntimeSource, aE as TileflowRuntimeSourceValidation, aF as TileflowRuntimeStyle, aG as TileflowRuntimeStyleOptions, d as TileflowRuntimeSystemThemes, aH as TileflowRuntimeViewOptions, aI as TileflowSessionController, aJ as TileflowSessionGrantResponse, aM as TileflowStyleFontFace, b9 as TileflowThemeSelection, bh as assertValidTileflowRuntimeSource, bi as clearTileflowManifestCache, bk as createTileflowSessionController, bl as createTileflowSessionId, bm as defaultTileflowManifestUrl, bn as defaultTileflowRuntimeView, bp as getTileflowAnalyticsApiUrl, bq as getTileflowStyleFontFaces, br as inferTileflowAnalyticsFromStyleUrl, bs as loadTileflowManifest, bt as mergeTileflowAnalytics, bu as normalizeTileflowRuntimeCenter, bv as normalizeTileflowStaticImageSize, bQ as normalizeTileflowSurfaceId, bw as normalizeTileflowUrl, bx as resolveTileflowAnalyticsRequestUrl, by as resolveTileflowManifestMap, bz as resolveTileflowMapMode, bA as resolveTileflowRuntimeStyle, bB as resolveTileflowRuntimeTheme, bC as resolveTileflowRuntimeView, bD as resolveTileflowStaticImageUrl, bE as shouldLoadTileflowManifest, bF as startTileflowSession, bH as tileflowStyleFontFaceLimits, bI as tileflowStyleFontFacesMetadataKey, bL as validateTileflowRuntimeSource, bM as validateTileflowThemeSelection } from './manifest-types-BdGjIYy-.js';
package/dist/runtime.js CHANGED
@@ -29,29 +29,59 @@ var init_portable_identity_rules = __esm({
29
29
  }
30
30
  });
31
31
 
32
- // src/portable-identity.ts
33
- import { z } from "zod";
34
- var tileflowPortableIdSchema, tileflowThemeNameSchema;
35
- var init_portable_identity = __esm({
36
- "src/portable-identity.ts"() {
32
+ // src/manifest-types.ts
33
+ var tileflowRuntimeManifestVersion, tileflowRuntimeManifestLimits;
34
+ var init_manifest_types = __esm({
35
+ "src/manifest-types.ts"() {
36
+ "use strict";
37
+ tileflowRuntimeManifestVersion = 1;
38
+ tileflowRuntimeManifestLimits = Object.freeze({ maximumBytes: 1024 * 1024 });
39
+ }
40
+ });
41
+
42
+ // src/portable-identity-schema.ts
43
+ function createPortableIdentitySchemas(operations) {
44
+ const bounded = operations.maxLength(
45
+ operations.minLength(operations.string(), 1),
46
+ tileflowPortableIdMaximumLength
47
+ );
48
+ const pattern = operations.regex(
49
+ bounded,
50
+ tileflowPortableIdPattern,
51
+ "Expected lowercase kebab-case beginning with a letter"
52
+ );
53
+ const tileflowPortableIdSchema2 = operations.refine(
54
+ pattern,
55
+ (name) => !["constructor", "prototype"].includes(name) && !/^(?:AUX|CON|NUL|PRN|COM[1-9]|LPT[1-9])$/i.test(name),
56
+ "Expected a portable identifier that is not a reserved filename or prototype key"
57
+ );
58
+ const tileflowThemeNameSchema2 = operations.refine(
59
+ tileflowPortableIdSchema2,
60
+ isTileflowThemeName,
61
+ "Expected a concrete theme name; system is browser-only"
62
+ );
63
+ return { tileflowPortableIdSchema: tileflowPortableIdSchema2, tileflowThemeNameSchema: tileflowThemeNameSchema2 };
64
+ }
65
+ var init_portable_identity_schema = __esm({
66
+ "src/portable-identity-schema.ts"() {
37
67
  "use strict";
38
68
  init_portable_identity_rules();
39
- tileflowPortableIdSchema = z.string().min(1).max(tileflowPortableIdMaximumLength).regex(tileflowPortableIdPattern, {
40
- message: "Expected lowercase kebab-case beginning with a letter"
41
- }).refine(
42
- (name) => !["constructor", "prototype"].includes(name) && !/^(?:AUX|CON|NUL|PRN|COM[1-9]|LPT[1-9])$/i.test(name),
43
- "Expected a portable identifier that is not a reserved filename or prototype key"
44
- );
45
- tileflowThemeNameSchema = tileflowPortableIdSchema.refine(
46
- isTileflowThemeName,
47
- "Expected a concrete theme name; system is browser-only"
48
- );
49
69
  }
50
70
  });
51
71
 
52
- // src/themes/visual-semantics.ts
53
- var init_visual_semantics = __esm({
54
- "src/themes/visual-semantics.ts"() {
72
+ // src/runtime-view-schema.ts
73
+ function createTileflowRuntimeViewSchema(operations) {
74
+ return operations.object({
75
+ bearing: operations.optional(operations.number(-180, 180)),
76
+ center: operations.optional(
77
+ operations.tuplePair(operations.number(-180, 180), operations.number(-90, 90))
78
+ ),
79
+ pitch: operations.optional(operations.number(0, 85)),
80
+ zoom: operations.optional(operations.number(0, 24))
81
+ });
82
+ }
83
+ var init_runtime_view_schema = __esm({
84
+ "src/runtime-view-schema.ts"() {
55
85
  "use strict";
56
86
  }
57
87
  });
@@ -73,155 +103,73 @@ var init_model = __esm({
73
103
  }
74
104
  });
75
105
 
76
- // src/themes/index.ts
77
- var init_themes = __esm({
78
- "src/themes/index.ts"() {
79
- "use strict";
80
- init_model();
81
- init_visual_semantics();
82
- }
83
- });
84
-
85
- // src/manifest.ts
86
- var manifest_exports = {};
87
- __export(manifest_exports, {
88
- parseTileflowRuntimeManifest: () => parseTileflowRuntimeManifest,
89
- safeParseTileflowRuntimeManifest: () => safeParseTileflowRuntimeManifest,
90
- tileflowRuntimeManifestLimits: () => tileflowRuntimeManifestLimits,
91
- tileflowRuntimeManifestSchema: () => tileflowRuntimeManifestSchema,
92
- tileflowRuntimeManifestVersion: () => tileflowRuntimeManifestVersion
93
- });
94
- import { z as z2 } from "zod";
95
- function parseTileflowRuntimeManifest(input) {
96
- return tileflowRuntimeManifestSchema.parse(input);
97
- }
98
- function safeParseTileflowRuntimeManifest(input) {
99
- return tileflowRuntimeManifestSchema.safeParse(input);
100
- }
101
- function validateUniqueFontFaces(fontFaces, context) {
102
- const seen = /* @__PURE__ */ new Map();
103
- for (const [index, fontFace] of fontFaces.entries()) {
104
- const identity = `${fontFace.family}\0${fontFace.style ?? "normal"}\0${fontFace.weight ?? "400"}`;
105
- const first = seen.get(identity);
106
- if (first !== void 0) {
107
- context.addIssue({
108
- code: "custom",
109
- message: `Duplicate font face identity; first declared at index ${first}`,
110
- path: [index]
111
- });
112
- continue;
113
- }
114
- seen.set(identity, index);
115
- }
116
- }
117
- function isPublicResourceUrl(value) {
118
- if (value.startsWith("//")) return false;
119
- if (!value.startsWith("/") && !value.startsWith("./") && !value.startsWith("../") && !isAbsolutePublicUrl(value)) {
120
- return false;
121
- }
122
- return isSafeResolvedPublicUrl(value);
123
- }
124
- function isAbsolutePublicUrl(value) {
125
- try {
126
- const url = new URL(value);
127
- return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password && !url.hash && !hasEncodedPathSeparator(value);
128
- } catch {
129
- return false;
130
- }
131
- }
132
- function isSafeResolvedPublicUrl(value) {
133
- try {
134
- const url = new URL(value, "https://manifest.invalid/owner/manifest.json");
135
- return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password && !url.hash && !hasEncodedPathSeparator(value);
136
- } catch {
137
- return false;
138
- }
139
- }
140
- function hasEncodedPathSeparator(value) {
141
- return /%(?:2f|5c)/iu.test(value);
142
- }
143
- function isApiOrigin(value) {
144
- try {
145
- const url = new URL(value);
146
- return isAbsolutePublicUrl(value) && url.pathname === "/" && !url.search && value.replace(/\/$/u, "") === url.origin;
147
- } catch {
148
- return false;
149
- }
150
- }
151
- function findUnsafeManifestStructure(input) {
152
- if (!input || typeof input !== "object") return void 0;
153
- const pending = [{ path: [], value: input }];
154
- const visited = /* @__PURE__ */ new WeakSet();
155
- while (pending.length > 0) {
156
- const current = pending.pop();
157
- if (visited.has(current.value)) continue;
158
- visited.add(current.value);
159
- if (!Array.isArray(current.value)) {
160
- const prototype = Object.getPrototypeOf(current.value);
161
- if (prototype !== Object.prototype && prototype !== null) {
162
- return { path: current.path, reason: "prototype" };
163
- }
164
- }
165
- for (const key of Object.keys(current.value)) {
166
- const path = [...current.path, Array.isArray(current.value) ? Number(key) : key];
167
- if (key === "__proto__") return { path, reason: "key" };
168
- const descriptor = Object.getOwnPropertyDescriptor(current.value, key);
169
- if (descriptor && "value" in descriptor && descriptor.value && typeof descriptor.value === "object") {
170
- pending.push({ path, value: descriptor.value });
171
- }
172
- }
173
- }
174
- return void 0;
175
- }
176
- var tileflowRuntimeManifestVersion, tileflowRuntimeManifestLimits, safeTextSchema, publicResourceUrlSchema, apiOriginSchema, viewSchema, fontFaceSchema, fontFacesSchema, manifestThemeSchema, manifestMapSchema, canonicalManifestSchema, safeManifestInputSchema, tileflowRuntimeManifestSchema;
177
- var init_manifest = __esm({
178
- "src/manifest.ts"() {
179
- "use strict";
180
- init_portable_identity();
181
- init_themes();
182
- tileflowRuntimeManifestVersion = 1;
183
- tileflowRuntimeManifestLimits = Object.freeze({ maximumBytes: 1024 * 1024 });
184
- safeTextSchema = z2.string().min(1).max(2048).refine((value) => value === value.trim(), "Expected text without surrounding whitespace").refine((value) => !/[\p{Cc}\\]/u.test(value), "Expected safe text");
185
- publicResourceUrlSchema = safeTextSchema.refine(isPublicResourceUrl, {
186
- message: "Expected an HTTP(S), root-relative, or path-relative public URL"
187
- });
188
- apiOriginSchema = safeTextSchema.refine(isApiOrigin, {
189
- message: "Expected an absolute HTTP(S) origin without path, credentials, query, or fragment"
190
- });
191
- viewSchema = z2.object({
192
- bearing: z2.number().finite().min(-180).max(180).optional(),
193
- center: z2.tuple([z2.number().finite().min(-180).max(180), z2.number().finite().min(-90).max(90)]).optional(),
194
- pitch: z2.number().finite().min(0).max(85).optional(),
195
- zoom: z2.number().finite().min(0).max(24).optional()
196
- }).strict();
197
- fontFaceSchema = z2.object({
198
- family: safeTextSchema.max(100),
199
- source: publicResourceUrlSchema,
200
- style: z2.enum(["italic", "normal", "oblique"]).optional(),
201
- weight: z2.enum(["100", "200", "300", "400", "500", "600", "700", "800", "900"]).optional()
202
- }).strict();
203
- fontFacesSchema = z2.array(fontFaceSchema).max(16).superRefine(validateUniqueFontFaces);
204
- manifestThemeSchema = z2.object({
205
- colorScheme: z2.enum(["dark", "light"]),
206
- fontFaces: fontFacesSchema.optional(),
207
- revision: safeTextSchema.max(128).optional(),
208
- styleId: safeTextSchema.max(128).optional(),
209
- styleUrl: publicResourceUrlSchema
210
- }).strict();
211
- manifestMapSchema = z2.object({
212
- apiUrl: apiOriginSchema.optional(),
213
- defaultTheme: tileflowThemeNameSchema,
214
- environment: safeTextSchema.max(128).optional(),
215
- mapId: safeTextSchema.max(128).optional(),
216
- systemThemes: z2.object({ dark: tileflowThemeNameSchema, light: tileflowThemeNameSchema }).strict().optional(),
217
- themes: z2.record(tileflowThemeNameSchema, manifestThemeSchema),
218
- usageMode: z2.literal("session").optional(),
219
- view: viewSchema.optional(),
220
- worldGeneration: z2.literal("v1").optional()
221
- }).strict().superRefine((entry, context) => {
106
+ // src/manifest-schema.ts
107
+ function createTileflowRuntimeManifestSchema(primitives, operations, identities = createPortableIdentitySchemas(operations)) {
108
+ const { tileflowPortableIdSchema: tileflowPortableIdSchema2, tileflowThemeNameSchema: tileflowThemeNameSchema2 } = identities;
109
+ const safeTextSchema = operations.refine(
110
+ operations.refine(
111
+ operations.maxLength(operations.minLength(operations.string(), 1), 2048),
112
+ (value) => value === value.trim(),
113
+ "Expected text without surrounding whitespace"
114
+ ),
115
+ (value) => !/[\p{Cc}\\]/u.test(value),
116
+ "Expected safe text"
117
+ );
118
+ const publicResourceUrlSchema = operations.refine(
119
+ safeTextSchema,
120
+ isPublicResourceUrl,
121
+ "Expected an HTTP(S), root-relative, or path-relative public URL"
122
+ );
123
+ const apiOriginSchema = operations.refine(
124
+ safeTextSchema,
125
+ isApiOrigin,
126
+ "Expected an absolute HTTP(S) origin without path, credentials, query, or fragment"
127
+ );
128
+ const viewSchema = createTileflowRuntimeViewSchema(operations);
129
+ const fontFaceSchema = operations.object({
130
+ family: operations.maxLength(safeTextSchema, 100),
131
+ source: publicResourceUrlSchema,
132
+ style: operations.optional(operations.enum(["italic", "normal", "oblique"])),
133
+ weight: operations.optional(
134
+ operations.enum(["100", "200", "300", "400", "500", "600", "700", "800", "900"])
135
+ )
136
+ });
137
+ const fontFacesSchema = operations.superRefine(
138
+ operations.maxLength(operations.array(fontFaceSchema), 16),
139
+ validateUniqueFontFaces
140
+ );
141
+ const manifestThemeSchema = operations.object({
142
+ colorScheme: operations.enum(["dark", "light"]),
143
+ fontFaces: operations.optional(fontFacesSchema),
144
+ revision: operations.optional(operations.maxLength(safeTextSchema, 128)),
145
+ styleId: operations.optional(operations.maxLength(safeTextSchema, 128)),
146
+ styleUrl: publicResourceUrlSchema
147
+ });
148
+ const manifestMapSchema = operations.superRefine(
149
+ operations.object({
150
+ apiUrl: operations.optional(apiOriginSchema),
151
+ defaultTheme: tileflowThemeNameSchema2,
152
+ environment: operations.optional(operations.maxLength(safeTextSchema, 128)),
153
+ mapId: operations.optional(operations.maxLength(safeTextSchema, 128)),
154
+ systemThemes: operations.optional(
155
+ operations.object({
156
+ dark: tileflowThemeNameSchema2,
157
+ light: tileflowThemeNameSchema2
158
+ })
159
+ ),
160
+ themes: operations.record(tileflowThemeNameSchema2, manifestThemeSchema),
161
+ usageMode: operations.optional(operations.literal("session")),
162
+ view: operations.optional(viewSchema),
163
+ worldGeneration: operations.optional(operations.literal("v1"))
164
+ }),
165
+ (entry, context) => {
222
166
  const names = Object.keys(entry.themes);
223
167
  if (names.length === 0) {
224
- context.addIssue({ code: "custom", message: "Expected at least one theme", path: ["themes"] });
168
+ context.addIssue({
169
+ code: "custom",
170
+ message: "Expected at least one theme",
171
+ path: ["themes"]
172
+ });
225
173
  }
226
174
  if (names.length > tileflowThemeLimits.maxThemes) {
227
175
  context.addIssue({
@@ -263,12 +211,15 @@ var init_manifest = __esm({
263
211
  message: "usageMode and worldGeneration must be declared together"
264
212
  });
265
213
  }
266
- });
267
- canonicalManifestSchema = z2.object({
268
- apiUrl: apiOriginSchema.optional(),
269
- maps: z2.record(tileflowPortableIdSchema, manifestMapSchema),
270
- version: z2.literal(tileflowRuntimeManifestVersion)
271
- }).strict().superRefine((manifest, context) => {
214
+ }
215
+ );
216
+ const canonicalManifestSchema = operations.superRefine(
217
+ operations.object({
218
+ apiUrl: operations.optional(apiOriginSchema),
219
+ maps: operations.record(tileflowPortableIdSchema2, manifestMapSchema),
220
+ version: operations.literal(tileflowRuntimeManifestVersion)
221
+ }),
222
+ (manifest, context) => {
272
223
  const mapCount = Object.keys(manifest.maps).length;
273
224
  if (mapCount === 0) {
274
225
  context.addIssue({ code: "custom", message: "Expected at least one map", path: ["maps"] });
@@ -276,7 +227,7 @@ var init_manifest = __esm({
276
227
  if (mapCount > 1e3) {
277
228
  context.addIssue({ code: "too_big", maximum: 1e3, origin: "object", path: ["maps"] });
278
229
  }
279
- if (new TextEncoder().encode(JSON.stringify(manifest)).byteLength > tileflowRuntimeManifestLimits.maximumBytes) {
230
+ if (primitives.utf8ByteLength(JSON.stringify(manifest)) > tileflowRuntimeManifestLimits.maximumBytes) {
280
231
  context.addIssue({
281
232
  code: "too_big",
282
233
  maximum: tileflowRuntimeManifestLimits.maximumBytes,
@@ -284,18 +235,217 @@ var init_manifest = __esm({
284
235
  message: "Manifest JSON exceeds the 1 MiB limit"
285
236
  });
286
237
  }
287
- });
288
- safeManifestInputSchema = z2.unknown().superRefine((input, context) => {
289
- const unsafe = findUnsafeManifestStructure(input);
290
- if (unsafe) {
238
+ }
239
+ );
240
+ const safeManifestInputSchema = operations.superRefine(operations.unknown(), (input, context) => {
241
+ const unsafe = findUnsafeManifestStructure(input);
242
+ if (unsafe) {
243
+ context.addIssue({
244
+ code: "custom",
245
+ message: unsafe.reason === "prototype" ? "Expected plain manifest objects" : "Expected no prototype-mutating keys",
246
+ path: unsafe.path
247
+ });
248
+ }
249
+ });
250
+ function validateUniqueFontFaces(fontFaces, context) {
251
+ const seen = /* @__PURE__ */ new Map();
252
+ for (const [index, fontFace] of fontFaces.entries()) {
253
+ const identity = `${fontFace.family}\0${fontFace.style ?? "normal"}\0${fontFace.weight ?? "400"}`;
254
+ const first = seen.get(identity);
255
+ if (first !== void 0) {
291
256
  context.addIssue({
292
257
  code: "custom",
293
- message: unsafe.reason === "prototype" ? "Expected plain manifest objects" : "Expected no prototype-mutating keys",
294
- path: unsafe.path
258
+ message: `Duplicate font face identity; first declared at index ${first}`,
259
+ path: [index]
295
260
  });
261
+ continue;
296
262
  }
297
- });
298
- tileflowRuntimeManifestSchema = safeManifestInputSchema.pipe(canonicalManifestSchema);
263
+ seen.set(identity, index);
264
+ }
265
+ }
266
+ function isPublicResourceUrl(value) {
267
+ if (value.startsWith("//")) return false;
268
+ if (!value.startsWith("/") && !value.startsWith("./") && !value.startsWith("../") && !isAbsolutePublicUrl(value)) {
269
+ return false;
270
+ }
271
+ return isSafeResolvedPublicUrl(value);
272
+ }
273
+ function isAbsolutePublicUrl(value) {
274
+ try {
275
+ const url = primitives.parseUrl(value);
276
+ return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password && !url.hash && !hasEncodedPathSeparator(value);
277
+ } catch {
278
+ return false;
279
+ }
280
+ }
281
+ function isSafeResolvedPublicUrl(value) {
282
+ try {
283
+ const url = primitives.parseUrl(value, "https://manifest.invalid/owner/manifest.json");
284
+ return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password && !url.hash && !hasEncodedPathSeparator(value);
285
+ } catch {
286
+ return false;
287
+ }
288
+ }
289
+ function hasEncodedPathSeparator(value) {
290
+ return /%(?:2f|5c)/iu.test(value);
291
+ }
292
+ function isApiOrigin(value) {
293
+ try {
294
+ const url = primitives.parseUrl(value);
295
+ return isAbsolutePublicUrl(value) && url.pathname === "/" && !url.search && value.replace(/\/$/u, "") === url.origin;
296
+ } catch {
297
+ return false;
298
+ }
299
+ }
300
+ function findUnsafeManifestStructure(input) {
301
+ if (!input || typeof input !== "object") return void 0;
302
+ const pending = [
303
+ { path: [], value: input }
304
+ ];
305
+ const visited = /* @__PURE__ */ new WeakSet();
306
+ while (pending.length > 0) {
307
+ const current = pending.pop();
308
+ if (visited.has(current.value)) continue;
309
+ visited.add(current.value);
310
+ if (!Array.isArray(current.value)) {
311
+ const prototype = Object.getPrototypeOf(current.value);
312
+ if (prototype !== Object.prototype && prototype !== null) {
313
+ return { path: current.path, reason: "prototype" };
314
+ }
315
+ }
316
+ for (const key of Object.keys(current.value)) {
317
+ const path = [...current.path, Array.isArray(current.value) ? Number(key) : key];
318
+ if (key === "__proto__") return { path, reason: "key" };
319
+ const descriptor = Object.getOwnPropertyDescriptor(current.value, key);
320
+ if (descriptor && "value" in descriptor && descriptor.value && typeof descriptor.value === "object") {
321
+ pending.push({ path, value: descriptor.value });
322
+ }
323
+ }
324
+ }
325
+ return void 0;
326
+ }
327
+ return operations.pipe(safeManifestInputSchema, canonicalManifestSchema);
328
+ }
329
+ var init_manifest_schema = __esm({
330
+ "src/manifest-schema.ts"() {
331
+ "use strict";
332
+ init_manifest_types();
333
+ init_portable_identity_schema();
334
+ init_runtime_view_schema();
335
+ init_model();
336
+ }
337
+ });
338
+
339
+ // src/native-zod-object.ts
340
+ import { z } from "zod";
341
+ function strictNativeObject(shape) {
342
+ const object = new z.core.$ZodObject({
343
+ type: "object",
344
+ shape,
345
+ catchall: z.never()
346
+ });
347
+ return z.lazy(() => object);
348
+ }
349
+ var init_native_zod_object = __esm({
350
+ "src/native-zod-object.ts"() {
351
+ "use strict";
352
+ }
353
+ });
354
+
355
+ // src/manifest-schema-classic.ts
356
+ import { z as z2 } from "zod";
357
+ function classic(schema) {
358
+ return schema;
359
+ }
360
+ var classicManifestStringOperations, classicManifestSchemaOperations;
361
+ var init_manifest_schema_classic = __esm({
362
+ "src/manifest-schema-classic.ts"() {
363
+ "use strict";
364
+ init_native_zod_object();
365
+ classicManifestStringOperations = {
366
+ string: () => z2.string(),
367
+ minLength(schema, minimum) {
368
+ return schema.min(
369
+ minimum
370
+ );
371
+ },
372
+ maxLength(schema, maximum) {
373
+ return schema.max(
374
+ maximum
375
+ );
376
+ },
377
+ regex: (schema, pattern, message) => schema.regex(pattern, { message }),
378
+ refine: (schema, check, message) => classic(schema).refine(check, message)
379
+ };
380
+ classicManifestSchemaOperations = {
381
+ ...classicManifestStringOperations,
382
+ number: (minimum, maximum) => z2.number().finite().min(minimum).max(maximum),
383
+ unknown: () => z2.unknown(),
384
+ optional: (schema) => classic(schema).optional(),
385
+ array: (schema) => z2.array(classic(schema)),
386
+ enum(values) {
387
+ return z2.enum(values);
388
+ },
389
+ literal: (value) => z2.literal(value),
390
+ tuplePair(left, right) {
391
+ return z2.tuple([classic(left), classic(right)]);
392
+ },
393
+ object(shape) {
394
+ return strictNativeObject(shape);
395
+ },
396
+ record(key, value) {
397
+ return z2.record(classic(key), classic(value));
398
+ },
399
+ superRefine: (schema, check) => classic(schema).superRefine(check),
400
+ pipe: (input, output) => classic(input).pipe(classic(output))
401
+ };
402
+ }
403
+ });
404
+
405
+ // src/portable-identity.ts
406
+ var schemas, tileflowPortableIdSchema, tileflowThemeNameSchema;
407
+ var init_portable_identity = __esm({
408
+ "src/portable-identity.ts"() {
409
+ "use strict";
410
+ init_manifest_schema_classic();
411
+ init_portable_identity_schema();
412
+ schemas = createPortableIdentitySchemas(classicManifestStringOperations);
413
+ tileflowPortableIdSchema = schemas.tileflowPortableIdSchema;
414
+ tileflowThemeNameSchema = schemas.tileflowThemeNameSchema;
415
+ }
416
+ });
417
+
418
+ // src/manifest.ts
419
+ var manifest_exports = {};
420
+ __export(manifest_exports, {
421
+ parseTileflowRuntimeManifest: () => parseTileflowRuntimeManifest,
422
+ safeParseTileflowRuntimeManifest: () => safeParseTileflowRuntimeManifest,
423
+ tileflowRuntimeManifestLimits: () => tileflowRuntimeManifestLimits,
424
+ tileflowRuntimeManifestSchema: () => tileflowRuntimeManifestSchema,
425
+ tileflowRuntimeManifestVersion: () => tileflowRuntimeManifestVersion
426
+ });
427
+ function parseTileflowRuntimeManifest(input) {
428
+ return tileflowRuntimeManifestSchema.parse(input);
429
+ }
430
+ function safeParseTileflowRuntimeManifest(input) {
431
+ return tileflowRuntimeManifestSchema.safeParse(input);
432
+ }
433
+ var tileflowRuntimeManifestSchema;
434
+ var init_manifest = __esm({
435
+ "src/manifest.ts"() {
436
+ "use strict";
437
+ init_manifest_schema();
438
+ init_manifest_schema_classic();
439
+ init_portable_identity();
440
+ init_manifest_types();
441
+ tileflowRuntimeManifestSchema = createTileflowRuntimeManifestSchema(
442
+ {
443
+ parseUrl: (value, base) => base === void 0 ? new URL(value) : new URL(value, base),
444
+ utf8ByteLength: (value) => new TextEncoder().encode(value).byteLength
445
+ },
446
+ classicManifestSchemaOperations,
447
+ { tileflowPortableIdSchema, tileflowThemeNameSchema }
448
+ );
299
449
  }
300
450
  });
301
451
 
@@ -325,7 +475,7 @@ var maximumSessionGrantBytes = 64 * 1024;
325
475
  var manifestCache = new globalThis.Map();
326
476
  var missingStaticMapIdWarnings = /* @__PURE__ */ new Set();
327
477
  function shouldLoadTileflowManifest(options) {
328
- return options.source.kind === "tileflow";
478
+ return validateTileflowRuntimeSource(options.source).ok;
329
479
  }
330
480
  function validateTileflowRuntimeSource(source) {
331
481
  if (source === void 0) {
@@ -334,32 +484,14 @@ function validateTileflowRuntimeSource(source) {
334
484
  if (!isPlainRuntimeRecord(source)) {
335
485
  return { code: "invalid-source", error: "source must be an object", ok: false };
336
486
  }
337
- if (source.kind === "tileflow") {
338
- if (!isTileflowPortableId(source.map) || source.manifestUrl !== void 0 && (typeof source.manifestUrl !== "string" || source.manifestUrl.length === 0)) {
339
- return {
340
- code: "invalid-source",
341
- error: "a tileflow source requires a portable map id and an optional non-empty manifestUrl",
342
- ok: false
343
- };
344
- }
345
- return { ok: true };
346
- }
347
- if (source.kind === "maplibre") {
348
- const style = source.style;
349
- if ((typeof style !== "string" || style.length === 0) && (!style || typeof style !== "object" || Array.isArray(style))) {
350
- return {
351
- code: "invalid-source",
352
- error: "a maplibre source requires a style object or non-empty style URL",
353
- ok: false
354
- };
355
- }
356
- return { ok: true };
487
+ if ("kind" in source || "style" in source || !isTileflowPortableId(source.map) || source.manifestUrl !== void 0 && (typeof source.manifestUrl !== "string" || source.manifestUrl.length === 0)) {
488
+ return {
489
+ code: "invalid-source",
490
+ error: "source requires a portable map id and an optional non-empty manifestUrl; renderer inputs are not supported",
491
+ ok: false
492
+ };
357
493
  }
358
- return {
359
- code: "invalid-source",
360
- error: "source.kind must be 'tileflow' or 'maplibre'",
361
- ok: false
362
- };
494
+ return { ok: true };
363
495
  }
364
496
  function validateTileflowThemeSelection(value) {
365
497
  return value === "system" || isTileflowThemeName(value);
@@ -372,21 +504,6 @@ function assertValidTileflowRuntimeSource(source) {
372
504
  }
373
505
  function resolveTileflowRuntimeStyle(options) {
374
506
  assertValidTileflowRuntimeSource(options.source);
375
- if (options.source.kind === "maplibre") {
376
- if (options.theme !== void 0) {
377
- throw new TypeError("The theme option is only valid for a Tileflow map source.");
378
- }
379
- if (typeof options.source.style !== "string") {
380
- return {
381
- fontFaces: getTileflowStyleFontFaces(options.source.style),
382
- style: options.source.style
383
- };
384
- }
385
- return {
386
- analytics: inferTileflowAnalyticsFromStyleUrl(options.source.style),
387
- style: options.source.style
388
- };
389
- }
390
507
  if (options.manifestMap) {
391
508
  const theme = resolveTileflowRuntimeTheme(
392
509
  options.manifestMap,
@@ -3,7 +3,7 @@
3
3
  Start with the [@tileflow/core guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md) for installation and a complete first example.
4
4
 
5
5
  Tileflow exposes one authoring concept and one constructor: `defineMap()`. A complete map omits
6
- `extends`; an inherited map sets `extends` to another imported map object. All ten first-party
6
+ `extends`; an inherited map sets `extends` to another imported map object. All first-party
7
7
  maps are independent standalone maps. They use the sole semantic compiler while defining
8
8
  their complete designs and asset providers directly; no official map imports or extends another
9
9
  official map. Applications can extend any of those maps through the same public API. Streets
@@ -106,7 +106,7 @@ const companyBase = defineMap({
106
106
  version: 1,
107
107
  glyphs: {
108
108
  kind: 'url',
109
- url: 'https://api.tileflow.dev/fonts/{fontstack}/{range}.pbf',
109
+ url: 'https://api.tileflow.dev/base/33d4de5e8086d9d629d67d3f39fedb87e23686c4c1ac653c27e2a52aee9d00b3/glyphs/{fontstack}/{range}.pbf',
110
110
  fontStacks: ['Noto Sans Regular', 'Noto Sans Bold'],
111
111
  },
112
112
  icons: [streetsIcons],
@@ -126,8 +126,9 @@ export default defineMap({
126
126
  The standalone map above is complete as written. A map always owns its complete text provider; Core does not
127
127
  obtain fonts or sprites from World and never invents a fallback URL. The URL-backed first-party
128
128
  `streets`, `ferraris`, `harad`, `soundings`, `verdant`, and `sanFrancisto` maps declare their glyph
129
- providers directly, while `baedeker`, `siegfried`, `cyberpunk`, and `matrix` declare packaged fonts, so ordinary imports and derived
130
- maps compile without out-of-band release metadata.
129
+ providers directly. `baedeker`, `civica`, `cyberpunk`, `matrix`, `siegfried`, and `superTileWorld`
130
+ declare packaged fonts, so ordinary imports and derived maps compile without out-of-band release
131
+ metadata.
131
132
 
132
133
  ```mermaid
133
134
  flowchart LR