@honua/app-platform 0.1.4-beta.0 → 0.1.7-beta.0
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/app/index.d.ts.map +1 -1
- package/app/index.js +4 -0
- package/contract/types.d.ts +1 -1
- package/contract/types.d.ts.map +1 -1
- package/contract/types.js +4 -0
- package/core/client.d.ts +6 -0
- package/core/client.d.ts.map +1 -1
- package/core/client.js +11 -9
- package/core/error-classifications.d.ts +17 -0
- package/core/error-classifications.d.ts.map +1 -1
- package/core/error-classifications.js +17 -0
- package/core/error-code-registry.d.ts +18 -1
- package/core/error-code-registry.d.ts.map +1 -1
- package/core/error-code-registry.js +17 -0
- package/core/errors.d.ts +1 -1
- package/core/errors.d.ts.map +1 -1
- package/core/geoparquet-sql.d.ts +1 -1
- package/core/geoparquet-sql.js +2 -2
- package/core/stac.d.ts +2 -1
- package/core/stac.d.ts.map +1 -1
- package/core/stac.js +29 -11
- package/core/types.d.ts +15 -2
- package/core/types.d.ts.map +1 -1
- package/interactions/declarative-contract.d.ts +149 -0
- package/interactions/declarative-contract.d.ts.map +1 -0
- package/interactions/declarative-contract.js +293 -0
- package/interactions/declarative.d.ts +198 -0
- package/interactions/declarative.d.ts.map +1 -0
- package/interactions/declarative.js +470 -0
- package/interactions/feature-state.d.ts +7 -0
- package/interactions/feature-state.d.ts.map +1 -1
- package/interactions/feature-state.js +10 -2
- package/map/maplibre-target.js +1 -1
- package/package.json +2 -2
- package/realtime/sse.d.ts.map +1 -1
- package/realtime/sse.js +7 -1
- package/runtime/style-compose.d.ts.map +1 -1
- package/runtime/style-compose.js +78 -9
package/runtime/style-compose.js
CHANGED
|
@@ -20,7 +20,8 @@ export async function composeStyle(pkg, mapSpecWithSources, options) {
|
|
|
20
20
|
try {
|
|
21
21
|
const withStyleRefs = await applyStyleRefs(mapSpecWithSources, pkg, options.resolveStyleRef);
|
|
22
22
|
const theme = await resolveTheme(pkg, options.resolveTheme);
|
|
23
|
-
|
|
23
|
+
const composed = theme ? applyTheme(withStyleRefs, theme) : withStyleRefs;
|
|
24
|
+
return pruneUndefined(composed);
|
|
24
25
|
}
|
|
25
26
|
catch (cause) {
|
|
26
27
|
if (cause instanceof HonuaMapPackageError)
|
|
@@ -97,26 +98,94 @@ function mergeLayerOverride(layer, override) {
|
|
|
97
98
|
...(override.filter !== undefined ? { filter: override.filter } : {}),
|
|
98
99
|
...(override.minzoom !== undefined ? { minzoom: override.minzoom } : {}),
|
|
99
100
|
...(override.maxzoom !== undefined ? { maxzoom: override.maxzoom } : {}),
|
|
100
|
-
paint
|
|
101
|
-
layout
|
|
102
|
-
metadata
|
|
101
|
+
...optionalRecord("paint", { ...(layer.paint ?? {}), ...(override.paint ?? {}) }),
|
|
102
|
+
...optionalRecord("layout", { ...(layer.layout ?? {}), ...(override.layout ?? {}) }),
|
|
103
|
+
...optionalRecord("metadata", { ...(layer.metadata ?? {}), ...(override.metadata ?? {}) }),
|
|
103
104
|
};
|
|
104
105
|
}
|
|
105
106
|
function cloneLayer(layer) {
|
|
106
107
|
return {
|
|
107
108
|
...layer,
|
|
108
|
-
paint
|
|
109
|
-
layout
|
|
110
|
-
metadata
|
|
109
|
+
...optionalRecord("paint", layer.paint ? { ...layer.paint } : undefined),
|
|
110
|
+
...optionalRecord("layout", layer.layout ? { ...layer.layout } : undefined),
|
|
111
|
+
...optionalRecord("metadata", layer.metadata ? { ...layer.metadata } : undefined),
|
|
111
112
|
};
|
|
112
113
|
}
|
|
113
114
|
function substituteLayerTokens(layer, tokens) {
|
|
114
115
|
return {
|
|
115
116
|
...layer,
|
|
116
|
-
paint
|
|
117
|
-
layout
|
|
117
|
+
...optionalRecord("paint", layer.paint ? substituteTokens(layer.paint, tokens) : undefined),
|
|
118
|
+
...optionalRecord("layout", layer.layout ? substituteTokens(layer.layout, tokens) : undefined),
|
|
118
119
|
};
|
|
119
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Spread helper for optional MapLibre layer properties: contributes the key
|
|
123
|
+
* only when there is something to contribute.
|
|
124
|
+
*
|
|
125
|
+
* `{ layout: undefined }` and "no `layout` key" are indistinguishable to
|
|
126
|
+
* `JSON.stringify`, but not to MapLibre's style validator — it reads the own
|
|
127
|
+
* property and rejects the layer with `layers[n].layout: object expected,
|
|
128
|
+
* undefined found`. A rejected style makes `setStyle(style, { diff: true })`
|
|
129
|
+
* a silent no-op, so the map stops updating with nothing thrown and nothing
|
|
130
|
+
* logged. An empty object is dropped for the same reason in spirit: it is
|
|
131
|
+
* meaningless in the document and only adds diff noise.
|
|
132
|
+
*/
|
|
133
|
+
function optionalRecord(key, value) {
|
|
134
|
+
if (!value || Object.keys(value).length === 0)
|
|
135
|
+
return {};
|
|
136
|
+
return { [key]: value };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Drop present-but-`undefined` properties from the composed document.
|
|
140
|
+
*
|
|
141
|
+
* The composition helpers above never introduce them, but the input
|
|
142
|
+
* `mapSpec` can arrive with them already (hand-built styles, projections
|
|
143
|
+
* from another shape, `JSON`-roundtripped packages that were assembled with
|
|
144
|
+
* explicit `undefined`s). Composition is the last hop before `setStyle`, so
|
|
145
|
+
* it is the right place to guarantee the invariant for every consumer rather
|
|
146
|
+
* than have each one re-implement the pruning.
|
|
147
|
+
*
|
|
148
|
+
* Structure-sharing: a subtree with no `undefined` values is returned by
|
|
149
|
+
* reference, so a clean style allocates nothing. Only plain objects and
|
|
150
|
+
* arrays are traversed; anything else (class instances, typed arrays) is
|
|
151
|
+
* passed through untouched.
|
|
152
|
+
*/
|
|
153
|
+
function pruneUndefined(value) {
|
|
154
|
+
return pruneUnknown(value);
|
|
155
|
+
}
|
|
156
|
+
function pruneUnknown(value) {
|
|
157
|
+
if (Array.isArray(value)) {
|
|
158
|
+
let changed = false;
|
|
159
|
+
const next = value.map((item) => {
|
|
160
|
+
const pruned = pruneUnknown(item);
|
|
161
|
+
if (pruned !== item)
|
|
162
|
+
changed = true;
|
|
163
|
+
return pruned;
|
|
164
|
+
});
|
|
165
|
+
return changed ? next : value;
|
|
166
|
+
}
|
|
167
|
+
if (!isPlainObject(value))
|
|
168
|
+
return value;
|
|
169
|
+
let changed = false;
|
|
170
|
+
const next = {};
|
|
171
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
172
|
+
if (entry === undefined) {
|
|
173
|
+
changed = true;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const pruned = pruneUnknown(entry);
|
|
177
|
+
if (pruned !== entry)
|
|
178
|
+
changed = true;
|
|
179
|
+
next[key] = pruned;
|
|
180
|
+
}
|
|
181
|
+
return changed ? next : value;
|
|
182
|
+
}
|
|
183
|
+
function isPlainObject(value) {
|
|
184
|
+
if (typeof value !== "object" || value === null)
|
|
185
|
+
return false;
|
|
186
|
+
const proto = Object.getPrototypeOf(value);
|
|
187
|
+
return proto === Object.prototype || proto === null;
|
|
188
|
+
}
|
|
120
189
|
function substituteTokens(obj, tokens) {
|
|
121
190
|
const out = {};
|
|
122
191
|
for (const [key, value] of Object.entries(obj)) {
|