@massif-maps/web 6.1.0-rc.1
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/bridge.mjs +197 -0
- package/coi-serviceworker.js +69 -0
- package/index.d.ts +17 -0
- package/index.mjs +41 -0
- package/massif-maps.bundle.mjs +2459 -0
- package/massif-web.data +0 -0
- package/massif-web.mjs +2 -0
- package/massif-web.wasm +0 -0
- package/massif.mjs +390 -0
- package/package.json +36 -0
package/massif.mjs
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The JavaScript binding: a thin wrapper over the facade's C ABI (all/native/api/MassifApiC.h).
|
|
3
|
+
*
|
|
4
|
+
* There is deliberately almost nothing here. The facade is a table, not a class hierarchy - every
|
|
5
|
+
* object is a kind plus an id, every property a path, every method a name - so a binding is string
|
|
6
|
+
* marshalling and nothing else, and a new SDK feature reaches JavaScript without touching this
|
|
7
|
+
* file. See docs/internals/api-facade.md.
|
|
8
|
+
*
|
|
9
|
+
* The typings for what you can pass are generated: bindings/typescript/massif.d.ts.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const RESULT_OK = 0;
|
|
13
|
+
|
|
14
|
+
/** Thrown for any non-zero ABI result, carrying the name the ABI gives it. */
|
|
15
|
+
export class MassifError extends Error {
|
|
16
|
+
constructor(code, name, what) {
|
|
17
|
+
super(`${what} failed: ${name} (${code})`);
|
|
18
|
+
this.code = code;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class Massif {
|
|
23
|
+
#module;
|
|
24
|
+
#ctx;
|
|
25
|
+
#fn;
|
|
26
|
+
// Every function pointer we added to the table, so they can be released.
|
|
27
|
+
#handlers = new Map();
|
|
28
|
+
|
|
29
|
+
constructor(module) {
|
|
30
|
+
this.#module = module;
|
|
31
|
+
const cwrap = module.cwrap;
|
|
32
|
+
this.#fn = {
|
|
33
|
+
resultName: cwrap('mm_result_name', 'string', ['number']),
|
|
34
|
+
contextDefault: cwrap('mm_context_default', 'number', []),
|
|
35
|
+
abiVersion: cwrap('mm_abi_version', 'number', []),
|
|
36
|
+
create: cwrap('mm_create', 'number', ['number', 'string', 'string', 'string', 'number']),
|
|
37
|
+
destroy: cwrap('mm_destroy', 'number', ['number', 'string', 'string']),
|
|
38
|
+
find: cwrap('mm_find', 'number', ['number', 'string', 'string', 'number']),
|
|
39
|
+
setBool: cwrap('mm_set_bool', 'number', ['number', 'number', 'string', 'number']),
|
|
40
|
+
setDouble: cwrap('mm_set_double', 'number', ['number', 'number', 'string', 'number']),
|
|
41
|
+
setString: cwrap('mm_set_string', 'number', ['number', 'number', 'string', 'string']),
|
|
42
|
+
setJson: cwrap('mm_set_json', 'number', ['number', 'number', 'string', 'string']),
|
|
43
|
+
getBool: cwrap('mm_get_bool', 'number', ['number', 'number', 'string', 'number']),
|
|
44
|
+
getDouble: cwrap('mm_get_double', 'number', ['number', 'number', 'string', 'number']),
|
|
45
|
+
getString: cwrap('mm_get_string', 'number', ['number', 'number', 'string', 'string', 'number', 'number', 'number']),
|
|
46
|
+
setObject: cwrap('mm_set_object', 'number', ['number', 'number', 'string', 'number']),
|
|
47
|
+
getObject: cwrap('mm_get_object', 'number', ['number', 'number', 'string']),
|
|
48
|
+
call: cwrap('mm_call', 'number', ['number', 'number', 'string', 'string', 'number']),
|
|
49
|
+
destroyHandle: cwrap('mm_destroy_handle', 'number', ['number', 'number']),
|
|
50
|
+
doublesCount: cwrap('mm_doubles_count', 'number', ['number', 'number', 'number']),
|
|
51
|
+
doublesCopy: cwrap('mm_doubles_copy', 'number', ['number', 'number', 'number', 'number', 'number']),
|
|
52
|
+
on: cwrap('mm_on', 'number', ['number', 'number', 'string', 'number', 'number', 'string', 'number']),
|
|
53
|
+
off: cwrap('mm_off', 'number', ['number', 'number']),
|
|
54
|
+
drain: cwrap('mm_drain', 'number', ['number', 'number']),
|
|
55
|
+
};
|
|
56
|
+
this.#ctx = this.#fn.contextDefault();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
get abiVersion() {
|
|
60
|
+
return this.#fn.abiVersion();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#check(code, what) {
|
|
64
|
+
if (code !== RESULT_OK) {
|
|
65
|
+
throw new MassifError(code, this.#fn.resultName(code), what);
|
|
66
|
+
}
|
|
67
|
+
return code;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Runs `body(pointer)` with `size` bytes of scratch, and always frees them.
|
|
72
|
+
* Zeroed: malloc does not, and an out-parameter the ABI leaves alone then reads as garbage - a
|
|
73
|
+
* void method's result length came back as 4 and parsed as a control character.
|
|
74
|
+
*/
|
|
75
|
+
#withBuffer(size, body) {
|
|
76
|
+
const pointer = this.#module._malloc(size);
|
|
77
|
+
this.#module.HEAPU8.fill(0, pointer, pointer + size);
|
|
78
|
+
try {
|
|
79
|
+
return body(pointer);
|
|
80
|
+
} finally {
|
|
81
|
+
this.#module._free(pointer);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A string out-parameter: the ABI answers the length when the buffer is too small, so ask once
|
|
87
|
+
* with nothing and once with enough.
|
|
88
|
+
*/
|
|
89
|
+
#readString(fill) {
|
|
90
|
+
return this.#withBuffer(4, (lengthPointer) => {
|
|
91
|
+
this.#check(fill(0, 0, lengthPointer), 'read');
|
|
92
|
+
const length = this.#module.getValue(lengthPointer, 'i32');
|
|
93
|
+
if (length <= 0) {
|
|
94
|
+
return '';
|
|
95
|
+
}
|
|
96
|
+
return this.#withBuffer(length + 1, (buffer) => {
|
|
97
|
+
this.#check(fill(buffer, length + 1, lengthPointer), 'read');
|
|
98
|
+
return this.#module.UTF8ToString(buffer);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Creates an object of `kind` under `id`, described by `spec`. Returns its handle. */
|
|
104
|
+
create(kind, id, spec) {
|
|
105
|
+
return this.#withBuffer(4, (out) => {
|
|
106
|
+
this.#check(this.#fn.create(this.#ctx, kind, id, JSON.stringify(spec ?? {}), out), `create ${kind}`);
|
|
107
|
+
return this.#module.getValue(out, 'i32') >>> 0;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
destroy(kind, id) {
|
|
112
|
+
this.#check(this.#fn.destroy(this.#ctx, kind, id), `destroy ${kind}`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** The handle of an object created earlier, or 0. */
|
|
116
|
+
find(kind, id) {
|
|
117
|
+
return this.#withBuffer(4, (out) => {
|
|
118
|
+
const code = this.#fn.find(this.#ctx, kind, id, out);
|
|
119
|
+
return code === RESULT_OK ? this.#module.getValue(out, 'i32') >>> 0 : 0;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
set(handle, path, value) {
|
|
124
|
+
switch (typeof value) {
|
|
125
|
+
case 'boolean':
|
|
126
|
+
return void this.#check(this.#fn.setBool(this.#ctx, handle, path, value ? 1 : 0), `set ${path}`);
|
|
127
|
+
case 'number':
|
|
128
|
+
return void this.#check(this.#fn.setDouble(this.#ctx, handle, path, value), `set ${path}`);
|
|
129
|
+
case 'string':
|
|
130
|
+
return void this.#check(this.#fn.setString(this.#ctx, handle, path, value), `set ${path}`);
|
|
131
|
+
default:
|
|
132
|
+
// An object property is a spec, which the ABI takes as JSON on the object itself.
|
|
133
|
+
return void this.#check(this.#fn.setJson(this.#ctx, handle, JSON.stringify(value), ''), `set ${path}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
getNumber(handle, path) {
|
|
138
|
+
return this.#withBuffer(8, (out) => {
|
|
139
|
+
this.#check(this.#fn.getDouble(this.#ctx, handle, path, out), `get ${path}`);
|
|
140
|
+
return this.#module.getValue(out, 'double');
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
getBool(handle, path) {
|
|
145
|
+
return this.#withBuffer(4, (out) => {
|
|
146
|
+
this.#check(this.#fn.getBool(this.#ctx, handle, path, out), `get ${path}`);
|
|
147
|
+
return this.#module.getValue(out, 'i32') !== 0;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Writes an object PROPERTY - `setObject(mapOptions, 'lightOptions', light)`.
|
|
153
|
+
*
|
|
154
|
+
* Its own call because a handle is neither a value nor a spec: `set` would send it as a number
|
|
155
|
+
* and the ABI refuses that with MM_UNSUPPORTED_TYPE.
|
|
156
|
+
*/
|
|
157
|
+
setObject(handle, path, value) {
|
|
158
|
+
this.#check(this.#fn.setObject(this.#ctx, handle, path, value), `set ${path}`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The handle of an object PROPERTY - `getObject(mapOptions, 'lightOptions')`.
|
|
163
|
+
*
|
|
164
|
+
* Reading a sub-object as a value would flatten it; a handle is what lets its own methods be
|
|
165
|
+
* called. Returns 0 when nothing is set there.
|
|
166
|
+
*/
|
|
167
|
+
getObject(handle, path) {
|
|
168
|
+
return this.#fn.getObject(this.#ctx, handle, path) >>> 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
getString(handle, path, projection = '') {
|
|
172
|
+
return this.#readString((buffer, size, lengthOut) =>
|
|
173
|
+
this.#fn.getString(this.#ctx, handle, path, projection, buffer, size, lengthOut));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Calls a facade method. `args` is positional - `flyTo` takes
|
|
178
|
+
* `[[lon, lat], zoom, rotation, tilt, climbHeight, seconds]` - and the result comes back parsed.
|
|
179
|
+
* A method that produces nothing returns undefined.
|
|
180
|
+
*/
|
|
181
|
+
call(handle, method, args) {
|
|
182
|
+
// The result is a HANDLE to a registered value, not a string - so it is read like any other
|
|
183
|
+
// object and then released, or the context keeps it forever.
|
|
184
|
+
const resultHandle = this.#withBuffer(4, (out) => {
|
|
185
|
+
this.#check(this.#fn.call(this.#ctx, handle, method, JSON.stringify(args ?? []), out), `call ${method}`);
|
|
186
|
+
return this.#module.getValue(out, 'i32') >>> 0;
|
|
187
|
+
});
|
|
188
|
+
if (!resultHandle) {
|
|
189
|
+
return undefined; // the method produced nothing, which is most of them
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
// A bulk numeric result (getElevations, calculateHorizon) is a Float64Array, copied in one go.
|
|
193
|
+
const numbers = this.#readDoubles(resultHandle);
|
|
194
|
+
if (numbers) {
|
|
195
|
+
return numbers;
|
|
196
|
+
}
|
|
197
|
+
const text = this.getString(resultHandle, '');
|
|
198
|
+
if (!text) {
|
|
199
|
+
// A number or a boolean has no text - createLayer's index read as undefined - so it is asked
|
|
200
|
+
// for as one.
|
|
201
|
+
for (const read of [() => this.getNumber(resultHandle, ''), () => this.getBool(resultHandle, '')]) {
|
|
202
|
+
try {
|
|
203
|
+
return read();
|
|
204
|
+
} catch (error) { /* not that kind */ }
|
|
205
|
+
}
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
return JSON.parse(text);
|
|
210
|
+
} catch (error) {
|
|
211
|
+
return text; // not every result is JSON
|
|
212
|
+
}
|
|
213
|
+
} finally {
|
|
214
|
+
this.#fn.destroyHandle(this.#ctx, resultHandle);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#readDoubles(handle) {
|
|
219
|
+
const count = this.#withBuffer(4, (out) =>
|
|
220
|
+
this.#fn.doublesCount(this.#ctx, handle, out) === RESULT_OK ? this.#module.getValue(out, 'i32') : -1);
|
|
221
|
+
if (count < 0) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
return this.#withBuffer(Math.max(8, count * 8), (buffer) => this.#withBuffer(4, (copied) => {
|
|
225
|
+
this.#check(this.#fn.doublesCopy(this.#ctx, handle, buffer, count, copied), 'doubles');
|
|
226
|
+
return new Float64Array(this.#module.HEAPF64.buffer, buffer, count).slice();
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Subscribes to an event. Returns an unsubscribe function.
|
|
232
|
+
*
|
|
233
|
+
* The handler gets the event's PAYLOAD HANDLE, valid for the call: read it with getString,
|
|
234
|
+
* getNumber and the rest (`getString(payload, 'featurePos', 'EPSG:4326')`). A truthy return
|
|
235
|
+
* consumes the event when `options.consume` is set.
|
|
236
|
+
*
|
|
237
|
+
* `options` is mm_on's: delivery 'ui' by default, because an event is produced on a worker thread
|
|
238
|
+
* (a click on the click worker) and a JS handler is only callable on the page's - the demo installs
|
|
239
|
+
* the dispatcher that posts it there. 'origin' is for handlers that are not JavaScript.
|
|
240
|
+
* The handler is added to the wasm table, so it must be removed again or the table only grows.
|
|
241
|
+
*/
|
|
242
|
+
on(handle, event, callback, options = { delivery: 'ui' }) {
|
|
243
|
+
const pointer = this.#module.addFunction((userData, target, eventName, payload) => (callback(payload >>> 0) ? 1 : 0), 'iiiii');
|
|
244
|
+
const subscription = this.#withBuffer(4, (out) => {
|
|
245
|
+
this.#check(this.#fn.on(this.#ctx, handle, event, pointer, 0, JSON.stringify(options ?? {}), out), `on ${event}`);
|
|
246
|
+
return this.#module.getValue(out, 'i32') >>> 0;
|
|
247
|
+
});
|
|
248
|
+
this.#handlers.set(subscription, pointer);
|
|
249
|
+
return () => {
|
|
250
|
+
this.#check(this.#fn.off(this.#ctx, subscription), 'off');
|
|
251
|
+
this.#module.removeFunction(pointer);
|
|
252
|
+
this.#handlers.delete(subscription);
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Starts the map on `canvas` (massif-web only; one map per module) and adopts it under `id`.
|
|
258
|
+
* Returns the handles of the map, its options and its layer list, and the camera.
|
|
259
|
+
*/
|
|
260
|
+
createMap(canvas, id = 'map') {
|
|
261
|
+
if (!this.#module.ccall('massifCreateMap', 'number', ['string'], [canvasSelector(canvas, id)])) {
|
|
262
|
+
throw new Error(`No map on #${canvas.id}: one already exists, or the browser has no WebGL 2`);
|
|
263
|
+
}
|
|
264
|
+
const adopt = (kind, what) => this.#module.ccall('massifAdopt', 'number', ['string', 'string', 'string'], [kind, what, id]);
|
|
265
|
+
const map = adopt('map', 'view');
|
|
266
|
+
this.#module.ccall('massifAttachMapEvents', null, ['number'], [map]);
|
|
267
|
+
return { id, map, options: adopt('options', 'options'), layers: adopt('layers', 'layers'), camera: new MassifCamera(this, id) };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** Emits a vector or vector tile layer's clicks as events on its handle ("vectortile.clicked"). */
|
|
271
|
+
bridgeClicks(layer) {
|
|
272
|
+
if (!this.#module.ccall('massifBridgeLayerClicks', 'number', ['number'], [layer])) {
|
|
273
|
+
throw new Error(`Handle ${layer} is not a vector or vector tile layer`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Delivers queued events for subscriptions that asked for the UI thread. */
|
|
278
|
+
drain() {
|
|
279
|
+
return this.#withBuffer(4, (out) => {
|
|
280
|
+
this.#check(this.#fn.drain(this.#ctx, out), 'drain');
|
|
281
|
+
return this.#module.getValue(out, 'i32');
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* The camera of a map adopted by the host under `kind: "map"`.
|
|
288
|
+
*
|
|
289
|
+
* Sugar, not a second API: every call below is one facade call, spelled the way a web map spells
|
|
290
|
+
* it. `massif.call(handle, ...)` reaches anything this does not cover.
|
|
291
|
+
*/
|
|
292
|
+
export class MassifCamera {
|
|
293
|
+
#massif;
|
|
294
|
+
#handle;
|
|
295
|
+
|
|
296
|
+
constructor(massif, id = 'map') {
|
|
297
|
+
this.#massif = massif;
|
|
298
|
+
this.#handle = massif.find('map', id);
|
|
299
|
+
if (!this.#handle) {
|
|
300
|
+
throw new Error(`No map adopted under the id "${id}"`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Waits for the host to adopt its map, then returns the camera.
|
|
306
|
+
*
|
|
307
|
+
* The module's promise resolves when the RUNTIME is up, which with pthreads is before main() has
|
|
308
|
+
* run - so the map is usually adopted a tick or two later, and reading it straight away is a
|
|
309
|
+
* race. Polling costs nothing and works whenever the host adopts.
|
|
310
|
+
*/
|
|
311
|
+
static async attach(massif, id = 'map', timeoutMs = 10000) {
|
|
312
|
+
const deadline = performance.now() + timeoutMs;
|
|
313
|
+
for (;;) {
|
|
314
|
+
if (massif.find('map', id)) {
|
|
315
|
+
return new MassifCamera(massif, id);
|
|
316
|
+
}
|
|
317
|
+
if (performance.now() > deadline) {
|
|
318
|
+
throw new Error(`No map adopted under the id "${id}" after ${timeoutMs} ms`);
|
|
319
|
+
}
|
|
320
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
get handle() {
|
|
325
|
+
return this.#handle;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
get zoom() {
|
|
329
|
+
return this.#massif.getNumber(this.#handle, 'zoom');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
get rotation() {
|
|
333
|
+
return this.#massif.getNumber(this.#handle, 'rotation');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
get tilt() {
|
|
337
|
+
return this.#massif.getNumber(this.#handle, 'tilt');
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
get focusPos() {
|
|
341
|
+
return JSON.parse(this.#massif.getString(this.#handle, 'focusPos', 'EPSG:4326'));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
moveTo(options) {
|
|
345
|
+
return this.#massif.call(this.#handle, 'moveTo', options);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
flyTo(options) {
|
|
349
|
+
return this.#massif.call(this.#handle, 'flyTo', options);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
fitBounds(options) {
|
|
353
|
+
return this.#massif.call(this.#handle, 'fitBounds', options);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
screenToMap(options) {
|
|
357
|
+
return this.#massif.call(this.#handle, 'screenToMap', options);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
mapToScreen(options) {
|
|
361
|
+
return this.#massif.call(this.#handle, 'mapToScreen', options);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/** The CSS selector emscripten addresses `canvas` by, giving it an id if it has none. */
|
|
366
|
+
export function canvasSelector(canvas, id = 'map') {
|
|
367
|
+
if (!canvas.id) {
|
|
368
|
+
canvas.id = `massif-${id}`;
|
|
369
|
+
}
|
|
370
|
+
return `#${canvas.id}`;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Loads the SDK module. `moduleUrl` defaults to massif-web.mjs beside this file; `options` go to
|
|
375
|
+
* the emscripten factory (print, printErr, locateFile...).
|
|
376
|
+
*/
|
|
377
|
+
// Not a literal in new URL(): a bundler would take that for an asset to bundle.
|
|
378
|
+
const MODULE_FILE = 'massif-web.mjs';
|
|
379
|
+
|
|
380
|
+
export async function loadModule({ moduleUrl = new URL(MODULE_FILE, import.meta.url).href, ...options } = {}) {
|
|
381
|
+
// webpackIgnore: a bundler must not inline the module, its pthread workers import it by URL.
|
|
382
|
+
const { default: factory } = await import(/* webpackIgnore: true */ moduleUrl);
|
|
383
|
+
const base = new URL('.', new URL(moduleUrl, location.href)).href;
|
|
384
|
+
return factory({ locateFile: (path) => base + path, ...options });
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/** Loads the SDK module and returns its low-level binding. */
|
|
388
|
+
export async function loadMassif(options = {}) {
|
|
389
|
+
return new Massif(await loadModule(options));
|
|
390
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@massif-maps/web",
|
|
3
|
+
"version": "6.1.0-rc.1",
|
|
4
|
+
"description": "Massif Maps in the browser: the SDK compiled to WebAssembly, with its typed API",
|
|
5
|
+
"license": "BSD-3-Clause",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "index.mjs",
|
|
8
|
+
"types": "index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./index.d.ts",
|
|
12
|
+
"default": "./index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"./bundle": "./massif-maps.bundle.mjs",
|
|
15
|
+
"./massif.mjs": "./massif.mjs",
|
|
16
|
+
"./coi-serviceworker.js": "./coi-serviceworker.js",
|
|
17
|
+
"./massif-web.mjs": "./massif-web.mjs"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"*.mjs",
|
|
21
|
+
"*.wasm",
|
|
22
|
+
"*.data",
|
|
23
|
+
"*.d.ts",
|
|
24
|
+
"coi-serviceworker.js"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@massif-maps/api": "6.1.0-rc.1"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/massif-maps/MassifMaps.git",
|
|
33
|
+
"directory": "web"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://massif-maps.github.io/MassifMaps/docs/getting-started/web"
|
|
36
|
+
}
|