@tileflow/core 0.1.0-alpha.17 → 0.1.0-alpha.18
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 +13 -0
- package/dist/browser.d.ts +4 -1
- package/dist/browser.js +29 -12
- package/dist/index.d.ts +2 -2
- package/dist/index.js +248 -6
- package/dist/{runtime-BMZ_tuba.d.ts → runtime-Bg--GMWM.d.ts} +25 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -272,6 +272,19 @@ their frame scheduler plus MapLibre event and marker operations after mount. The
|
|
|
272
272
|
is documented in
|
|
273
273
|
[`docs/contracts/framework-browser-runtime.md`](../../docs/contracts/framework-browser-runtime.md).
|
|
274
274
|
|
|
275
|
+
## Hosted session authorization
|
|
276
|
+
|
|
277
|
+
The framework adapters use `createTileflowSessionController` to obtain one short-lived session
|
|
278
|
+
grant before eligible hosted style, tile, font, or sprite requests. Concurrent resources share the
|
|
279
|
+
same preflight, grants are attached only to reviewed HTTP(S) origins, and an expired unused session
|
|
280
|
+
rotates once when the server requests it. A controller also rotates after six hours or 10,000
|
|
281
|
+
eligible requests. The preflight has a 10-second client timeout by default; direct controller users
|
|
282
|
+
can set `grantTimeoutMs` from 1 to 120,000 milliseconds.
|
|
283
|
+
|
|
284
|
+
`analytics.enabled: false` disables only the optional analytics beacon. It does not disable this
|
|
285
|
+
server-owned commercial authorization. User `transformRequest` callbacks still run first; Tileflow
|
|
286
|
+
then decorates only the resulting eligible URL and preserves the other request options.
|
|
287
|
+
|
|
275
288
|
Other subpaths under `src/`, `themes/`, `templates/`, and `modules/` are internal implementation
|
|
276
289
|
details and can change during alpha releases.
|
|
277
290
|
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { T as TileflowAnalytics } from './runtime-
|
|
1
|
+
import { T as TileflowAnalytics, a as TileflowSessionController } from './runtime-Bg--GMWM.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
|
|
4
4
|
type TileflowMapReadinessState = 'error' | 'idle' | 'loading';
|
|
@@ -35,6 +35,7 @@ type TileflowMarkerController<TMap, TDefinition, TMarker> = {
|
|
|
35
35
|
replace: (map: TMap, definitions: readonly TDefinition[]) => void;
|
|
36
36
|
};
|
|
37
37
|
declare function createTileflowSessionStarter(options: {
|
|
38
|
+
getSessionId?: () => string;
|
|
38
39
|
sessionId: string;
|
|
39
40
|
source: string;
|
|
40
41
|
startSession?: TileflowSessionSender;
|
|
@@ -55,6 +56,7 @@ declare function createTileflowTransformRequest<TRequest extends TileflowTransfo
|
|
|
55
56
|
always: true;
|
|
56
57
|
asyncAnalyticsTiming?: TileflowAsyncAnalyticsTiming;
|
|
57
58
|
getAnalytics: () => TileflowAnalytics | undefined;
|
|
59
|
+
sessionController?: TileflowSessionController;
|
|
58
60
|
sessionId: string;
|
|
59
61
|
transformRequest?: TileflowUserTransformRequest<TRequest, TResourceType>;
|
|
60
62
|
}): TileflowTransformRequest<TRequest, TResourceType>;
|
|
@@ -62,6 +64,7 @@ declare function createTileflowTransformRequest<TRequest extends TileflowTransfo
|
|
|
62
64
|
always?: boolean;
|
|
63
65
|
asyncAnalyticsTiming?: TileflowAsyncAnalyticsTiming;
|
|
64
66
|
getAnalytics: () => TileflowAnalytics | undefined;
|
|
67
|
+
sessionController?: TileflowSessionController;
|
|
65
68
|
sessionId: string;
|
|
66
69
|
transformRequest?: TileflowUserTransformRequest<TRequest, TResourceType>;
|
|
67
70
|
}): TileflowTransformRequest<TRequest, TResourceType> | undefined;
|
package/dist/browser.js
CHANGED
|
@@ -26,7 +26,7 @@ function startTileflowSession(analytics, input) {
|
|
|
26
26
|
if (!analytics || analytics.enabled === false || !input.mapId || typeof navigator === "undefined") {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
-
const endpoint = analytics.endpoint ?? `${getTileflowAnalyticsApiUrl(analytics)}/v1/sessions/
|
|
29
|
+
const endpoint = analytics.endpoint ?? `${getTileflowAnalyticsApiUrl(analytics)}/v1/sessions/analytics`;
|
|
30
30
|
const payload = JSON.stringify({
|
|
31
31
|
mapId: input.mapId,
|
|
32
32
|
metadata: analytics.metadata,
|
|
@@ -49,7 +49,7 @@ function startTileflowSession(analytics, input) {
|
|
|
49
49
|
},
|
|
50
50
|
keepalive: true,
|
|
51
51
|
method: "POST"
|
|
52
|
-
});
|
|
52
|
+
}).catch(() => void 0);
|
|
53
53
|
}
|
|
54
54
|
function getTileflowAnalyticsApiUrl(analytics) {
|
|
55
55
|
if (analytics.apiUrl) {
|
|
@@ -94,17 +94,18 @@ function createTileflowSessionStarter(options) {
|
|
|
94
94
|
},
|
|
95
95
|
start(analytics, styleId) {
|
|
96
96
|
const mapId = analytics?.mapId;
|
|
97
|
+
const sessionId = options.getSessionId?.() ?? options.sessionId;
|
|
97
98
|
if (!mapId) {
|
|
98
99
|
return false;
|
|
99
100
|
}
|
|
100
|
-
const key = `${
|
|
101
|
+
const key = `${sessionId}:${mapId}:${styleId ?? ""}`;
|
|
101
102
|
if (starts.has(key)) {
|
|
102
103
|
return false;
|
|
103
104
|
}
|
|
104
105
|
starts.add(key);
|
|
105
106
|
send(analytics, {
|
|
106
107
|
mapId,
|
|
107
|
-
sessionId
|
|
108
|
+
sessionId,
|
|
108
109
|
source: options.source,
|
|
109
110
|
styleId
|
|
110
111
|
});
|
|
@@ -216,7 +217,8 @@ function attachTileflowMapLifecycle(options) {
|
|
|
216
217
|
function createTileflowTransformRequest(options) {
|
|
217
218
|
if (!options.always && !options.transformRequest) {
|
|
218
219
|
const analytics = options.getAnalytics();
|
|
219
|
-
|
|
220
|
+
const requiresCommercialSession = Boolean(options.sessionController && analytics?.mapId);
|
|
221
|
+
if (!requiresCommercialSession && (!analytics || analytics.enabled === false)) {
|
|
220
222
|
return void 0;
|
|
221
223
|
}
|
|
222
224
|
}
|
|
@@ -226,19 +228,21 @@ function createTileflowTransformRequest(options) {
|
|
|
226
228
|
const analyticsAtRequest = asyncAnalyticsTiming === "request" ? options.getAnalytics() : void 0;
|
|
227
229
|
if (isPromiseLike(request)) {
|
|
228
230
|
return request.then(
|
|
229
|
-
(resolvedRequest) =>
|
|
231
|
+
(resolvedRequest) => applyTileflowRequest(
|
|
230
232
|
url,
|
|
231
233
|
resolvedRequest,
|
|
232
234
|
asyncAnalyticsTiming === "resolution" ? options.getAnalytics() : analyticsAtRequest,
|
|
233
|
-
options.sessionId
|
|
235
|
+
options.sessionId,
|
|
236
|
+
options.sessionController
|
|
234
237
|
) ?? resolvedRequest
|
|
235
238
|
);
|
|
236
239
|
}
|
|
237
|
-
return
|
|
240
|
+
return applyTileflowRequest(
|
|
238
241
|
url,
|
|
239
242
|
request,
|
|
240
243
|
asyncAnalyticsTiming === "resolution" ? options.getAnalytics() : analyticsAtRequest,
|
|
241
|
-
options.sessionId
|
|
244
|
+
options.sessionId,
|
|
245
|
+
options.sessionController
|
|
242
246
|
);
|
|
243
247
|
};
|
|
244
248
|
}
|
|
@@ -272,10 +276,23 @@ function createTileflowMarkerController(options) {
|
|
|
272
276
|
}
|
|
273
277
|
};
|
|
274
278
|
}
|
|
275
|
-
function
|
|
276
|
-
const
|
|
279
|
+
function applyTileflowRequest(url, request, analytics, sessionId, sessionController) {
|
|
280
|
+
const requestUrl = request?.url ?? url;
|
|
281
|
+
if (sessionController) {
|
|
282
|
+
return sessionController.resolveRequestUrl(requestUrl, analytics).then(
|
|
283
|
+
(nextUrl) => composeTileflowRequest(url, request, nextUrl, true) ?? { url }
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
return composeTileflowRequest(
|
|
287
|
+
url,
|
|
288
|
+
request,
|
|
289
|
+
resolveTileflowAnalyticsRequestUrl(requestUrl, analytics, sessionId),
|
|
290
|
+
false
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
function composeTileflowRequest(originalUrl, request, nextUrl, ensureRequest) {
|
|
277
294
|
if (!nextUrl) {
|
|
278
|
-
return request;
|
|
295
|
+
return request ?? (ensureRequest ? { url: originalUrl } : void 0);
|
|
279
296
|
}
|
|
280
297
|
return request ? { ...request, url: nextUrl } : { url: nextUrl };
|
|
281
298
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { M as MapLibreSprite,
|
|
1
|
+
import { b as TileflowConfig, c as TileflowProjectConfig, V as ValidationResult, d as TileflowOsmBasemapOptions, e as TileflowOsmBasemapConfig, f as TileflowRoadsModuleOptions, g as TileflowRoadsModuleConfig, h as TileflowLabelsModuleOptions, i as TileflowLabelsModuleConfig, j as TileflowPoiModuleOptions, k as TileflowPoiModuleConfig, l as TileflowStyleOverrideOptions, m as TileflowStyleOverrideModuleConfig } from './runtime-Bg--GMWM.js';
|
|
2
|
+
export { M as MapLibreSprite, n as MapLibreStyle, N as NormalizedTileflowCaptureScene, R as ResolvedTileflowTypography, o as TileflowAdvancedColorConfig, T as TileflowAnalytics, p as TileflowBaseColors, q as TileflowBasemapConfig, r as TileflowBoundaryColorConfig, s as TileflowBuildingColorConfig, t as TileflowBuildingStyleConfig, u as TileflowBuildings, v as TileflowCaptureApplicationTarget, w as TileflowCaptureBoundsCamera, x as TileflowCaptureCamera, y as TileflowCaptureCenterCamera, z as TileflowCaptureMapTarget, A as TileflowCaptureScene, B as TileflowCaptureTarget, C as TileflowCaptureViewport, D as TileflowColor, E as TileflowColorConfig, F as TileflowColors, G as TileflowDensity, H as TileflowFontWeight, I as TileflowFonts, J as TileflowHostedNotoSansWeight, K as TileflowHydroColorConfig, L as TileflowIconSet, O as TileflowIconSetConfig, P as TileflowLabelColorConfig, Q as TileflowLabelDetail, S as TileflowLabelLanguage, U as TileflowLabels, W as TileflowLandcoverColorConfig, X as TileflowLanduseColorConfig, Y as TileflowManifest, Z as TileflowManifestLoadOptions, _ as TileflowMapConfig, $ as TileflowMapMarker, a0 as TileflowMapMode, a1 as TileflowMapModeOptions, a2 as TileflowModuleConfig, a3 as TileflowPoi, a4 as TileflowPoiCategory, a5 as TileflowPoiClassMapping, a6 as TileflowPoiColorConfig, a7 as TileflowPoiColorMode, a8 as TileflowPoiDensity, a9 as TileflowPoiIcons, aa as TileflowPoiLabels, ab as TileflowProjectIconSets, ac as TileflowProjectThemes, ad as TileflowRenderer, ae as TileflowRoadClass, af as TileflowRoadColorConfig, ag as TileflowRoadDetail, ah as TileflowRoadExtras, ai as TileflowRoadHierarchy, aj as TileflowRoadLabelDetail, ak as TileflowRoadOutline, al as TileflowRoadWeight, am as TileflowRoads, an as TileflowRuntimeManifest, ao as TileflowRuntimeManifestMap, ap as TileflowRuntimeManifestMapEntry, aq as TileflowRuntimeStyle, ar as TileflowRuntimeStyleOptions, a as TileflowSessionController, as as TileflowSessionGrantResponse, at as TileflowSourceLayers, au as TileflowStyleLayerOverride, av as TileflowStyleOptions, aw as TileflowTerrain, ax as TileflowTerrainConfig, ay as TileflowTerrainEncoding, az as TileflowTerrainMode, aA as TileflowTheme, aB as TileflowThemeConfig, aC as TileflowThemeMode, aD as TileflowThemeModulesConfig, aE as TileflowThemeName, aF as TileflowTiles, aG as TileflowTilesetConfig, aH as TileflowTypography, aI as TileflowTypographyDomain, aJ as TileflowTypographyStyle, aK as TileflowViewConfig, aL as ValidationMessage, aM as createManifest, aN as createStyle, aO as createStyleFromProject, aP as createTileflowSessionController, aQ as createTileflowSessionId, aR as defaultTileflowManifestUrl, aS as defaultTileflowStyleBaseUrl, aT as getDefaultColors, aU as getDefaultTileflowStyleBaseUrl, aV as getTileflowAnalyticsApiUrl, aW as inferTileflowAnalyticsFromStyleUrl, aX as isTileflowLocalDevHost, aY as loadTileflowManifest, aZ as mergeTileflowAnalytics, a_ as normalizeTileflowCaptureId, a$ as normalizeTileflowCaptureScene, b0 as normalizeTileflowStaticImageSize, b1 as normalizeTileflowUrl, b2 as resolveTileflowAnalyticsRequestUrl, b3 as resolveTileflowManifestMap, b4 as resolveTileflowMapMode, b5 as resolveTileflowRuntimeStyle, b6 as resolveTileflowStaticImageUrl, b7 as resolveTileflowStyleUrl, b8 as shouldLoadTileflowManifest, b9 as startTileflowSession, ba as tileflowCaptureApplicationTargetSchema, bb as tileflowCaptureBoundsCameraSchema, bc as tileflowCaptureCameraSchema, bd as tileflowCaptureCenterCameraSchema, be as tileflowCaptureIdSchema, bf as tileflowCaptureMapTargetSchema, bg as tileflowCaptureSceneLimits, bh as tileflowCaptureSceneNameSchema, bi as tileflowCaptureSceneSchema, bj as tileflowCaptureSceneSchemaVersion, bk as tileflowCaptureTargetSchema, bl as tileflowCaptureViewportSchema, bm as tileflowHostedNotoSansWeights } from './runtime-Bg--GMWM.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
declare const tileflowThemeSchema: z.ZodObject<{
|
package/dist/index.js
CHANGED
|
@@ -6821,6 +6821,250 @@ function createTileflowSessionId() {
|
|
|
6821
6821
|
}
|
|
6822
6822
|
return `ses_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`;
|
|
6823
6823
|
}
|
|
6824
|
+
function createTileflowSessionController(input) {
|
|
6825
|
+
const fetchGrant = input.fetch ?? globalThis.fetch;
|
|
6826
|
+
const grantTimeoutMs = validateSessionGrantTimeout(input.grantTimeoutMs);
|
|
6827
|
+
const now = input.now ?? (() => /* @__PURE__ */ new Date());
|
|
6828
|
+
const sessionIdFactory = input.sessionIdFactory ?? createTileflowSessionId;
|
|
6829
|
+
const createSession = (startedAt) => ({
|
|
6830
|
+
binding: null,
|
|
6831
|
+
grant: null,
|
|
6832
|
+
grantPromise: null,
|
|
6833
|
+
pendingGrantRequests: 0,
|
|
6834
|
+
requestCount: 0,
|
|
6835
|
+
sessionId: sessionIdFactory(),
|
|
6836
|
+
startedAt
|
|
6837
|
+
});
|
|
6838
|
+
let activeSession = createSession(now().getTime());
|
|
6839
|
+
async function resolveGrant(session, analytics, at) {
|
|
6840
|
+
if (session.grant && session.grant.expiresAt - at > 3e4) {
|
|
6841
|
+
return { grant: session.grant, session };
|
|
6842
|
+
}
|
|
6843
|
+
session.pendingGrantRequests += 1;
|
|
6844
|
+
try {
|
|
6845
|
+
if (!session.grantPromise) {
|
|
6846
|
+
const pending = (async () => {
|
|
6847
|
+
try {
|
|
6848
|
+
const nextGrant = await requestSessionGrant({
|
|
6849
|
+
analytics,
|
|
6850
|
+
at,
|
|
6851
|
+
fetchGrant,
|
|
6852
|
+
timeoutMs: grantTimeoutMs,
|
|
6853
|
+
sessionId: session.sessionId,
|
|
6854
|
+
source: input.source
|
|
6855
|
+
});
|
|
6856
|
+
session.grant = nextGrant;
|
|
6857
|
+
return { grant: nextGrant, session };
|
|
6858
|
+
} catch (error) {
|
|
6859
|
+
if (!(error instanceof TileflowSessionRestartError)) throw error;
|
|
6860
|
+
const replacement = createSession(at);
|
|
6861
|
+
replacement.binding = session.binding;
|
|
6862
|
+
replacement.requestCount = session.pendingGrantRequests;
|
|
6863
|
+
if (activeSession === session) activeSession = replacement;
|
|
6864
|
+
const replacementPending = requestSessionGrant({
|
|
6865
|
+
analytics,
|
|
6866
|
+
at,
|
|
6867
|
+
fetchGrant,
|
|
6868
|
+
timeoutMs: grantTimeoutMs,
|
|
6869
|
+
sessionId: replacement.sessionId,
|
|
6870
|
+
source: input.source
|
|
6871
|
+
}).then((nextGrant) => {
|
|
6872
|
+
replacement.grant = nextGrant;
|
|
6873
|
+
return { grant: nextGrant, session: replacement };
|
|
6874
|
+
});
|
|
6875
|
+
replacement.grantPromise = replacementPending;
|
|
6876
|
+
try {
|
|
6877
|
+
return await replacementPending;
|
|
6878
|
+
} finally {
|
|
6879
|
+
if (replacement.grantPromise === replacementPending) {
|
|
6880
|
+
replacement.grantPromise = null;
|
|
6881
|
+
}
|
|
6882
|
+
}
|
|
6883
|
+
} finally {
|
|
6884
|
+
session.grantPromise = null;
|
|
6885
|
+
}
|
|
6886
|
+
})();
|
|
6887
|
+
session.grantPromise = pending;
|
|
6888
|
+
}
|
|
6889
|
+
return await session.grantPromise;
|
|
6890
|
+
} finally {
|
|
6891
|
+
session.pendingGrantRequests -= 1;
|
|
6892
|
+
}
|
|
6893
|
+
}
|
|
6894
|
+
return {
|
|
6895
|
+
get sessionId() {
|
|
6896
|
+
return activeSession.sessionId;
|
|
6897
|
+
},
|
|
6898
|
+
async resolveRequestUrl(url, analytics) {
|
|
6899
|
+
if (!analytics || !analytics.mapId) return void 0;
|
|
6900
|
+
const at = now().getTime();
|
|
6901
|
+
if (at - activeSession.startedAt >= 6 * 60 * 60 * 1e3 || activeSession.requestCount >= 1e4) {
|
|
6902
|
+
activeSession = createSession(at);
|
|
6903
|
+
}
|
|
6904
|
+
const apiOrigin = originOf(getTileflowAnalyticsApiUrl(analytics));
|
|
6905
|
+
const binding = JSON.stringify([getTileflowAnalyticsApiUrl(analytics), analytics.mapId]);
|
|
6906
|
+
let session = activeSession;
|
|
6907
|
+
const grantedOrigins = session.binding === binding ? session.grant?.resourceOrigins : void 0;
|
|
6908
|
+
if (!isEligibleResource(url, analytics.mapId, apiOrigin, grantedOrigins)) {
|
|
6909
|
+
return void 0;
|
|
6910
|
+
}
|
|
6911
|
+
if (session.binding !== null && session.binding !== binding) {
|
|
6912
|
+
session = createSession(at);
|
|
6913
|
+
activeSession = session;
|
|
6914
|
+
}
|
|
6915
|
+
session.binding = binding;
|
|
6916
|
+
session.requestCount += 1;
|
|
6917
|
+
const resolved = await resolveGrant(session, analytics, at);
|
|
6918
|
+
const nextUrl = new URL(url);
|
|
6919
|
+
nextUrl.searchParams.set("session", resolved.session.sessionId);
|
|
6920
|
+
nextUrl.searchParams.set("map", analytics.mapId);
|
|
6921
|
+
if (analytics.styleId) nextUrl.searchParams.set("styleId", analytics.styleId);
|
|
6922
|
+
if (resolved.grant.token) nextUrl.searchParams.set("grant", resolved.grant.token);
|
|
6923
|
+
return nextUrl.toString();
|
|
6924
|
+
}
|
|
6925
|
+
};
|
|
6926
|
+
}
|
|
6927
|
+
async function requestSessionGrant(input) {
|
|
6928
|
+
return runWithinSessionGrantTimeout(input.timeoutMs, async (signal) => {
|
|
6929
|
+
const apiUrl = getTileflowAnalyticsApiUrl(input.analytics);
|
|
6930
|
+
const response = await input.fetchGrant(`${apiUrl}/v1/sessions/start`, {
|
|
6931
|
+
body: JSON.stringify({
|
|
6932
|
+
mapId: input.analytics.mapId,
|
|
6933
|
+
sdkVersion: input.analytics.sdkVersion,
|
|
6934
|
+
sessionId: input.sessionId,
|
|
6935
|
+
source: input.analytics.source ?? input.source,
|
|
6936
|
+
styleId: input.analytics.styleId
|
|
6937
|
+
}),
|
|
6938
|
+
credentials: "omit",
|
|
6939
|
+
headers: { "Content-Type": "application/json" },
|
|
6940
|
+
method: "POST",
|
|
6941
|
+
signal
|
|
6942
|
+
});
|
|
6943
|
+
throwIfSessionGrantAborted(signal);
|
|
6944
|
+
const body = await response.json().catch(() => null);
|
|
6945
|
+
throwIfSessionGrantAborted(signal);
|
|
6946
|
+
if (response.status === 409 && isRecord6(body) && body.code === "COMMERCIAL_SESSION_RESTART_REQUIRED" && body.ok === false && body.retryWithNewSession === true && body.sessionId === input.sessionId) {
|
|
6947
|
+
throw new TileflowSessionRestartError();
|
|
6948
|
+
}
|
|
6949
|
+
if (!response.ok) {
|
|
6950
|
+
throw new Error(`Tileflow session grant failed: ${response.status}`);
|
|
6951
|
+
}
|
|
6952
|
+
const parsed = parseSessionGrantResponse(body, input.sessionId);
|
|
6953
|
+
if (!parsed) {
|
|
6954
|
+
throw new Error("Tileflow session grant response was invalid.");
|
|
6955
|
+
}
|
|
6956
|
+
const expiresAt = parsed.grant ? Date.parse(parsed.expiresAt) : input.at + 6e4;
|
|
6957
|
+
if (response.status === 201 && (!parsed.grant || !parsed.expiresAt) || parsed.grant && (!Number.isFinite(expiresAt) || expiresAt <= input.at)) {
|
|
6958
|
+
throw new Error("Tileflow session grant response was invalid.");
|
|
6959
|
+
}
|
|
6960
|
+
return {
|
|
6961
|
+
expiresAt,
|
|
6962
|
+
resourceOrigins: new Set(
|
|
6963
|
+
[originOf(apiUrl), ...(parsed.resourceOrigins ?? []).map(originOf)].filter(
|
|
6964
|
+
(value) => Boolean(value)
|
|
6965
|
+
)
|
|
6966
|
+
),
|
|
6967
|
+
token: parsed.grant ?? null
|
|
6968
|
+
};
|
|
6969
|
+
});
|
|
6970
|
+
}
|
|
6971
|
+
function validateSessionGrantTimeout(value) {
|
|
6972
|
+
const resolved = value ?? 1e4;
|
|
6973
|
+
if (!Number.isSafeInteger(resolved) || resolved < 1 || resolved > 12e4) {
|
|
6974
|
+
throw new Error("Tileflow session grantTimeoutMs must be an integer from 1 to 120000");
|
|
6975
|
+
}
|
|
6976
|
+
return resolved;
|
|
6977
|
+
}
|
|
6978
|
+
async function runWithinSessionGrantTimeout(timeoutMs, operation) {
|
|
6979
|
+
const controller = new AbortController();
|
|
6980
|
+
const timeoutError = new Error(`Tileflow session grant timed out after ${timeoutMs}ms`);
|
|
6981
|
+
const timeout = setTimeout(() => controller.abort(timeoutError), timeoutMs);
|
|
6982
|
+
try {
|
|
6983
|
+
return await raceSessionGrantWithAbort(operation(controller.signal), controller.signal);
|
|
6984
|
+
} finally {
|
|
6985
|
+
clearTimeout(timeout);
|
|
6986
|
+
}
|
|
6987
|
+
}
|
|
6988
|
+
function raceSessionGrantWithAbort(operation, signal) {
|
|
6989
|
+
if (signal.aborted) return Promise.reject(sessionGrantAbortReason(signal));
|
|
6990
|
+
return new Promise((resolve, reject) => {
|
|
6991
|
+
const onAbort = () => {
|
|
6992
|
+
cleanup();
|
|
6993
|
+
reject(sessionGrantAbortReason(signal));
|
|
6994
|
+
};
|
|
6995
|
+
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
6996
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
6997
|
+
operation.then(
|
|
6998
|
+
(value) => {
|
|
6999
|
+
cleanup();
|
|
7000
|
+
resolve(value);
|
|
7001
|
+
},
|
|
7002
|
+
(error) => {
|
|
7003
|
+
cleanup();
|
|
7004
|
+
reject(error);
|
|
7005
|
+
}
|
|
7006
|
+
);
|
|
7007
|
+
});
|
|
7008
|
+
}
|
|
7009
|
+
function throwIfSessionGrantAborted(signal) {
|
|
7010
|
+
if (signal.aborted) throw sessionGrantAbortReason(signal);
|
|
7011
|
+
}
|
|
7012
|
+
function sessionGrantAbortReason(signal) {
|
|
7013
|
+
if (signal.reason instanceof Error) return signal.reason;
|
|
7014
|
+
const error = new Error("Tileflow session grant was aborted");
|
|
7015
|
+
error.name = "AbortError";
|
|
7016
|
+
return error;
|
|
7017
|
+
}
|
|
7018
|
+
function parseSessionGrantResponse(value, expectedSessionId) {
|
|
7019
|
+
if (!isRecord6(value) || value.ok !== true || value.sessionId !== expectedSessionId) return null;
|
|
7020
|
+
if (value.usageMode !== void 0 && value.usageMode !== "session") return null;
|
|
7021
|
+
if (value.billingEnabled !== void 0 && value.billingEnabled !== false) return null;
|
|
7022
|
+
if (value.disposition !== void 0 && value.disposition !== "ordinary" && value.disposition !== "unbilled_fail_open") {
|
|
7023
|
+
return null;
|
|
7024
|
+
}
|
|
7025
|
+
if (value.meterMode !== void 0 && value.meterMode !== "disabled" && value.meterMode !== "shadow" && value.meterMode !== "enforced") {
|
|
7026
|
+
return null;
|
|
7027
|
+
}
|
|
7028
|
+
if (value.grant !== void 0 && (typeof value.grant !== "string" || value.grant.length === 0 || value.grant.length > 8192)) {
|
|
7029
|
+
return null;
|
|
7030
|
+
}
|
|
7031
|
+
if (value.expiresAt !== void 0 && typeof value.expiresAt !== "string") return null;
|
|
7032
|
+
if (value.grant !== void 0 && value.expiresAt === void 0) return null;
|
|
7033
|
+
if (value.resourceOrigins !== void 0 && (!Array.isArray(value.resourceOrigins) || value.resourceOrigins.length > 32 || value.resourceOrigins.some((origin) => !originOf(origin)))) {
|
|
7034
|
+
return null;
|
|
7035
|
+
}
|
|
7036
|
+
return value;
|
|
7037
|
+
}
|
|
7038
|
+
function isRecord6(value) {
|
|
7039
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
7040
|
+
}
|
|
7041
|
+
var TileflowSessionRestartError = class extends Error {
|
|
7042
|
+
constructor() {
|
|
7043
|
+
super("Tileflow session must restart");
|
|
7044
|
+
this.name = "TileflowSessionRestartError";
|
|
7045
|
+
}
|
|
7046
|
+
};
|
|
7047
|
+
function isEligibleResource(value, mapId, apiOrigin, grantedOrigins) {
|
|
7048
|
+
try {
|
|
7049
|
+
const url = new URL(value);
|
|
7050
|
+
if (url.username || url.password) return false;
|
|
7051
|
+
const originAllowed = url.origin === apiOrigin || grantedOrigins?.has(url.origin) || apiOrigin === "https://api.tileflow.dev" && url.origin === "https://cdn.tileflow.dev";
|
|
7052
|
+
if (!originAllowed) return false;
|
|
7053
|
+
return url.pathname === `/maps/${encodeURIComponent(mapId)}/style.json` || url.pathname.startsWith("/tiles/") || url.pathname.startsWith("/v1/tiles/") || url.pathname.startsWith("/fonts/") || url.pathname.startsWith("/sprites/");
|
|
7054
|
+
} catch {
|
|
7055
|
+
return false;
|
|
7056
|
+
}
|
|
7057
|
+
}
|
|
7058
|
+
function originOf(value) {
|
|
7059
|
+
if (typeof value !== "string") return null;
|
|
7060
|
+
try {
|
|
7061
|
+
const url = new URL(value);
|
|
7062
|
+
if (!["http:", "https:"].includes(url.protocol) || url.username || url.password) return null;
|
|
7063
|
+
return url.origin;
|
|
7064
|
+
} catch {
|
|
7065
|
+
return null;
|
|
7066
|
+
}
|
|
7067
|
+
}
|
|
6824
7068
|
function resolveTileflowAnalyticsRequestUrl(url, analytics, sessionId) {
|
|
6825
7069
|
if (!analytics || analytics.enabled === false) {
|
|
6826
7070
|
return void 0;
|
|
@@ -6843,7 +7087,7 @@ function startTileflowSession(analytics, input) {
|
|
|
6843
7087
|
if (!analytics || analytics.enabled === false || !input.mapId || typeof navigator === "undefined") {
|
|
6844
7088
|
return;
|
|
6845
7089
|
}
|
|
6846
|
-
const endpoint = analytics.endpoint ?? `${getTileflowAnalyticsApiUrl(analytics)}/v1/sessions/
|
|
7090
|
+
const endpoint = analytics.endpoint ?? `${getTileflowAnalyticsApiUrl(analytics)}/v1/sessions/analytics`;
|
|
6847
7091
|
const payload = JSON.stringify({
|
|
6848
7092
|
mapId: input.mapId,
|
|
6849
7093
|
metadata: analytics.metadata,
|
|
@@ -6866,7 +7110,7 @@ function startTileflowSession(analytics, input) {
|
|
|
6866
7110
|
},
|
|
6867
7111
|
keepalive: true,
|
|
6868
7112
|
method: "POST"
|
|
6869
|
-
});
|
|
7113
|
+
}).catch(() => void 0);
|
|
6870
7114
|
}
|
|
6871
7115
|
function getTileflowAnalyticsApiUrl(analytics) {
|
|
6872
7116
|
if (analytics.apiUrl) {
|
|
@@ -6883,9 +7127,6 @@ function getTileflowAnalyticsApiUrl(analytics) {
|
|
|
6883
7127
|
return "https://api.tileflow.dev";
|
|
6884
7128
|
}
|
|
6885
7129
|
function mergeTileflowAnalytics(userAnalytics, runtimeAnalytics) {
|
|
6886
|
-
if (userAnalytics?.enabled === false) {
|
|
6887
|
-
return userAnalytics;
|
|
6888
|
-
}
|
|
6889
7130
|
if (!userAnalytics && !runtimeAnalytics?.mapId) {
|
|
6890
7131
|
return void 0;
|
|
6891
7132
|
}
|
|
@@ -6994,7 +7235,7 @@ function normalizeTileflowStaticImageSize(input) {
|
|
|
6994
7235
|
function inferTileflowAnalyticsFromStyleUrl(styleUrl) {
|
|
6995
7236
|
try {
|
|
6996
7237
|
const url = new URL(styleUrl, getTileflowLocationOrigin());
|
|
6997
|
-
const match = url.pathname.match(
|
|
7238
|
+
const match = url.pathname.match(/^\/maps\/([^/]+)\/style\.json$/);
|
|
6998
7239
|
if (!match?.[1]) {
|
|
6999
7240
|
return void 0;
|
|
7000
7241
|
}
|
|
@@ -7037,6 +7278,7 @@ export {
|
|
|
7037
7278
|
createManifest,
|
|
7038
7279
|
createStyle,
|
|
7039
7280
|
createStyleFromProject,
|
|
7281
|
+
createTileflowSessionController,
|
|
7040
7282
|
createTileflowSessionId,
|
|
7041
7283
|
defaultTileflowManifestUrl,
|
|
7042
7284
|
defaultTileflowStyleBaseUrl,
|
|
@@ -558,6 +558,23 @@ type TileflowAnalytics = {
|
|
|
558
558
|
source?: string;
|
|
559
559
|
styleId?: string;
|
|
560
560
|
};
|
|
561
|
+
type TileflowSessionGrantResponse = {
|
|
562
|
+
billingEnabled?: false;
|
|
563
|
+
disposition?: 'ordinary' | 'unbilled_fail_open';
|
|
564
|
+
expiresAt?: string;
|
|
565
|
+
grant?: string;
|
|
566
|
+
meterMode?: 'disabled' | 'shadow' | 'enforced';
|
|
567
|
+
ok: boolean;
|
|
568
|
+
resourceOrigins?: string[];
|
|
569
|
+
sessionId: string;
|
|
570
|
+
usageMode?: 'session';
|
|
571
|
+
code?: string;
|
|
572
|
+
retryWithNewSession?: boolean;
|
|
573
|
+
};
|
|
574
|
+
type TileflowSessionController = {
|
|
575
|
+
readonly sessionId: string;
|
|
576
|
+
resolveRequestUrl(url: string, analytics: TileflowAnalytics | undefined): Promise<string | undefined>;
|
|
577
|
+
};
|
|
561
578
|
type TileflowMapMarker = {
|
|
562
579
|
id: string;
|
|
563
580
|
coordinates: [number, number];
|
|
@@ -622,6 +639,13 @@ declare function resolveTileflowStyleUrl(mapName: string, styleBaseUrl?: string)
|
|
|
622
639
|
declare function getDefaultTileflowStyleBaseUrl(): string;
|
|
623
640
|
declare function normalizeTileflowUrl(value: string): string;
|
|
624
641
|
declare function createTileflowSessionId(): string;
|
|
642
|
+
declare function createTileflowSessionController(input: {
|
|
643
|
+
fetch?: typeof fetch;
|
|
644
|
+
grantTimeoutMs?: number;
|
|
645
|
+
now?: () => Date;
|
|
646
|
+
sessionIdFactory?: () => string;
|
|
647
|
+
source: string;
|
|
648
|
+
}): TileflowSessionController;
|
|
625
649
|
declare function resolveTileflowAnalyticsRequestUrl(url: string, analytics: TileflowAnalytics | undefined, sessionId: string): string | undefined;
|
|
626
650
|
declare function startTileflowSession(analytics: TileflowAnalytics | undefined, input: {
|
|
627
651
|
mapId?: string;
|
|
@@ -653,4 +677,4 @@ declare function normalizeTileflowStaticImageSize(input: {
|
|
|
653
677
|
};
|
|
654
678
|
declare function inferTileflowAnalyticsFromStyleUrl(styleUrl: string): TileflowAnalytics | undefined;
|
|
655
679
|
|
|
656
|
-
export { type
|
|
680
|
+
export { type TileflowMapMarker as $, type TileflowCaptureScene as A, type TileflowCaptureTarget as B, type TileflowCaptureViewport as C, type TileflowColor as D, type TileflowColorConfig as E, type TileflowColors as F, type TileflowDensity as G, type TileflowFontWeight as H, type TileflowFonts as I, type TileflowHostedNotoSansWeight as J, type TileflowHydroColorConfig as K, type TileflowIconSet as L, type MapLibreSprite as M, type NormalizedTileflowCaptureScene as N, type TileflowIconSetConfig as O, type TileflowLabelColorConfig as P, type TileflowLabelDetail as Q, type ResolvedTileflowTypography as R, type TileflowLabelLanguage as S, type TileflowAnalytics as T, type TileflowLabels as U, type ValidationResult as V, type TileflowLandcoverColorConfig as W, type TileflowLanduseColorConfig as X, type TileflowManifest as Y, type TileflowManifestLoadOptions as Z, type TileflowMapConfig as _, type TileflowSessionController as a, normalizeTileflowCaptureScene as a$, type TileflowMapMode as a0, type TileflowMapModeOptions as a1, type TileflowModuleConfig as a2, type TileflowPoi as a3, type TileflowPoiCategory as a4, type TileflowPoiClassMapping as a5, type TileflowPoiColorConfig as a6, type TileflowPoiColorMode as a7, type TileflowPoiDensity as a8, type TileflowPoiIcons as a9, type TileflowTheme as aA, type TileflowThemeConfig as aB, type TileflowThemeMode as aC, type TileflowThemeModulesConfig as aD, type TileflowThemeName as aE, type TileflowTiles as aF, type TileflowTilesetConfig as aG, type TileflowTypography as aH, type TileflowTypographyDomain as aI, type TileflowTypographyStyle as aJ, type TileflowViewConfig as aK, type ValidationMessage as aL, createManifest as aM, createStyle as aN, createStyleFromProject as aO, createTileflowSessionController as aP, createTileflowSessionId as aQ, defaultTileflowManifestUrl as aR, defaultTileflowStyleBaseUrl as aS, getDefaultColors as aT, getDefaultTileflowStyleBaseUrl as aU, getTileflowAnalyticsApiUrl as aV, inferTileflowAnalyticsFromStyleUrl as aW, isTileflowLocalDevHost as aX, loadTileflowManifest as aY, mergeTileflowAnalytics as aZ, normalizeTileflowCaptureId as a_, type TileflowPoiLabels as aa, type TileflowProjectIconSets as ab, type TileflowProjectThemes as ac, type TileflowRenderer as ad, type TileflowRoadClass as ae, type TileflowRoadColorConfig as af, type TileflowRoadDetail as ag, type TileflowRoadExtras as ah, type TileflowRoadHierarchy as ai, type TileflowRoadLabelDetail as aj, type TileflowRoadOutline as ak, type TileflowRoadWeight as al, type TileflowRoads as am, type TileflowRuntimeManifest as an, type TileflowRuntimeManifestMap as ao, type TileflowRuntimeManifestMapEntry as ap, type TileflowRuntimeStyle as aq, type TileflowRuntimeStyleOptions as ar, type TileflowSessionGrantResponse as as, type TileflowSourceLayers as at, type TileflowStyleLayerOverride as au, type TileflowStyleOptions as av, type TileflowTerrain as aw, type TileflowTerrainConfig as ax, type TileflowTerrainEncoding as ay, type TileflowTerrainMode as az, type TileflowConfig as b, normalizeTileflowStaticImageSize as b0, normalizeTileflowUrl as b1, resolveTileflowAnalyticsRequestUrl as b2, resolveTileflowManifestMap as b3, resolveTileflowMapMode as b4, resolveTileflowRuntimeStyle as b5, resolveTileflowStaticImageUrl as b6, resolveTileflowStyleUrl as b7, shouldLoadTileflowManifest as b8, startTileflowSession as b9, tileflowCaptureApplicationTargetSchema as ba, tileflowCaptureBoundsCameraSchema as bb, tileflowCaptureCameraSchema as bc, tileflowCaptureCenterCameraSchema as bd, tileflowCaptureIdSchema as be, tileflowCaptureMapTargetSchema as bf, tileflowCaptureSceneLimits as bg, tileflowCaptureSceneNameSchema as bh, tileflowCaptureSceneSchema as bi, tileflowCaptureSceneSchemaVersion as bj, tileflowCaptureTargetSchema as bk, tileflowCaptureViewportSchema as bl, tileflowHostedNotoSansWeights as bm, type TileflowProjectConfig as c, type TileflowOsmBasemapOptions as d, type TileflowOsmBasemapConfig as e, type TileflowRoadsModuleOptions as f, type TileflowRoadsModuleConfig as g, type TileflowLabelsModuleOptions as h, type TileflowLabelsModuleConfig as i, type TileflowPoiModuleOptions as j, type TileflowPoiModuleConfig as k, type TileflowStyleOverrideOptions as l, type TileflowStyleOverrideModuleConfig as m, type MapLibreStyle as n, type TileflowAdvancedColorConfig as o, type TileflowBaseColors as p, type TileflowBasemapConfig as q, type TileflowBoundaryColorConfig as r, type TileflowBuildingColorConfig as s, type TileflowBuildingStyleConfig as t, type TileflowBuildings as u, type TileflowCaptureApplicationTarget as v, type TileflowCaptureBoundsCamera as w, type TileflowCaptureCamera as x, type TileflowCaptureCenterCamera as y, type TileflowCaptureMapTarget as z };
|