@dcl/sdk 7.29.1-35862852104.commit-1f44e80 → 7.29.1-35901015152.commit-d1b7b96
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/internal/transports/rendererTransport.js +2 -5
- package/network/binary-message-bus.d.ts +3 -6
- package/network/binary-message-bus.js +5 -9
- package/network/index.d.ts +2 -8
- package/network/index.js +3 -16
- package/network/message-bus-sync.d.ts +3 -16
- package/network/message-bus-sync.js +103 -161
- package/network/state.js +5 -3
- package/observables.d.ts +0 -4
- package/observables.js +1 -6
- package/package.json +6 -6
- package/platform/index.d.ts +0 -16
- package/platform/index.js +1 -42
- package/players/index.d.ts +1 -0
- package/players/index.js +4 -6
- package/src/internal/transports/rendererTransport.ts +1 -4
- package/src/network/binary-message-bus.ts +4 -9
- package/src/network/index.ts +3 -40
- package/src/network/message-bus-sync.ts +112 -176
- package/src/network/state.ts +4 -3
- package/src/observables.ts +0 -10
- package/src/platform/index.ts +0 -47
- package/src/players/index.ts +4 -5
- package/src/testing/runtime.ts +0 -3
- package/testing/runtime.js +1 -4
- package/atom.d.ts +0 -19
- package/atom.js +0 -83
- package/future.d.ts +0 -8
- package/future.js +0 -26
- package/internal/language-events.d.ts +0 -1
- package/internal/language-events.js +0 -8
- package/network/chunking.d.ts +0 -5
- package/network/chunking.js +0 -38
- package/network/events/implementation.d.ts +0 -93
- package/network/events/implementation.js +0 -221
- package/network/events/index.d.ts +0 -42
- package/network/events/index.js +0 -43
- package/network/events/protocol.d.ts +0 -27
- package/network/events/protocol.js +0 -66
- package/network/events/registry.d.ts +0 -8
- package/network/events/registry.js +0 -3
- package/network/server/index.d.ts +0 -14
- package/network/server/index.js +0 -219
- package/network/server/utils.d.ts +0 -18
- package/network/server/utils.js +0 -135
- package/server/env-var.d.ts +0 -15
- package/server/env-var.js +0 -31
- package/server/index.d.ts +0 -2
- package/server/index.js +0 -3
- package/server/storage/constants.d.ts +0 -79
- package/server/storage/constants.js +0 -19
- package/server/storage/index.d.ts +0 -45
- package/server/storage/index.js +0 -51
- package/server/storage/player.d.ts +0 -45
- package/server/storage/player.js +0 -198
- package/server/storage/scene.d.ts +0 -40
- package/server/storage/scene.js +0 -188
- package/server/storage/value-cache.d.ts +0 -1
- package/server/storage/value-cache.js +0 -52
- package/server/storage/write-queue.d.ts +0 -1
- package/server/storage/write-queue.js +0 -71
- package/server/storage-url.d.ts +0 -13
- package/server/storage-url.js +0 -42
- package/server/utils.d.ts +0 -35
- package/server/utils.js +0 -61
- package/src/atom.ts +0 -98
- package/src/future.ts +0 -38
- package/src/internal/language-events.ts +0 -8
- package/src/network/chunking.ts +0 -45
- package/src/network/events/implementation.ts +0 -271
- package/src/network/events/index.ts +0 -48
- package/src/network/events/protocol.ts +0 -94
- package/src/network/events/registry.ts +0 -18
- package/src/network/server/index.ts +0 -301
- package/src/network/server/utils.ts +0 -189
- package/src/server/env-var.ts +0 -36
- package/src/server/index.ts +0 -12
- package/src/server/storage/constants.ts +0 -111
- package/src/server/storage/index.ts +0 -74
- package/src/server/storage/player.ts +0 -289
- package/src/server/storage/scene.ts +0 -270
- package/src/server/storage/value-cache.ts +0 -92
- package/src/server/storage/write-queue.ts +0 -131
- package/src/server/storage-url.ts +0 -49
- package/src/server/utils.ts +0 -76
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { EventSchemas, EventTypes, EventSchemaRegistry } from './registry';
|
|
2
|
-
/**
|
|
3
|
-
* Encode an event into a binary buffer
|
|
4
|
-
* @param eventType - The type of event from the registry
|
|
5
|
-
* @param data - The event data matching the schema
|
|
6
|
-
* @param registry - Optional custom registry (defaults to EventSchemas)
|
|
7
|
-
* @returns Binary buffer containing the encoded event
|
|
8
|
-
*/
|
|
9
|
-
export declare function encodeEvent<T extends EventSchemaRegistry = typeof EventSchemas, K extends keyof T = keyof T>(eventType: K, data: EventTypes<T>[K], registry?: T): Uint8Array;
|
|
10
|
-
/**
|
|
11
|
-
* Decode a binary buffer into an event
|
|
12
|
-
* @param data - Binary buffer containing the encoded event
|
|
13
|
-
* @param registry - Optional custom registry (defaults to EventSchemas)
|
|
14
|
-
* @returns Decoded event with type, payload, and timestamp
|
|
15
|
-
*/
|
|
16
|
-
export declare function decodeEvent<T extends EventSchemaRegistry = typeof EventSchemas>(data: Uint8Array, registry?: T): {
|
|
17
|
-
eventType: keyof T;
|
|
18
|
-
payload: EventTypes<T>[keyof T];
|
|
19
|
-
timestamp: number;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Validate if an event type exists in the registry
|
|
23
|
-
* @param eventType - The event type to check
|
|
24
|
-
* @param registry - Optional custom registry (defaults to EventSchemas)
|
|
25
|
-
* @returns True if the event type exists
|
|
26
|
-
*/
|
|
27
|
-
export declare function isValidEventType<T extends EventSchemaRegistry = typeof EventSchemas>(eventType: string, registry?: T): eventType is Extract<keyof T, string>;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { ReadWriteByteBuffer } from '@dcl/ecs/dist/serialization/ByteBuffer';
|
|
2
|
-
import { Schemas } from '@dcl/ecs';
|
|
3
|
-
import { EventSchemas } from './registry';
|
|
4
|
-
// Event envelope that wraps all events with metadata
|
|
5
|
-
const EventEnvelope = Schemas.Map({
|
|
6
|
-
eventType: Schemas.String,
|
|
7
|
-
timestamp: Schemas.Int64
|
|
8
|
-
});
|
|
9
|
-
/**
|
|
10
|
-
* Encode an event into a binary buffer
|
|
11
|
-
* @param eventType - The type of event from the registry
|
|
12
|
-
* @param data - The event data matching the schema
|
|
13
|
-
* @param registry - Optional custom registry (defaults to EventSchemas)
|
|
14
|
-
* @returns Binary buffer containing the encoded event
|
|
15
|
-
*/
|
|
16
|
-
export function encodeEvent(eventType, data, registry = EventSchemas) {
|
|
17
|
-
const buffer = new ReadWriteByteBuffer();
|
|
18
|
-
// Write envelope with event type and timestamp
|
|
19
|
-
EventEnvelope.serialize({
|
|
20
|
-
eventType: eventType,
|
|
21
|
-
timestamp: Date.now()
|
|
22
|
-
}, buffer);
|
|
23
|
-
// Get the schema for this event type
|
|
24
|
-
const schema = registry[eventType];
|
|
25
|
-
if (!schema) {
|
|
26
|
-
throw new Error(`Unknown event type: ${String(eventType)}`);
|
|
27
|
-
}
|
|
28
|
-
// Write the typed payload
|
|
29
|
-
schema.serialize(data, buffer);
|
|
30
|
-
return buffer.toBinary();
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Decode a binary buffer into an event
|
|
34
|
-
* @param data - Binary buffer containing the encoded event
|
|
35
|
-
* @param registry - Optional custom registry (defaults to EventSchemas)
|
|
36
|
-
* @returns Decoded event with type, payload, and timestamp
|
|
37
|
-
*/
|
|
38
|
-
export function decodeEvent(data, registry = EventSchemas) {
|
|
39
|
-
const buffer = new ReadWriteByteBuffer();
|
|
40
|
-
buffer.writeBuffer(data, false);
|
|
41
|
-
// Read envelope
|
|
42
|
-
const envelope = EventEnvelope.deserialize(buffer);
|
|
43
|
-
const eventType = envelope.eventType;
|
|
44
|
-
// Get the schema for this event type
|
|
45
|
-
const schema = registry[eventType];
|
|
46
|
-
if (!schema) {
|
|
47
|
-
throw new Error(`Unknown event type: ${String(eventType)}`);
|
|
48
|
-
}
|
|
49
|
-
// Read the typed payload
|
|
50
|
-
const payload = schema.deserialize(buffer);
|
|
51
|
-
return {
|
|
52
|
-
eventType,
|
|
53
|
-
payload,
|
|
54
|
-
timestamp: envelope.timestamp
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Validate if an event type exists in the registry
|
|
59
|
-
* @param eventType - The event type to check
|
|
60
|
-
* @param registry - Optional custom registry (defaults to EventSchemas)
|
|
61
|
-
* @returns True if the event type exists
|
|
62
|
-
*/
|
|
63
|
-
export function isValidEventType(eventType, registry = EventSchemas) {
|
|
64
|
-
return eventType in registry;
|
|
65
|
-
}
|
|
66
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbmV0d29yay9ldmVudHMvcHJvdG9jb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0NBQXdDLENBQUE7QUFDNUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUNsQyxPQUFPLEVBQUUsWUFBWSxFQUFtQyxNQUFNLFlBQVksQ0FBQTtBQUUxRSxxREFBcUQ7QUFDckQsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQztJQUNoQyxTQUFTLEVBQUUsT0FBTyxDQUFDLE1BQU07SUFDekIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxLQUFLO0NBQ3pCLENBQUMsQ0FBQTtBQUVGOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQ3pCLFNBQVksRUFDWixJQUFzQixFQUN0QixXQUFjLFlBQWlCO0lBRS9CLE1BQU0sTUFBTSxHQUFHLElBQUksbUJBQW1CLEVBQUUsQ0FBQTtJQUV4QywrQ0FBK0M7SUFDL0MsYUFBYSxDQUFDLFNBQVMsQ0FDckI7UUFDRSxTQUFTLEVBQUUsU0FBbUI7UUFDOUIsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7S0FDdEIsRUFDRCxNQUFNLENBQ1AsQ0FBQTtJQUVELHFDQUFxQztJQUNyQyxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUE7SUFDbEMsSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUE7S0FDNUQ7SUFFRCwwQkFBMEI7SUFDMUIsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFFOUIsT0FBTyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUE7QUFDMUIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FDekIsSUFBZ0IsRUFDaEIsV0FBYyxZQUFpQjtJQU0vQixNQUFNLE1BQU0sR0FBRyxJQUFJLG1CQUFtQixFQUFFLENBQUE7SUFDeEMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFFL0IsZ0JBQWdCO0lBQ2hCLE1BQU0sUUFBUSxHQUFHLGFBQWEsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDbEQsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLFNBQW9CLENBQUE7SUFFL0MscUNBQXFDO0lBQ3JDLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUNsQyxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxJQUFJLEtBQUssQ0FBQyx1QkFBdUIsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtLQUM1RDtJQUVELHlCQUF5QjtJQUN6QixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBRTFDLE9BQU87UUFDTCxTQUFTO1FBQ1QsT0FBTztRQUNQLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUztLQUM5QixDQUFBO0FBQ0gsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUM5QixTQUFpQixFQUNqQixXQUFjLFlBQWlCO0lBRS9CLE9BQU8sU0FBUyxJQUFJLFFBQVEsQ0FBQTtBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUmVhZFdyaXRlQnl0ZUJ1ZmZlciB9IGZyb20gJ0BkY2wvZWNzL2Rpc3Qvc2VyaWFsaXphdGlvbi9CeXRlQnVmZmVyJ1xuaW1wb3J0IHsgU2NoZW1hcyB9IGZyb20gJ0BkY2wvZWNzJ1xuaW1wb3J0IHsgRXZlbnRTY2hlbWFzLCBFdmVudFR5cGVzLCBFdmVudFNjaGVtYVJlZ2lzdHJ5IH0gZnJvbSAnLi9yZWdpc3RyeSdcblxuLy8gRXZlbnQgZW52ZWxvcGUgdGhhdCB3cmFwcyBhbGwgZXZlbnRzIHdpdGggbWV0YWRhdGFcbmNvbnN0IEV2ZW50RW52ZWxvcGUgPSBTY2hlbWFzLk1hcCh7XG4gIGV2ZW50VHlwZTogU2NoZW1hcy5TdHJpbmcsXG4gIHRpbWVzdGFtcDogU2NoZW1hcy5JbnQ2NFxufSlcblxuLyoqXG4gKiBFbmNvZGUgYW4gZXZlbnQgaW50byBhIGJpbmFyeSBidWZmZXJcbiAqIEBwYXJhbSBldmVudFR5cGUgLSBUaGUgdHlwZSBvZiBldmVudCBmcm9tIHRoZSByZWdpc3RyeVxuICogQHBhcmFtIGRhdGEgLSBUaGUgZXZlbnQgZGF0YSBtYXRjaGluZyB0aGUgc2NoZW1hXG4gKiBAcGFyYW0gcmVnaXN0cnkgLSBPcHRpb25hbCBjdXN0b20gcmVnaXN0cnkgKGRlZmF1bHRzIHRvIEV2ZW50U2NoZW1hcylcbiAqIEByZXR1cm5zIEJpbmFyeSBidWZmZXIgY29udGFpbmluZyB0aGUgZW5jb2RlZCBldmVudFxuICovXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlRXZlbnQ8VCBleHRlbmRzIEV2ZW50U2NoZW1hUmVnaXN0cnkgPSB0eXBlb2YgRXZlbnRTY2hlbWFzLCBLIGV4dGVuZHMga2V5b2YgVCA9IGtleW9mIFQ+KFxuICBldmVudFR5cGU6IEssXG4gIGRhdGE6IEV2ZW50VHlwZXM8VD5bS10sXG4gIHJlZ2lzdHJ5OiBUID0gRXZlbnRTY2hlbWFzIGFzIFRcbik6IFVpbnQ4QXJyYXkge1xuICBjb25zdCBidWZmZXIgPSBuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcigpXG5cbiAgLy8gV3JpdGUgZW52ZWxvcGUgd2l0aCBldmVudCB0eXBlIGFuZCB0aW1lc3RhbXBcbiAgRXZlbnRFbnZlbG9wZS5zZXJpYWxpemUoXG4gICAge1xuICAgICAgZXZlbnRUeXBlOiBldmVudFR5cGUgYXMgc3RyaW5nLFxuICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpXG4gICAgfSxcbiAgICBidWZmZXJcbiAgKVxuXG4gIC8vIEdldCB0aGUgc2NoZW1hIGZvciB0aGlzIGV2ZW50IHR5cGVcbiAgY29uc3Qgc2NoZW1hID0gcmVnaXN0cnlbZXZlbnRUeXBlXVxuICBpZiAoIXNjaGVtYSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBldmVudCB0eXBlOiAke1N0cmluZyhldmVudFR5cGUpfWApXG4gIH1cblxuICAvLyBXcml0ZSB0aGUgdHlwZWQgcGF5bG9hZFxuICBzY2hlbWEuc2VyaWFsaXplKGRhdGEsIGJ1ZmZlcilcblxuICByZXR1cm4gYnVmZmVyLnRvQmluYXJ5KClcbn1cblxuLyoqXG4gKiBEZWNvZGUgYSBiaW5hcnkgYnVmZmVyIGludG8gYW4gZXZlbnRcbiAqIEBwYXJhbSBkYXRhIC0gQmluYXJ5IGJ1ZmZlciBjb250YWluaW5nIHRoZSBlbmNvZGVkIGV2ZW50XG4gKiBAcGFyYW0gcmVnaXN0cnkgLSBPcHRpb25hbCBjdXN0b20gcmVnaXN0cnkgKGRlZmF1bHRzIHRvIEV2ZW50U2NoZW1hcylcbiAqIEByZXR1cm5zIERlY29kZWQgZXZlbnQgd2l0aCB0eXBlLCBwYXlsb2FkLCBhbmQgdGltZXN0YW1wXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVFdmVudDxUIGV4dGVuZHMgRXZlbnRTY2hlbWFSZWdpc3RyeSA9IHR5cGVvZiBFdmVudFNjaGVtYXM+KFxuICBkYXRhOiBVaW50OEFycmF5LFxuICByZWdpc3RyeTogVCA9IEV2ZW50U2NoZW1hcyBhcyBUXG4pOiB7XG4gIGV2ZW50VHlwZToga2V5b2YgVFxuICBwYXlsb2FkOiBFdmVudFR5cGVzPFQ+W2tleW9mIFRdXG4gIHRpbWVzdGFtcDogbnVtYmVyXG59IHtcbiAgY29uc3QgYnVmZmVyID0gbmV3IFJlYWRXcml0ZUJ5dGVCdWZmZXIoKVxuICBidWZmZXIud3JpdGVCdWZmZXIoZGF0YSwgZmFsc2UpXG5cbiAgLy8gUmVhZCBlbnZlbG9wZVxuICBjb25zdCBlbnZlbG9wZSA9IEV2ZW50RW52ZWxvcGUuZGVzZXJpYWxpemUoYnVmZmVyKVxuICBjb25zdCBldmVudFR5cGUgPSBlbnZlbG9wZS5ldmVudFR5cGUgYXMga2V5b2YgVFxuXG4gIC8vIEdldCB0aGUgc2NoZW1hIGZvciB0aGlzIGV2ZW50IHR5cGVcbiAgY29uc3Qgc2NoZW1hID0gcmVnaXN0cnlbZXZlbnRUeXBlXVxuICBpZiAoIXNjaGVtYSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBldmVudCB0eXBlOiAke1N0cmluZyhldmVudFR5cGUpfWApXG4gIH1cblxuICAvLyBSZWFkIHRoZSB0eXBlZCBwYXlsb2FkXG4gIGNvbnN0IHBheWxvYWQgPSBzY2hlbWEuZGVzZXJpYWxpemUoYnVmZmVyKVxuXG4gIHJldHVybiB7XG4gICAgZXZlbnRUeXBlLFxuICAgIHBheWxvYWQsXG4gICAgdGltZXN0YW1wOiBlbnZlbG9wZS50aW1lc3RhbXBcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlIGlmIGFuIGV2ZW50IHR5cGUgZXhpc3RzIGluIHRoZSByZWdpc3RyeVxuICogQHBhcmFtIGV2ZW50VHlwZSAtIFRoZSBldmVudCB0eXBlIHRvIGNoZWNrXG4gKiBAcGFyYW0gcmVnaXN0cnkgLSBPcHRpb25hbCBjdXN0b20gcmVnaXN0cnkgKGRlZmF1bHRzIHRvIEV2ZW50U2NoZW1hcylcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGV2ZW50IHR5cGUgZXhpc3RzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkRXZlbnRUeXBlPFQgZXh0ZW5kcyBFdmVudFNjaGVtYVJlZ2lzdHJ5ID0gdHlwZW9mIEV2ZW50U2NoZW1hcz4oXG4gIGV2ZW50VHlwZTogc3RyaW5nLFxuICByZWdpc3RyeTogVCA9IEV2ZW50U2NoZW1hcyBhcyBUXG4pOiBldmVudFR5cGUgaXMgRXh0cmFjdDxrZXlvZiBULCBzdHJpbmc+IHtcbiAgcmV0dXJuIGV2ZW50VHlwZSBpbiByZWdpc3RyeVxufVxuIl19
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ISchema } from '@dcl/ecs';
|
|
2
|
-
export type EventSchemaRegistry = Record<string, ISchema>;
|
|
3
|
-
export type EventTypes<T extends EventSchemaRegistry = EventSchemaRegistry> = {
|
|
4
|
-
[K in keyof T]: T[K] extends ISchema<infer U> ? U : never;
|
|
5
|
-
};
|
|
6
|
-
export type RegisteredEvents = EventSchemaRegistry;
|
|
7
|
-
export declare const EventSchemas: EventSchemaRegistry;
|
|
8
|
-
export type ValidateEventRegistry<T extends EventSchemaRegistry> = T;
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// Default empty registry
|
|
2
|
-
export const EventSchemas = {};
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbmV0d29yay9ldmVudHMvcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBYUEseUJBQXlCO0FBQ3pCLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxFQUFzQixDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSVNjaGVtYSB9IGZyb20gJ0BkY2wvZWNzJ1xuXG4vLyBCYXNlIHR5cGUgZm9yIGV2ZW50IHNjaGVtYSByZWdpc3RyeVxuZXhwb3J0IHR5cGUgRXZlbnRTY2hlbWFSZWdpc3RyeSA9IFJlY29yZDxzdHJpbmcsIElTY2hlbWE+XG5cbi8vIFR5cGUgZXh0cmFjdGlvbiBmcm9tIHNjaGVtYXNcbmV4cG9ydCB0eXBlIEV2ZW50VHlwZXM8VCBleHRlbmRzIEV2ZW50U2NoZW1hUmVnaXN0cnkgPSBFdmVudFNjaGVtYVJlZ2lzdHJ5PiA9IHtcbiAgW0sgaW4ga2V5b2YgVF06IFRbS10gZXh0ZW5kcyBJU2NoZW1hPGluZmVyIFU+ID8gVSA6IG5ldmVyXG59XG5cbi8vIEdsb2JhbCBpbnRlcmZhY2UgdGhhdCB1c2VycyBjYW4gYXVnbWVudCB3aXRoIHRoZWlyIG93biBldmVudHNcbmV4cG9ydCB0eXBlIFJlZ2lzdGVyZWRFdmVudHMgPSBFdmVudFNjaGVtYVJlZ2lzdHJ5XG5cbi8vIERlZmF1bHQgZW1wdHkgcmVnaXN0cnlcbmV4cG9ydCBjb25zdCBFdmVudFNjaGVtYXMgPSB7fSBhcyBSZWdpc3RlcmVkRXZlbnRzXG5cbi8vIEhlbHBlciB0byBlbnN1cmUgdXNlciBldmVudHMgY29uZm9ybSB0byB0aGUgcmVnaXN0cnkgdHlwZVxuZXhwb3J0IHR5cGUgVmFsaWRhdGVFdmVudFJlZ2lzdHJ5PFQgZXh0ZW5kcyBFdmVudFNjaGVtYVJlZ2lzdHJ5PiA9IFRcbiJdfQ==
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { IEngine, Entity } from '@dcl/ecs';
|
|
2
|
-
import * as utils from './utils';
|
|
3
|
-
import { type BinaryMessageBus } from '../binary-message-bus';
|
|
4
|
-
export declare const LIVEKIT_MAX_SIZE = 12;
|
|
5
|
-
export interface ServerValidationConfig {
|
|
6
|
-
engine: IEngine;
|
|
7
|
-
binaryMessageBus: ReturnType<typeof BinaryMessageBus>;
|
|
8
|
-
}
|
|
9
|
-
export declare function createServerValidator(config: ServerValidationConfig): {
|
|
10
|
-
findExistingNetworkEntity: (message: utils.NetworkMessage) => Entity | null;
|
|
11
|
-
processClientMessages: (value: Uint8Array, sender: string, forceCorrections?: boolean) => Uint8Array;
|
|
12
|
-
processServerMessages: (value: Uint8Array, sender: string) => Uint8Array;
|
|
13
|
-
convertRegularToNetworkMessage: (regularMessage: Uint8Array) => Uint8Array[];
|
|
14
|
-
};
|
package/network/server/index.js
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { CrdtMessageType, ProcessMessageResultType, PutNetworkComponentOperation } from '@dcl/ecs';
|
|
2
|
-
import * as components from '@dcl/ecs/dist/components';
|
|
3
|
-
import { ReadWriteByteBuffer } from '@dcl/ecs/dist/serialization/ByteBuffer';
|
|
4
|
-
import { CommsMessage } from '../binary-message-bus';
|
|
5
|
-
import { chunkCrdtMessages } from '../chunking';
|
|
6
|
-
import * as utils from './utils';
|
|
7
|
-
import { AUTH_SERVER_PEER_ID, DEBUG_NETWORK_MESSAGES } from '../message-bus-sync';
|
|
8
|
-
export const LIVEKIT_MAX_SIZE = 12;
|
|
9
|
-
export function createServerValidator(config) {
|
|
10
|
-
const { engine, binaryMessageBus } = config;
|
|
11
|
-
// Initialize components for network operations and transform fixing
|
|
12
|
-
const NetworkEntity = components.NetworkEntity(engine);
|
|
13
|
-
const CreatedBy = components.CreatedBy(engine);
|
|
14
|
-
const NetworkParent = components.NetworkParent(engine);
|
|
15
|
-
// Type guard to check if component supports corrections (both LWW and GrowOnlySet)
|
|
16
|
-
function supportsCorrections(component) {
|
|
17
|
-
return ((component.componentType === 0 /* ComponentType.LastWriteWinElementSet */ ||
|
|
18
|
-
component.componentType === 1 /* ComponentType.GrowOnlyValueSet */) &&
|
|
19
|
-
'getCrdtState' in component);
|
|
20
|
-
}
|
|
21
|
-
function findExistingNetworkEntity(message) {
|
|
22
|
-
// Look for existing network entity mapping (don't create new ones)
|
|
23
|
-
for (const [entityId, networkData] of engine.getEntitiesWith(NetworkEntity)) {
|
|
24
|
-
if (networkData.networkId === message.networkId && networkData.entityId === message.entityId) {
|
|
25
|
-
return entityId;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
// Return null if not found
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
function findOrCreateNetworkEntity(message, sender, isServer) {
|
|
32
|
-
// Look for existing network entity mapping first
|
|
33
|
-
const existingEntity = findExistingNetworkEntity(message);
|
|
34
|
-
if (existingEntity) {
|
|
35
|
-
return existingEntity;
|
|
36
|
-
}
|
|
37
|
-
// Create new entity and network mapping
|
|
38
|
-
const newEntityId = engine.addEntity();
|
|
39
|
-
NetworkEntity.createOrReplace(newEntityId, {
|
|
40
|
-
networkId: message.networkId,
|
|
41
|
-
entityId: message.entityId
|
|
42
|
-
});
|
|
43
|
-
if (isServer) {
|
|
44
|
-
CreatedBy.createOrReplace(newEntityId, { address: sender });
|
|
45
|
-
}
|
|
46
|
-
DEBUG_NETWORK_MESSAGES() &&
|
|
47
|
-
console.log(`[DEBUG] Created new entity ${newEntityId} for network ${message.networkId}:${message.entityId}`);
|
|
48
|
-
return newEntityId;
|
|
49
|
-
}
|
|
50
|
-
function convertNetworkToRegularMessage(networkMessage, localEntityId, forceCorrections = false) {
|
|
51
|
-
const buffer = new ReadWriteByteBuffer();
|
|
52
|
-
try {
|
|
53
|
-
// Use the well-tested networkMessageToLocal utility with transform fixing for Unity
|
|
54
|
-
const message = utils.networkMessageToLocal(networkMessage, localEntityId, buffer, NetworkParent, forceCorrections);
|
|
55
|
-
return { ...message, messageBuffer: buffer.toBinary() };
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
DEBUG_NETWORK_MESSAGES() && console.error('Error converting network message:', error);
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function validateMessagePermissions(message, sender, _localEntityId) {
|
|
63
|
-
// Basic checks
|
|
64
|
-
if (!sender || sender === AUTH_SERVER_PEER_ID) {
|
|
65
|
-
return false; // Server shouldn't send messages to itself
|
|
66
|
-
}
|
|
67
|
-
if (message.type === CrdtMessageType.DELETE_ENTITY) {
|
|
68
|
-
// TODO: how to handle this case ?
|
|
69
|
-
}
|
|
70
|
-
if (message.type === CrdtMessageType.PUT_COMPONENT || message.type === CrdtMessageType.DELETE_COMPONENT) {
|
|
71
|
-
const component = engine.getComponent(message.componentId);
|
|
72
|
-
const buf = 'data' in message ? new ReadWriteByteBuffer(message.data) : null;
|
|
73
|
-
const value = buf ? component.schema.deserialize(buf) : null;
|
|
74
|
-
const dryRunCRDT = component.__dry_run_updateFromCrdt(message);
|
|
75
|
-
const validCRDT = [
|
|
76
|
-
ProcessMessageResultType.StateUpdatedData,
|
|
77
|
-
ProcessMessageResultType.StateUpdatedTimestamp,
|
|
78
|
-
ProcessMessageResultType.EntityDeleted
|
|
79
|
-
].includes(dryRunCRDT);
|
|
80
|
-
const createdBy = CreatedBy.getOrNull(message.entityId);
|
|
81
|
-
const validMessage = validCRDT &&
|
|
82
|
-
component.__run_validateBeforeChange(message.entityId, value, sender, createdBy?.address ?? AUTH_SERVER_PEER_ID);
|
|
83
|
-
return !!validMessage;
|
|
84
|
-
}
|
|
85
|
-
// For now, basic validation - in the future this will check component sync permissions
|
|
86
|
-
// TODO: Check if sender owns the entity
|
|
87
|
-
// TODO: Check component sync mode ('all' | 'owner' | 'server')
|
|
88
|
-
// TODO: Run component custom validation
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
function broadcastBatchedMessages(messages, excludeSender) {
|
|
92
|
-
if (messages.length === 0)
|
|
93
|
-
return;
|
|
94
|
-
// Build the complete buffer with all messages
|
|
95
|
-
const networkBuffer = new ReadWriteByteBuffer();
|
|
96
|
-
for (const message of messages) {
|
|
97
|
-
// Skip oversized messages upfront
|
|
98
|
-
if (message.messageBuffer.byteLength / 1024 > LIVEKIT_MAX_SIZE) {
|
|
99
|
-
console.error(`Message too large (${message.messageBuffer.byteLength} bytes), skipping message from ${excludeSender}`);
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
networkBuffer.writeBuffer(message.messageBuffer, false);
|
|
103
|
-
}
|
|
104
|
-
// Use the chunking function to split into proper chunks
|
|
105
|
-
const chunks = chunkCrdtMessages(networkBuffer.toBinary(), LIVEKIT_MAX_SIZE);
|
|
106
|
-
for (const chunk of chunks) {
|
|
107
|
-
binaryMessageBus.emit(CommsMessage.CRDT, chunk);
|
|
108
|
-
}
|
|
109
|
-
DEBUG_NETWORK_MESSAGES() &&
|
|
110
|
-
console.log(`Total: ${messages.length} messages in ${chunks.length} chunks from ${excludeSender}`);
|
|
111
|
-
}
|
|
112
|
-
function sendCorrectionToSender(networkMessage, sender, localEntityId) {
|
|
113
|
-
try {
|
|
114
|
-
// Only handle component messages (PUT/DELETE), not entity deletion
|
|
115
|
-
if (networkMessage.type === CrdtMessageType.DELETE_ENTITY_NETWORK) {
|
|
116
|
-
DEBUG_NETWORK_MESSAGES() && console.log('[AUTHORITATIVE] Cannot send authoritative message for entity deletion');
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
// Safe to access componentId and timestamp now
|
|
120
|
-
const component = engine.getComponent(networkMessage.componentId);
|
|
121
|
-
// Only proceed if component supports authoritative messages (LWW or GrowOnlySet)
|
|
122
|
-
if (!supportsCorrections(component)) {
|
|
123
|
-
DEBUG_NETWORK_MESSAGES() && console.log('[AUTHORITATIVE] Component does not support authoritative messages');
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const serverCRDTState = component.getCrdtState(localEntityId);
|
|
127
|
-
if (serverCRDTState) {
|
|
128
|
-
// Create authoritative message using PUT_COMPONENT_NETWORK
|
|
129
|
-
// Each client will convert this to AUTHORITATIVE_PUT_COMPONENT with proper entity mapping
|
|
130
|
-
const correctionBuffer = new ReadWriteByteBuffer();
|
|
131
|
-
PutNetworkComponentOperation.write(networkMessage.entityId, // Use original network entity ID
|
|
132
|
-
serverCRDTState.timestamp, networkMessage.componentId, networkMessage.networkId, serverCRDTState.data, correctionBuffer);
|
|
133
|
-
// Send authoritative message directly to the sender
|
|
134
|
-
binaryMessageBus.emit(CommsMessage.CRDT_AUTHORITATIVE, correctionBuffer.toBinary(), [sender]);
|
|
135
|
-
DEBUG_NETWORK_MESSAGES() &&
|
|
136
|
-
console.log(`[AUTHORITATIVE] Sent authoritative message to ${sender} for entity ${localEntityId} component ${networkMessage.componentId} with timestamp ${networkMessage.timestamp}`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
DEBUG_NETWORK_MESSAGES() && console.error('Error sending correction:', error);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return {
|
|
144
|
-
findExistingNetworkEntity,
|
|
145
|
-
// transform Network messages to CRDT Common Messages.
|
|
146
|
-
processClientMessages: function processClientMessages(value, sender, forceCorrections = false) {
|
|
147
|
-
// console.log(`[CLIENT] Processing message from ${sender}, ${value.length} bytes`)
|
|
148
|
-
// Collect all regular messages in a single buffer for batched application
|
|
149
|
-
const combinedBuffer = new ReadWriteByteBuffer();
|
|
150
|
-
// Clients process network messages from server and convert them to regular messages
|
|
151
|
-
for (const message of utils.readMessages(value)) {
|
|
152
|
-
// Only process network messages in client message handler
|
|
153
|
-
if (utils.isNetworkMessage(message)) {
|
|
154
|
-
const networkMessage = message;
|
|
155
|
-
// Find or create network entity mapping
|
|
156
|
-
const localEntityId = findOrCreateNetworkEntity(networkMessage, sender, false);
|
|
157
|
-
// Convert network message to regular message or correction message
|
|
158
|
-
const regularMessage = convertNetworkToRegularMessage(networkMessage, localEntityId, forceCorrections);
|
|
159
|
-
if (regularMessage?.messageBuffer.byteLength) {
|
|
160
|
-
combinedBuffer.writeBuffer(regularMessage.messageBuffer, false);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return combinedBuffer.toBinary();
|
|
165
|
-
},
|
|
166
|
-
// Sever Code: process message, handle permissions, and broadcast if needed.
|
|
167
|
-
processServerMessages: function processServerMessages(value, sender) {
|
|
168
|
-
// console.log(`[SERVER] Processing message from ${sender}, ${value.length} bytes`)
|
|
169
|
-
// Collect all valid messages for batched broadcasting
|
|
170
|
-
const messagesToBroadcast = [];
|
|
171
|
-
const regularMessagesBuffer = new ReadWriteByteBuffer();
|
|
172
|
-
for (const message of utils.readMessages(value)) {
|
|
173
|
-
try {
|
|
174
|
-
// Only process network messages in server message handler
|
|
175
|
-
if (utils.isNetworkMessage(message)) {
|
|
176
|
-
const networkMessage = message;
|
|
177
|
-
// 1. Find or create network entity mapping
|
|
178
|
-
const localEntityId = findOrCreateNetworkEntity(networkMessage, sender, true);
|
|
179
|
-
// 2. Convert network message to regular message and collect for local application
|
|
180
|
-
const regularMessage = convertNetworkToRegularMessage(networkMessage, localEntityId);
|
|
181
|
-
// 3. Basic permission validation
|
|
182
|
-
if (!validateMessagePermissions(regularMessage, sender, localEntityId)) {
|
|
183
|
-
// Send correction back to sender with server's authoritative state
|
|
184
|
-
sendCorrectionToSender(networkMessage, sender, localEntityId);
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
// 4. Collect valid message for batched broadcasting
|
|
188
|
-
messagesToBroadcast.push(networkMessage);
|
|
189
|
-
if (regularMessage?.messageBuffer.byteLength) {
|
|
190
|
-
regularMessagesBuffer.writeBuffer(regularMessage.messageBuffer, false);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
DEBUG_NETWORK_MESSAGES() && console.error('Error processing server message:', error);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
// Batch broadcast all valid messages together
|
|
199
|
-
broadcastBatchedMessages(messagesToBroadcast, sender);
|
|
200
|
-
return regularMessagesBuffer.toBinary();
|
|
201
|
-
},
|
|
202
|
-
// engine changes that needs to be broadcasted.
|
|
203
|
-
convertRegularToNetworkMessage: function convertRegularToNetworkMessage(regularMessage) {
|
|
204
|
-
const groupedBuffer = new ReadWriteByteBuffer();
|
|
205
|
-
// First pass: Convert all regular messages to network format and group them into one big buffer
|
|
206
|
-
for (const message of utils.readMessages(regularMessage)) {
|
|
207
|
-
// Only convert regular messages that have network data
|
|
208
|
-
const networkData = NetworkEntity.getOrNull(message.entityId);
|
|
209
|
-
if (networkData && !utils.isNetworkMessage(message)) {
|
|
210
|
-
utils.localMessageToNetwork(message, networkData, groupedBuffer);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
// Second pass: Use the new chunking function that respects message boundaries
|
|
214
|
-
const totalData = groupedBuffer.toBinary();
|
|
215
|
-
return chunkCrdtMessages(totalData, LIVEKIT_MAX_SIZE);
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbmV0d29yay9zZXJ2ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLGVBQWUsRUFFZix3QkFBd0IsRUFFeEIsNEJBQTRCLEVBQzdCLE1BQU0sVUFBVSxDQUFBO0FBQ2pCLE9BQU8sS0FBSyxVQUFVLE1BQU0sMEJBQTBCLENBQUE7QUFDdEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0NBQXdDLENBQUE7QUFDNUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFBO0FBQ3BELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUMvQyxPQUFPLEtBQUssS0FBSyxNQUFNLFNBQVMsQ0FBQTtBQUNoQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQVNqRixNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLENBQUE7QUFPbEMsTUFBTSxVQUFVLHFCQUFxQixDQUFDLE1BQThCO0lBQ2xFLE1BQU0sRUFBRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsR0FBRyxNQUFNLENBQUE7SUFFM0Msb0VBQW9FO0lBQ3BFLE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDdEQsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUM5QyxNQUFNLGFBQWEsR0FBRyxVQUFVLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBRXRELG1GQUFtRjtJQUNuRixTQUFTLG1CQUFtQixDQUMxQixTQUFpQztRQUVqQyxPQUFPLENBQ0wsQ0FBQyxTQUFTLENBQUMsYUFBYSxpREFBeUM7WUFDL0QsU0FBUyxDQUFDLGFBQWEsMkNBQW1DLENBQUM7WUFDN0QsY0FBYyxJQUFJLFNBQVMsQ0FD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QkFBcUIsQ0FBQyxPQUFPLEVBQUUsV0FBVyxFQUFFLGFBQWEsQ0FBQyxDQUFBO2lCQUNqRTthQUNGO1lBRUQsOEVBQThFO1lBQzlFLE1BQU0sU0FBUyxHQUFHLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtZQUMxQyxPQUFPLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFBO1FBQ3ZELENBQUM7S0FDRixDQUFBO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIElFbmdpbmUsXG4gIEVudGl0eSxcbiAgQ3JkdE1lc3NhZ2VUeXBlLFxuICBDcmR0TWVzc2FnZUJvZHksXG4gIFByb2Nlc3NNZXNzYWdlUmVzdWx0VHlwZSxcbiAgQ29tcG9uZW50VHlwZSxcbiAgUHV0TmV0d29ya0NvbXBvbmVudE9wZXJhdGlvblxufSBmcm9tICdAZGNsL2VjcydcbmltcG9ydCAqIGFzIGNvbXBvbmVudHMgZnJvbSAnQGRjbC9lY3MvZGlzdC9jb21wb25lbnRzJ1xuaW1wb3J0IHsgUmVhZFdyaXRlQnl0ZUJ1ZmZlciB9IGZyb20gJ0BkY2wvZWNzL2Rpc3Qvc2VyaWFsaXphdGlvbi9CeXRlQnVmZmVyJ1xuaW1wb3J0IHsgQ29tbXNNZXNzYWdlIH0gZnJvbSAnLi4vYmluYXJ5LW1lc3NhZ2UtYnVzJ1xuaW1wb3J0IHsgY2h1bmtDcmR0TWVzc2FnZXMgfSBmcm9tICcuLi9jaHVua2luZydcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gJy4vdXRpbHMnXG5pbXBvcnQgeyBBVVRIX1NFUlZFUl9QRUVSX0lELCBERUJVR19ORVRXT1JLX01FU1NBR0VTIH0gZnJvbSAnLi4vbWVzc2FnZS1idXMtc3luYydcbmltcG9ydCB7IHR5cGUgQmluYXJ5TWVzc2FnZUJ1cyB9IGZyb20gJy4uL2JpbmFyeS1tZXNzYWdlLWJ1cydcbmltcG9ydCB7XG4gIExhc3RXcml0ZVdpbkVsZW1lbnRTZXRDb21wb25lbnREZWZpbml0aW9uLFxuICBHcm93T25seVZhbHVlU2V0Q29tcG9uZW50RGVmaW5pdGlvbixcbiAgQ29tcG9uZW50RGVmaW5pdGlvbixcbiAgSW50ZXJuYWxCYXNlQ29tcG9uZW50XG59IGZyb20gJ0BkY2wvZWNzL2Rpc3QvZW5naW5lL2NvbXBvbmVudCdcblxuZXhwb3J0IGNvbnN0IExJVkVLSVRfTUFYX1NJWkUgPSAxMlxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZlclZhbGlkYXRpb25Db25maWcge1xuICBlbmdpbmU6IElFbmdpbmVcbiAgYmluYXJ5TWVzc2FnZUJ1czogUmV0dXJuVHlwZTx0eXBlb2YgQmluYXJ5TWVzc2FnZUJ1cz5cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNlcnZlclZhbGlkYXRvcihjb25maWc6IFNlcnZlclZhbGlkYXRpb25Db25maWcpIHtcbiAgY29uc3QgeyBlbmdpbmUsIGJpbmFyeU1lc3NhZ2VCdXMgfSA9IGNvbmZpZ1xuXG4gIC8vIEluaXRpYWxpemUgY29tcG9uZW50cyBmb3IgbmV0d29yayBvcGVyYXRpb25zIGFuZCB0cmFuc2Zvcm0gZml4aW5nXG4gIGNvbnN0IE5ldHdvcmtFbnRpdHkgPSBjb21wb25lbnRzLk5ldHdvcmtFbnRpdHkoZW5naW5lKVxuICBjb25zdCBDcmVhdGVkQnkgPSBjb21wb25lbnRzLkNyZWF0ZWRCeShlbmdpbmUpXG4gIGNvbnN0IE5ldHdvcmtQYXJlbnQgPSBjb21wb25lbnRzLk5ldHdvcmtQYXJlbnQoZW5naW5lKVxuXG4gIC8vIFR5cGUgZ3VhcmQgdG8gY2hlY2sgaWYgY29tcG9uZW50IHN1cHBvcnRzIGNvcnJlY3Rpb25zIChib3RoIExXVyBhbmQgR3Jvd09ubHlTZXQpXG4gIGZ1bmN0aW9uIHN1cHBvcnRzQ29ycmVjdGlvbnM8VD4oXG4gICAgY29tcG9uZW50OiBDb21wb25lbnREZWZpbml0aW9uPFQ+XG4gICk6IGNvbXBvbmVudCBpcyBMYXN0V3JpdGVXaW5FbGVtZW50U2V0Q29tcG9uZW50RGVmaW5pdGlvbjxUPiB8IEdyb3dPbmx5VmFsdWVTZXRDb21wb25lbnREZWZpbml0aW9uPFQ+IHtcbiAgICByZXR1cm4gKFxuICAgICAgKGNvbXBvbmVudC5jb21wb25lbnRUeXBlID09PSBDb21wb25lbnRUeXBlLkxhc3RXcml0ZVdpbkVsZW1lbnRTZXQgfHxcbiAgICAgICAgY29tcG9uZW50LmNvbXBvbmVudFR5cGUgPT09IENvbXBvbmVudFR5cGUuR3Jvd09ubHlWYWx1ZVNldCkgJiZcbiAgICAgICdnZXRDcmR0U3RhdGUnIGluIGNvbXBvbmVudFxuICAgIClcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmRFeGlzdGluZ05ldHdvcmtFbnRpdHkobWVzc2FnZTogdXRpbHMuTmV0d29ya01lc3NhZ2UpOiBFbnRpdHkgfCBudWxsIHtcbiAgICAvLyBMb29rIGZvciBleGlzdGluZyBuZXR3b3JrIGVudGl0eSBtYXBwaW5nIChkb24ndCBjcmVhdGUgbmV3IG9uZXMpXG4gICAgZm9yIChjb25zdCBbZW50aXR5SWQsIG5ldHdvcmtEYXRhXSBvZiBlbmdpbmUuZ2V0RW50aXRpZXNXaXRoKE5ldHdvcmtFbnRpdHkpKSB7XG4gICAgICBpZiAobmV0d29ya0RhdGEubmV0d29ya0lkID09PSBtZXNzYWdlLm5ldHdvcmtJZCAmJiBuZXR3b3JrRGF0YS5lbnRpdHlJZCA9PT0gbWVzc2FnZS5lbnRpdHlJZCkge1xuICAgICAgICByZXR1cm4gZW50aXR5SWRcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gUmV0dXJuIG51bGwgaWYgbm90IGZvdW5kXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmRPckNyZWF0ZU5ldHdvcmtFbnRpdHkobWVzc2FnZTogdXRpbHMuTmV0d29ya01lc3NhZ2UsIHNlbmRlcjogc3RyaW5nLCBpc1NlcnZlcjogYm9vbGVhbik6IEVudGl0eSB7XG4gICAgLy8gTG9vayBmb3IgZXhpc3RpbmcgbmV0d29yayBlbnRpdHkgbWFwcGluZyBmaXJzdFxuICAgIGNvbnN0IGV4aXN0aW5nRW50aXR5ID0gZmluZEV4aXN0aW5nTmV0d29ya0VudGl0eShtZXNzYWdlKVxuXG4gICAgaWYgKGV4aXN0aW5nRW50aXR5KSB7XG4gICAgICByZXR1cm4gZXhpc3RpbmdFbnRpdHlcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgbmV3IGVudGl0eSBhbmQgbmV0d29yayBtYXBwaW5nXG4gICAgY29uc3QgbmV3RW50aXR5SWQgPSBlbmdpbmUuYWRkRW50aXR5KClcbiAgICBOZXR3b3JrRW50aXR5LmNyZWF0ZU9yUmVwbGFjZShuZXdFbnRpdHlJZCwge1xuICAgICAgbmV0d29ya0lkOiBtZXNzYWdlLm5ldHdvcmtJZCxcbiAgICAgIGVudGl0eUlkOiBtZXNzYWdlLmVudGl0eUlkXG4gICAgfSlcblxuICAgIGlmIChpc1NlcnZlcikge1xuICAgICAgQ3JlYXRlZEJ5LmNyZWF0ZU9yUmVwbGFjZShuZXdFbnRpdHlJZCwgeyBhZGRyZXNzOiBzZW5kZXIgfSlcbiAgICB9XG5cbiAgICBERUJVR19ORVRXT1JLX01FU1NBR0VTKCkgJiZcbiAgICAgIGNvbnNvbGUubG9nKGBbREVCVUddIENyZWF0ZWQgbmV3IGVudGl0eSAke25ld0VudGl0eUlkfSBmb3IgbmV0d29yayAke21lc3NhZ2UubmV0d29ya0lkfToke21lc3NhZ2UuZW50aXR5SWR9YClcbiAgICByZXR1cm4gbmV3RW50aXR5SWRcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvbnZlcnROZXR3b3JrVG9SZWd1bGFyTWVzc2FnZShcbiAgICBuZXR3b3JrTWVzc2FnZTogdXRpbHMuTmV0d29ya01lc3NhZ2UsXG4gICAgbG9jYWxFbnRpdHlJZDogRW50aXR5LFxuICAgIGZvcmNlQ29ycmVjdGlvbnMgPSBmYWxzZVxuICApOiAoQ3JkdE1lc3NhZ2VCb2R5ICYgeyBtZXNzYWdlQnVmZmVyOiBVaW50OEFycmF5IH0pIHwgbnVsbCB7XG4gICAgY29uc3QgYnVmZmVyID0gbmV3IFJlYWRXcml0ZUJ5dGVCdWZmZXIoKVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIFVzZSB0aGUgd2VsbC10ZXN0ZWQgbmV0d29ya01lc3NhZ2VUb0xvY2FsIHV0aWxpdHkgd2l0aCB0cmFuc2Zvcm0gZml4aW5nIGZvciBVbml0eVxuICAgICAgY29uc3QgbWVzc2FnZSA9IHV0aWxzLm5ldHdvcmtNZXNzYWdlVG9Mb2NhbChcbiAgICAgICAgbmV0d29ya01lc3NhZ2UsXG4gICAgICAgIGxvY2FsRW50aXR5SWQsXG4gICAgICAgIGJ1ZmZlcixcbiAgICAgICAgTmV0d29ya1BhcmVudCxcbiAgICAgICAgZm9yY2VDb3JyZWN0aW9uc1xuICAgICAgKVxuICAgICAgcmV0dXJuIHsgLi4ubWVzc2FnZSwgbWVzc2FnZUJ1ZmZlcjogYnVmZmVyLnRvQmluYXJ5KCkgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBERUJVR19ORVRXT1JLX01FU1NBR0VTKCkgJiYgY29uc29sZS5lcnJvcignRXJyb3IgY29udmVydGluZyBuZXR3b3JrIG1lc3NhZ2U6JywgZXJyb3IpXG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHZhbGlkYXRlTWVzc2FnZVBlcm1pc3Npb25zKG1lc3NhZ2U6IHV0aWxzLlJlZ3VsYXJNZXNzYWdlLCBzZW5kZXI6IHN0cmluZywgX2xvY2FsRW50aXR5SWQ6IEVudGl0eSk6IGJvb2xlYW4ge1xuICAgIC8vIEJhc2ljIGNoZWNrc1xuICAgIGlmICghc2VuZGVyIHx8IHNlbmRlciA9PT0gQVVUSF9TRVJWRVJfUEVFUl9JRCkge1xuICAgICAgcmV0dXJuIGZhbHNlIC8vIFNlcnZlciBzaG91bGRuJ3Qgc2VuZCBtZXNzYWdlcyB0byBpdHNlbGZcbiAgICB9XG5cbiAgICBpZiAobWVzc2FnZS50eXBlID09PSBDcmR0TWVzc2FnZVR5cGUuREVMRVRFX0VOVElUWSkge1xuICAgICAgLy8gVE9ETzogaG93IHRvIGhhbmRsZSB0aGlzIGNhc2UgP1xuICAgIH1cblxuICAgIGlmIChtZXNzYWdlLnR5cGUgPT09IENyZHRNZXNzYWdlVHlwZS5QVVRfQ09NUE9ORU5UIHx8IG1lc3NhZ2UudHlwZSA9PT0gQ3JkdE1lc3NhZ2VUeXBlLkRFTEVURV9DT01QT05FTlQpIHtcbiAgICAgIGNvbnN0IGNvbXBvbmVudCA9IGVuZ2luZS5nZXRDb21wb25lbnQobWVzc2FnZS5jb21wb25lbnRJZCkgYXMgSW50ZXJuYWxCYXNlQ29tcG9uZW50PHVua25vd24+XG4gICAgICBjb25zdCBidWYgPSAnZGF0YScgaW4gbWVzc2FnZSA/IG5ldyBSZWFkV3JpdGVCeXRlQnVmZmVyKG1lc3NhZ2UuZGF0YSkgOiBudWxsXG4gICAgICBjb25zdCB2YWx1ZSA9IGJ1ZiA/IGNvbXBvbmVudC5zY2hlbWEuZGVzZXJpYWxpemUoYnVmKSA6IG51bGxcbiAgICAgIGNvbnN0IGRyeVJ1bkNSRFQgPSBjb21wb25lbnQuX19kcnlfcnVuX3VwZGF0ZUZyb21DcmR0KG1lc3NhZ2UpXG4gICAgICBjb25zdCB2YWxpZENSRFQgPSBbXG4gICAgICAgIFByb2Nlc3NNZXNzYWdlUmVzdWx0VHlwZS5TdGF0ZVVwZGF0ZWREYXRhLFxuICAgICAgICBQcm9jZXNzTWVzc2FnZVJlc3VsdFR5cGUuU3RhdGVVcGRhdGVkVGltZXN0YW1wLFxuICAgICAgICBQcm9jZXNzTWVzc2FnZVJlc3VsdFR5cGUuRW50aXR5RGVsZXRlZFxuICAgICAgXS5pbmNsdWRlcyhkcnlSdW5DUkRUKVxuICAgICAgY29uc3QgY3JlYXRlZEJ5ID0gQ3JlYXRlZEJ5LmdldE9yTnVsbChtZXNzYWdlLmVudGl0eUlkKVxuICAgICAgY29uc3QgdmFsaWRNZXNzYWdlID1cbiAgICAgICAgdmFsaWRDUkRUICYmXG4gICAgICAgIGNvbXBvbmVudC5fX3J1bl92YWxpZGF0ZUJlZm9yZUNoYW5nZShtZXNzYWdlLmVudGl0eUlkLCB2YWx1ZSwgc2VuZGVyLCBjcmVhdGVkQnk/LmFkZHJlc3MgPz8gQVVUSF9TRVJWRVJfUEVFUl9JRClcblxuICAgICAgcmV0dXJuICEhdmFsaWRNZXNzYWdlXG4gICAgfVxuXG4gICAgLy8gRm9yIG5vdywgYmFzaWMgdmFsaWRhdGlvbiAtIGluIHRoZSBmdXR1cmUgdGhpcyB3aWxsIGNoZWNrIGNvbXBvbmVudCBzeW5jIHBlcm1pc3Npb25zXG4gICAgLy8gVE9ETzogQ2hlY2sgaWYgc2VuZGVyIG93bnMgdGhlIGVudGl0eVxuICAgIC8vIFRPRE86IENoZWNrIGNvbXBvbmVudCBzeW5jIG1vZGUgKCdhbGwnIHwgJ293bmVyJyB8ICdzZXJ2ZXInKVxuICAgIC8vIFRPRE86IFJ1biBjb21wb25lbnQgY3VzdG9tIHZhbGlkYXRpb25cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgZnVuY3Rpb24gYnJvYWRjYXN0QmF0Y2hlZE1lc3NhZ2VzKG1lc3NhZ2VzOiB1dGlscy5OZXR3b3JrTWVzc2FnZVtdLCBleGNsdWRlU2VuZGVyOiBzdHJpbmcpIHtcbiAgICBpZiAobWVzc2FnZXMubGVuZ3RoID09PSAwKSByZXR1cm5cblxuICAgIC8vIEJ1aWxkIHRoZSBjb21wbGV0ZSBidWZmZXIgd2l0aCBhbGwgbWVzc2FnZXNcbiAgICBjb25zdCBuZXR3b3JrQnVmZmVyID0gbmV3IFJlYWRXcml0ZUJ5dGVCdWZmZXIoKVxuICAgIGZvciAoY29uc3QgbWVzc2FnZSBvZiBtZXNzYWdlcykge1xuICAgICAgLy8gU2tpcCBvdmVyc2l6ZWQgbWVzc2FnZXMgdXBmcm9udFxuICAgICAgaWYgKG1lc3NhZ2UubWVzc2FnZUJ1ZmZlci5ieXRlTGVuZ3RoIC8gMTAyNCA+IExJVkVLSVRfTUFYX1NJWkUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgICBgTWVzc2FnZSB0b28gbGFyZ2UgKCR7bWVzc2FnZS5tZXNzYWdlQnVmZmVyLmJ5dGVMZW5ndGh9IGJ5dGVzKSwgc2tpcHBpbmcgbWVzc2FnZSBmcm9tICR7ZXhjbHVkZVNlbmRlcn1gXG4gICAgICAgIClcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIG5ldHdvcmtCdWZmZXIud3JpdGVCdWZmZXIobWVzc2FnZS5tZXNzYWdlQnVmZmVyLCBmYWxzZSlcbiAgICB9XG5cbiAgICAvLyBVc2UgdGhlIGNodW5raW5nIGZ1bmN0aW9uIHRvIHNwbGl0IGludG8gcHJvcGVyIGNodW5rc1xuICAgIGNvbnN0IGNodW5rcyA9IGNodW5rQ3JkdE1lc3NhZ2VzKG5ldHdvcmtCdWZmZXIudG9CaW5hcnkoKSwgTElWRUtJVF9NQVhfU0laRSlcblxuICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzKSB7XG4gICAgICBiaW5hcnlNZXNzYWdlQnVzLmVtaXQoQ29tbXNNZXNzYWdlLkNSRFQsIGNodW5rKVxuICAgIH1cbiAgICBERUJVR19ORVRXT1JLX01FU1NBR0VTKCkgJiZcbiAgICAgIGNvbnNvbGUubG9nKGBUb3RhbDogJHttZXNzYWdlcy5sZW5ndGh9IG1lc3NhZ2VzIGluICR7Y2h1bmtzLmxlbmd0aH0gY2h1bmtzIGZyb20gJHtleGNsdWRlU2VuZGVyfWApXG4gIH1cblxuICBmdW5jdGlvbiBzZW5kQ29ycmVjdGlvblRvU2VuZGVyKG5ldHdvcmtNZXNzYWdlOiB1dGlscy5OZXR3b3JrTWVzc2FnZSwgc2VuZGVyOiBzdHJpbmcsIGxvY2FsRW50aXR5SWQ6IEVudGl0eSkge1xuICAgIHRyeSB7XG4gICAgICAvLyBPbmx5IGhhbmRsZSBjb21wb25lbnQgbWVzc2FnZXMgKFBVVC9ERUxFVEUpLCBub3QgZW50aXR5IGRlbGV0aW9uXG4gICAgICBpZiAobmV0d29ya01lc3NhZ2UudHlwZSA9PT0gQ3JkdE1lc3NhZ2VUeXBlLkRFTEVURV9FTlRJVFlfTkVUV09SSykge1xuICAgICAgICBERUJVR19ORVRXT1JLX01FU1NBR0VTKCkgJiYgY29uc29sZS5sb2coJ1tBVVRIT1JJVEFUSVZFXSBDYW5ub3Qgc2VuZCBhdXRob3JpdGF0aXZlIG1lc3NhZ2UgZm9yIGVudGl0eSBkZWxldGlvbicpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICAvLyBTYWZlIHRvIGFjY2VzcyBjb21wb25lbnRJZCBhbmQgdGltZXN0YW1wIG5vd1xuICAgICAgY29uc3QgY29tcG9uZW50ID0gZW5naW5lLmdldENvbXBvbmVudChuZXR3b3JrTWVzc2FnZS5jb21wb25lbnRJZClcblxuICAgICAgLy8gT25seSBwcm9jZWVkIGlmIGNvbXBvbmVudCBzdXBwb3J0cyBhdXRob3JpdGF0aXZlIG1lc3NhZ2VzIChMV1cgb3IgR3Jvd09ubHlTZXQpXG4gICAgICBpZiAoIXN1cHBvcnRzQ29ycmVjdGlvbnMoY29tcG9uZW50KSkge1xuICAgICAgICBERUJVR19ORVRXT1JLX01FU1NBR0VTKCkgJiYgY29uc29sZS5sb2coJ1tBVVRIT1JJVEFUSVZFXSBDb21wb25lbnQgZG9lcyBub3Qgc3VwcG9ydCBhdXRob3JpdGF0aXZlIG1lc3NhZ2VzJylcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNlcnZlckNSRFRTdGF0ZSA9IGNvbXBvbmVudC5nZXRDcmR0U3RhdGUobG9jYWxFbnRpdHlJZClcblxuICAgICAgaWYgKHNlcnZlckNSRFRTdGF0ZSkge1xuICAgICAgICAvLyBDcmVhdGUgYXV0aG9yaXRhdGl2ZSBtZXNzYWdlIHVzaW5nIFBVVF9DT01QT05FTlRfTkVUV09SS1xuICAgICAgICAvLyBFYWNoIGNsaWVudCB3aWxsIGNvbnZlcnQgdGhpcyB0byBBVVRIT1JJVEFUSVZFX1BVVF9DT01QT05FTlQgd2l0aCBwcm9wZXIgZW50aXR5IG1hcHBpbmdcbiAgICAgICAgY29uc3QgY29ycmVjdGlvbkJ1ZmZlciA9IG5ldyBSZWFkV3JpdGVCeXRlQnVmZmVyKClcbiAgICAgICAgUHV0TmV0d29ya0NvbXBvbmVudE9wZXJhdGlvbi53cml0ZShcbiAgICAgICAgICBuZXR3b3JrTWVzc2FnZS5lbnRpdHlJZCwgLy8gVXNlIG9yaWdpbmFsIG5ldHdvcmsgZW50aXR5IElEXG4gICAgICAgICAgc2VydmVyQ1JEVFN0YXRlLnRpbWVzdGFtcCxcbiAgICAgICAgICBuZXR3b3JrTWVzc2FnZS5jb21wb25lbnRJZCxcbiAgICAgICAgICBuZXR3b3JrTWVzc2FnZS5uZXR3b3JrSWQsXG4gICAgICAgICAgc2VydmVyQ1JEVFN0YXRlLmRhdGEsXG4gICAgICAgICAgY29ycmVjdGlvbkJ1ZmZlclxuICAgICAgICApXG4gICAgICAgIC8vIFNlbmQgYXV0aG9yaXRhdGl2ZSBtZXNzYWdlIGRpcmVjdGx5IHRvIHRoZSBzZW5kZXJcbiAgICAgICAgYmluYXJ5TWVzc2FnZUJ1cy5lbWl0KENvbW1zTWVzc2FnZS5DUkRUX0FVVEhPUklUQVRJVkUsIGNvcnJlY3Rpb25CdWZmZXIudG9CaW5hcnkoKSwgW3NlbmRlcl0pXG5cbiAgICAgICAgREVCVUdfTkVUV09SS19NRVNTQUdFUygpICYmXG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICBgW0FVVEhPUklUQVRJVkVdIFNlbnQgYXV0aG9yaXRhdGl2ZSBtZXNzYWdlIHRvICR7c2VuZGVyfSBmb3IgZW50aXR5ICR7bG9jYWxFbnRpdHlJZH0gY29tcG9uZW50ICR7bmV0d29ya01lc3NhZ2UuY29tcG9uZW50SWR9IHdpdGggdGltZXN0YW1wICR7bmV0d29ya01lc3NhZ2UudGltZXN0YW1wfWBcbiAgICAgICAgICApXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIERFQlVHX05FVFdPUktfTUVTU0FHRVMoKSAmJiBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIGNvcnJlY3Rpb246JywgZXJyb3IpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBmaW5kRXhpc3RpbmdOZXR3b3JrRW50aXR5LFxuICAgIC8vIHRyYW5zZm9ybSBOZXR3b3JrIG1lc3NhZ2VzIHRvIENSRFQgQ29tbW9uIE1lc3NhZ2VzLlxuICAgIHByb2Nlc3NDbGllbnRNZXNzYWdlczogZnVuY3Rpb24gcHJvY2Vzc0NsaWVudE1lc3NhZ2VzKHZhbHVlOiBVaW50OEFycmF5LCBzZW5kZXI6IHN0cmluZywgZm9yY2VDb3JyZWN0aW9ucyA9IGZhbHNlKSB7XG4gICAgICAvLyBjb25zb2xlLmxvZyhgW0NMSUVOVF0gUHJvY2Vzc2luZyBtZXNzYWdlIGZyb20gJHtzZW5kZXJ9LCAke3ZhbHVlLmxlbmd0aH0gYnl0ZXNgKVxuXG4gICAgICAvLyBDb2xsZWN0IGFsbCByZWd1bGFyIG1lc3NhZ2VzIGluIGEgc2luZ2xlIGJ1ZmZlciBmb3IgYmF0Y2hlZCBhcHBsaWNhdGlvblxuICAgICAgY29uc3QgY29tYmluZWRCdWZmZXIgPSBuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcigpXG5cbiAgICAgIC8vIENsaWVudHMgcHJvY2VzcyBuZXR3b3JrIG1lc3NhZ2VzIGZyb20gc2VydmVyIGFuZCBjb252ZXJ0IHRoZW0gdG8gcmVndWxhciBtZXNzYWdlc1xuICAgICAgZm9yIChjb25zdCBtZXNzYWdlIG9mIHV0aWxzLnJlYWRNZXNzYWdlcyh2YWx1ZSkpIHtcbiAgICAgICAgLy8gT25seSBwcm9jZXNzIG5ldHdvcmsgbWVzc2FnZXMgaW4gY2xpZW50IG1lc3NhZ2UgaGFuZGxlclxuICAgICAgICBpZiAodXRpbHMuaXNOZXR3b3JrTWVzc2FnZShtZXNzYWdlKSkge1xuICAgICAgICAgIGNvbnN0IG5ldHdvcmtNZXNzYWdlID0gbWVzc2FnZSBhcyB1dGlscy5OZXR3b3JrTWVzc2FnZVxuXG4gICAgICAgICAgLy8gRmluZCBvciBjcmVhdGUgbmV0d29yayBlbnRpdHkgbWFwcGluZ1xuICAgICAgICAgIGNvbnN0IGxvY2FsRW50aXR5SWQgPSBmaW5kT3JDcmVhdGVOZXR3b3JrRW50aXR5KG5ldHdvcmtNZXNzYWdlLCBzZW5kZXIsIGZhbHNlKVxuXG4gICAgICAgICAgLy8gQ29udmVydCBuZXR3b3JrIG1lc3NhZ2UgdG8gcmVndWxhciBtZXNzYWdlIG9yIGNvcnJlY3Rpb24gbWVzc2FnZVxuICAgICAgICAgIGNvbnN0IHJlZ3VsYXJNZXNzYWdlID0gY29udmVydE5ldHdvcmtUb1JlZ3VsYXJNZXNzYWdlKG5ldHdvcmtNZXNzYWdlLCBsb2NhbEVudGl0eUlkLCBmb3JjZUNvcnJlY3Rpb25zKVxuXG4gICAgICAgICAgaWYgKHJlZ3VsYXJNZXNzYWdlPy5tZXNzYWdlQnVmZmVyLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbWJpbmVkQnVmZmVyLndyaXRlQnVmZmVyKHJlZ3VsYXJNZXNzYWdlLm1lc3NhZ2VCdWZmZXIsIGZhbHNlKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGNvbWJpbmVkQnVmZmVyLnRvQmluYXJ5KClcbiAgICB9LFxuICAgIC8vIFNldmVyIENvZGU6IHByb2Nlc3MgbWVzc2FnZSwgaGFuZGxlIHBlcm1pc3Npb25zLCBhbmQgYnJvYWRjYXN0IGlmIG5lZWRlZC5cbiAgICBwcm9jZXNzU2VydmVyTWVzc2FnZXM6IGZ1bmN0aW9uIHByb2Nlc3NTZXJ2ZXJNZXNzYWdlcyh2YWx1ZTogVWludDhBcnJheSwgc2VuZGVyOiBzdHJpbmcpIHtcbiAgICAgIC8vIGNvbnNvbGUubG9nKGBbU0VSVkVSXSBQcm9jZXNzaW5nIG1lc3NhZ2UgZnJvbSAke3NlbmRlcn0sICR7dmFsdWUubGVuZ3RofSBieXRlc2ApXG5cbiAgICAgIC8vIENvbGxlY3QgYWxsIHZhbGlkIG1lc3NhZ2VzIGZvciBiYXRjaGVkIGJyb2FkY2FzdGluZ1xuICAgICAgY29uc3QgbWVzc2FnZXNUb0Jyb2FkY2FzdDogdXRpbHMuTmV0d29ya01lc3NhZ2VbXSA9IFtdXG4gICAgICBjb25zdCByZWd1bGFyTWVzc2FnZXNCdWZmZXIgPSBuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcigpXG5cbiAgICAgIGZvciAoY29uc3QgbWVzc2FnZSBvZiB1dGlscy5yZWFkTWVzc2FnZXModmFsdWUpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gT25seSBwcm9jZXNzIG5ldHdvcmsgbWVzc2FnZXMgaW4gc2VydmVyIG1lc3NhZ2UgaGFuZGxlclxuICAgICAgICAgIGlmICh1dGlscy5pc05ldHdvcmtNZXNzYWdlKG1lc3NhZ2UpKSB7XG4gICAgICAgICAgICBjb25zdCBuZXR3b3JrTWVzc2FnZSA9IG1lc3NhZ2UgYXMgdXRpbHMuTmV0d29ya01lc3NhZ2VcbiAgICAgICAgICAgIC8vIDEuIEZpbmQgb3IgY3JlYXRlIG5ldHdvcmsgZW50aXR5IG1hcHBpbmdcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsRW50aXR5SWQgPSBmaW5kT3JDcmVhdGVOZXR3b3JrRW50aXR5KG5ldHdvcmtNZXNzYWdlLCBzZW5kZXIsIHRydWUpXG5cbiAgICAgICAgICAgIC8vIDIuIENvbnZlcnQgbmV0d29yayBtZXNzYWdlIHRvIHJlZ3VsYXIgbWVzc2FnZSBhbmQgY29sbGVjdCBmb3IgbG9jYWwgYXBwbGljYXRpb25cbiAgICAgICAgICAgIGNvbnN0IHJlZ3VsYXJNZXNzYWdlID0gY29udmVydE5ldHdvcmtUb1JlZ3VsYXJNZXNzYWdlKG5ldHdvcmtNZXNzYWdlLCBsb2NhbEVudGl0eUlkKVxuXG4gICAgICAgICAgICAvLyAzLiBCYXNpYyBwZXJtaXNzaW9uIHZhbGlkYXRpb25cbiAgICAgICAgICAgIGlmICghdmFsaWRhdGVNZXNzYWdlUGVybWlzc2lvbnMocmVndWxhck1lc3NhZ2UgYXMgYW55LCBzZW5kZXIsIGxvY2FsRW50aXR5SWQpKSB7XG4gICAgICAgICAgICAgIC8vIFNlbmQgY29ycmVjdGlvbiBiYWNrIHRvIHNlbmRlciB3aXRoIHNlcnZlcidzIGF1dGhvcml0YXRpdmUgc3RhdGVcbiAgICAgICAgICAgICAgc2VuZENvcnJlY3Rpb25Ub1NlbmRlcihuZXR3b3JrTWVzc2FnZSwgc2VuZGVyLCBsb2NhbEVudGl0eUlkKVxuICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyA0LiBDb2xsZWN0IHZhbGlkIG1lc3NhZ2UgZm9yIGJhdGNoZWQgYnJvYWRjYXN0aW5nXG4gICAgICAgICAgICBtZXNzYWdlc1RvQnJvYWRjYXN0LnB1c2gobmV0d29ya01lc3NhZ2UpXG5cbiAgICAgICAgICAgIGlmIChyZWd1bGFyTWVzc2FnZT8ubWVzc2FnZUJ1ZmZlci5ieXRlTGVuZ3RoKSB7XG4gICAgICAgICAgICAgIHJlZ3VsYXJNZXNzYWdlc0J1ZmZlci53cml0ZUJ1ZmZlcihyZWd1bGFyTWVzc2FnZS5tZXNzYWdlQnVmZmVyLCBmYWxzZSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgREVCVUdfTkVUV09SS19NRVNTQUdFUygpICYmIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHByb2Nlc3Npbmcgc2VydmVyIG1lc3NhZ2U6JywgZXJyb3IpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEJhdGNoIGJyb2FkY2FzdCBhbGwgdmFsaWQgbWVzc2FnZXMgdG9nZXRoZXJcbiAgICAgIGJyb2FkY2FzdEJhdGNoZWRNZXNzYWdlcyhtZXNzYWdlc1RvQnJvYWRjYXN0LCBzZW5kZXIpXG4gICAgICByZXR1cm4gcmVndWxhck1lc3NhZ2VzQnVmZmVyLnRvQmluYXJ5KClcbiAgICB9LFxuICAgIC8vIGVuZ2luZSBjaGFuZ2VzIHRoYXQgbmVlZHMgdG8gYmUgYnJvYWRjYXN0ZWQuXG4gICAgY29udmVydFJlZ3VsYXJUb05ldHdvcmtNZXNzYWdlOiBmdW5jdGlvbiBjb252ZXJ0UmVndWxhclRvTmV0d29ya01lc3NhZ2UocmVndWxhck1lc3NhZ2U6IFVpbnQ4QXJyYXkpOiBVaW50OEFycmF5W10ge1xuICAgICAgY29uc3QgZ3JvdXBlZEJ1ZmZlciA9IG5ldyBSZWFkV3JpdGVCeXRlQnVmZmVyKClcblxuICAgICAgLy8gRmlyc3QgcGFzczogQ29udmVydCBhbGwgcmVndWxhciBtZXNzYWdlcyB0byBuZXR3b3JrIGZvcm1hdCBhbmQgZ3JvdXAgdGhlbSBpbnRvIG9uZSBiaWcgYnVmZmVyXG4gICAgICBmb3IgKGNvbnN0IG1lc3NhZ2Ugb2YgdXRpbHMucmVhZE1lc3NhZ2VzKHJlZ3VsYXJNZXNzYWdlKSkge1xuICAgICAgICAvLyBPbmx5IGNvbnZlcnQgcmVndWxhciBtZXNzYWdlcyB0aGF0IGhhdmUgbmV0d29yayBkYXRhXG4gICAgICAgIGNvbnN0IG5ldHdvcmtEYXRhID0gTmV0d29ya0VudGl0eS5nZXRPck51bGwobWVzc2FnZS5lbnRpdHlJZClcblxuICAgICAgICBpZiAobmV0d29ya0RhdGEgJiYgIXV0aWxzLmlzTmV0d29ya01lc3NhZ2UobWVzc2FnZSkpIHtcbiAgICAgICAgICB1dGlscy5sb2NhbE1lc3NhZ2VUb05ldHdvcmsobWVzc2FnZSwgbmV0d29ya0RhdGEsIGdyb3VwZWRCdWZmZXIpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gU2Vjb25kIHBhc3M6IFVzZSB0aGUgbmV3IGNodW5raW5nIGZ1bmN0aW9uIHRoYXQgcmVzcGVjdHMgbWVzc2FnZSBib3VuZGFyaWVzXG4gICAgICBjb25zdCB0b3RhbERhdGEgPSBncm91cGVkQnVmZmVyLnRvQmluYXJ5KClcbiAgICAgIHJldHVybiBjaHVua0NyZHRNZXNzYWdlcyh0b3RhbERhdGEsIExJVkVLSVRfTUFYX1NJWkUpXG4gICAgfVxuICB9XG59XG4iXX0=
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Entity } from '@dcl/ecs/dist/engine';
|
|
2
|
-
import { NetworkParent } from '@dcl/ecs';
|
|
3
|
-
import { ReceiveMessage } from '@dcl/ecs/dist/runtime/types';
|
|
4
|
-
import { ReceiveNetworkMessage } from '@dcl/ecs/dist/systems/crdt/types';
|
|
5
|
-
import { ByteBuffer } from '@dcl/ecs/dist/serialization/ByteBuffer';
|
|
6
|
-
import { CrdtMessageBody, DeleteComponentMessage, DeleteComponentNetworkMessage, DeleteEntityMessage, DeleteEntityNetworkMessage, PutComponentMessage, AuthoritativePutComponentMessage, PutNetworkComponentMessage } from '@dcl/ecs/dist/serialization/crdt/types';
|
|
7
|
-
import { INetowrkEntityType } from '@dcl/ecs/dist/components/types';
|
|
8
|
-
export type NetworkMessage = (PutNetworkComponentMessage | DeleteComponentNetworkMessage | DeleteEntityNetworkMessage) & {
|
|
9
|
-
messageBuffer: Uint8Array;
|
|
10
|
-
};
|
|
11
|
-
export type RegularMessage = (PutComponentMessage | AuthoritativePutComponentMessage | DeleteComponentMessage | DeleteEntityMessage) & {
|
|
12
|
-
messageBuffer: Uint8Array;
|
|
13
|
-
};
|
|
14
|
-
export declare function readMessages(data: Uint8Array): (NetworkMessage | RegularMessage)[];
|
|
15
|
-
export declare function isNetworkMessage(message: ReceiveMessage): message is ReceiveNetworkMessage;
|
|
16
|
-
export declare function networkMessageToLocal(message: ReceiveNetworkMessage, localEntityId: Entity, destinationBuffer: ByteBuffer, networkParentComponent?: typeof NetworkParent, forceCorrections?: boolean): CrdtMessageBody;
|
|
17
|
-
export declare function localMessageToNetwork(message: ReceiveMessage, network: INetowrkEntityType, destinationBuffer: ByteBuffer): void;
|
|
18
|
-
export declare function fixTransformParent(message: ReceiveMessage, parent?: Entity): Uint8Array;
|
package/network/server/utils.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { CrdtMessageProtocol } from '@dcl/ecs';
|
|
2
|
-
import { ReadWriteByteBuffer } from '@dcl/ecs/dist/serialization/ByteBuffer';
|
|
3
|
-
import { AuthoritativePutComponentOperation, PutComponentOperation } from '@dcl/ecs/dist/serialization/crdt';
|
|
4
|
-
import { CrdtMessageType } from '@dcl/ecs/dist/serialization/crdt/types';
|
|
5
|
-
import { DeleteComponent } from '@dcl/ecs/dist/serialization/crdt/deleteComponent';
|
|
6
|
-
import { DeleteEntity } from '@dcl/ecs/dist/serialization/crdt/deleteEntity';
|
|
7
|
-
import { PutNetworkComponentOperation } from '@dcl/ecs/dist/serialization/crdt/network/putComponentNetwork';
|
|
8
|
-
import { DeleteComponentNetwork } from '@dcl/ecs/dist/serialization/crdt/network/deleteComponentNetwork';
|
|
9
|
-
import { DeleteEntityNetwork } from '@dcl/ecs/dist/serialization/crdt/network/deleteEntityNetwork';
|
|
10
|
-
import { TransformSchema, COMPONENT_ID as TransformComponentId } from '@dcl/ecs/dist/components/manual/Transform';
|
|
11
|
-
export function readMessages(data) {
|
|
12
|
-
const buffer = new ReadWriteByteBuffer(data);
|
|
13
|
-
const messages = [];
|
|
14
|
-
let header;
|
|
15
|
-
while ((header = CrdtMessageProtocol.getHeader(buffer))) {
|
|
16
|
-
const offset = buffer.currentReadOffset();
|
|
17
|
-
let message = undefined;
|
|
18
|
-
// Network messages
|
|
19
|
-
if (header.type === CrdtMessageType.DELETE_COMPONENT_NETWORK) {
|
|
20
|
-
message = DeleteComponentNetwork.read(buffer);
|
|
21
|
-
}
|
|
22
|
-
else if (header.type === CrdtMessageType.PUT_COMPONENT_NETWORK) {
|
|
23
|
-
message = PutNetworkComponentOperation.read(buffer);
|
|
24
|
-
}
|
|
25
|
-
else if (header.type === CrdtMessageType.DELETE_ENTITY_NETWORK) {
|
|
26
|
-
message = DeleteEntityNetwork.read(buffer);
|
|
27
|
-
}
|
|
28
|
-
// Regular messages
|
|
29
|
-
else if (header.type === CrdtMessageType.PUT_COMPONENT) {
|
|
30
|
-
message = PutComponentOperation.read(buffer);
|
|
31
|
-
}
|
|
32
|
-
else if (header.type === CrdtMessageType.AUTHORITATIVE_PUT_COMPONENT) {
|
|
33
|
-
message = AuthoritativePutComponentOperation.read(buffer);
|
|
34
|
-
}
|
|
35
|
-
else if (header.type === CrdtMessageType.DELETE_COMPONENT) {
|
|
36
|
-
message = DeleteComponent.read(buffer);
|
|
37
|
-
}
|
|
38
|
-
else if (header.type === CrdtMessageType.DELETE_ENTITY) {
|
|
39
|
-
message = DeleteEntity.read(buffer);
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
// consume unknown messages
|
|
43
|
-
buffer.incrementReadOffset(header.length);
|
|
44
|
-
}
|
|
45
|
-
if (message) {
|
|
46
|
-
messages.push({
|
|
47
|
-
...message,
|
|
48
|
-
messageBuffer: buffer.buffer().subarray(offset, buffer.currentReadOffset())
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return messages;
|
|
53
|
-
}
|
|
54
|
-
export function isNetworkMessage(message) {
|
|
55
|
-
return [
|
|
56
|
-
CrdtMessageType.DELETE_COMPONENT_NETWORK,
|
|
57
|
-
CrdtMessageType.DELETE_ENTITY_NETWORK,
|
|
58
|
-
CrdtMessageType.PUT_COMPONENT_NETWORK
|
|
59
|
-
].includes(message.type);
|
|
60
|
-
}
|
|
61
|
-
export function networkMessageToLocal(message, localEntityId, destinationBuffer,
|
|
62
|
-
// Optional network parent component for transform fixing
|
|
63
|
-
networkParentComponent,
|
|
64
|
-
// Force corrections - converts PUT_COMPONENT_NETWORK to authoritative_PUT_COMPONENT
|
|
65
|
-
forceCorrections = false) {
|
|
66
|
-
if (message.type === CrdtMessageType.PUT_COMPONENT_NETWORK) {
|
|
67
|
-
let messageData = message.data;
|
|
68
|
-
// Fix transform parent if needed for Unity/engine processing
|
|
69
|
-
if (message.componentId === TransformComponentId && networkParentComponent) {
|
|
70
|
-
const parentNetwork = networkParentComponent.getOrNull(localEntityId);
|
|
71
|
-
messageData = fixTransformParent(message, parentNetwork?.entityId);
|
|
72
|
-
}
|
|
73
|
-
if (forceCorrections) {
|
|
74
|
-
// Use AUTHORITATIVE_PUT_COMPONENT for forced state updates
|
|
75
|
-
AuthoritativePutComponentOperation.write(localEntityId, message.timestamp, message.componentId, messageData, destinationBuffer);
|
|
76
|
-
return {
|
|
77
|
-
type: CrdtMessageType.AUTHORITATIVE_PUT_COMPONENT,
|
|
78
|
-
componentId: message.componentId,
|
|
79
|
-
timestamp: message.timestamp,
|
|
80
|
-
data: messageData,
|
|
81
|
-
entityId: localEntityId
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
// Normal PUT_COMPONENT conversion
|
|
86
|
-
PutComponentOperation.write(localEntityId, message.timestamp, message.componentId, messageData, destinationBuffer);
|
|
87
|
-
return {
|
|
88
|
-
type: CrdtMessageType.PUT_COMPONENT,
|
|
89
|
-
componentId: message.componentId,
|
|
90
|
-
timestamp: message.timestamp,
|
|
91
|
-
data: messageData,
|
|
92
|
-
entityId: localEntityId
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
else if (message.type === CrdtMessageType.DELETE_COMPONENT_NETWORK) {
|
|
97
|
-
DeleteComponent.write(localEntityId, message.componentId, message.timestamp, destinationBuffer);
|
|
98
|
-
return {
|
|
99
|
-
type: CrdtMessageType.DELETE_COMPONENT,
|
|
100
|
-
componentId: message.componentId,
|
|
101
|
-
timestamp: message.timestamp,
|
|
102
|
-
entityId: localEntityId
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
else if (message.type === CrdtMessageType.DELETE_ENTITY_NETWORK) {
|
|
106
|
-
DeleteEntity.write(localEntityId, destinationBuffer);
|
|
107
|
-
return {
|
|
108
|
-
type: CrdtMessageType.DELETE_ENTITY,
|
|
109
|
-
entityId: localEntityId
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
throw 1;
|
|
113
|
-
}
|
|
114
|
-
export function localMessageToNetwork(message, network, destinationBuffer) {
|
|
115
|
-
if (message.type === CrdtMessageType.PUT_COMPONENT) {
|
|
116
|
-
PutNetworkComponentOperation.write(network.entityId, message.timestamp, message.componentId, network.networkId, message.data, destinationBuffer);
|
|
117
|
-
}
|
|
118
|
-
else if (message.type === CrdtMessageType.DELETE_COMPONENT) {
|
|
119
|
-
DeleteComponentNetwork.write(network.entityId, message.componentId, message.timestamp, network.networkId, destinationBuffer);
|
|
120
|
-
}
|
|
121
|
-
else if (message.type === CrdtMessageType.DELETE_ENTITY) {
|
|
122
|
-
DeleteEntityNetwork.write(network.entityId, network.networkId, destinationBuffer);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
export function fixTransformParent(message, parent) {
|
|
126
|
-
const buffer = new ReadWriteByteBuffer();
|
|
127
|
-
const transform = 'data' in message && TransformSchema.deserialize(new ReadWriteByteBuffer(message.data));
|
|
128
|
-
if (!transform)
|
|
129
|
-
throw new Error('Invalid parent transform');
|
|
130
|
-
// Generate new transform raw data with the parent
|
|
131
|
-
const newTransform = { ...transform, parent };
|
|
132
|
-
TransformSchema.serialize(newTransform, buffer);
|
|
133
|
-
return buffer.toBinary();
|
|
134
|
-
}
|
|
135
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbmV0d29yay9zZXJ2ZXIvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLG1CQUFtQixFQUFpQixNQUFNLFVBQVUsQ0FBQTtBQUc3RCxPQUFPLEVBQWMsbUJBQW1CLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQTtBQUN4RixPQUFPLEVBQUUsa0NBQWtDLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQTtBQUM1RyxPQUFPLEVBSUwsZUFBZSxFQVFoQixNQUFNLHdDQUF3QyxDQUFBO0FBQy9DLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrREFBa0QsQ0FBQTtBQUNsRixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sK0NBQStDLENBQUE7QUFFNUUsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sOERBQThELENBQUE7QUFDM0csT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0saUVBQWlFLENBQUE7QUFDeEcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sOERBQThELENBQUE7QUFDbEcsT0FBTyxFQUFFLGVBQWUsRUFBRSxZQUFZLElBQUksb0JBQW9CLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQTtBQWdCakgsTUFBTSxVQUFVLFlBQVksQ0FBQyxJQUFnQjtJQUMzQyxNQUFNLE1BQU0sR0FBRyxJQUFJLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFBO0lBQzVDLE1BQU0sUUFBUSxHQUF3QyxFQUFFLENBQUE7SUFDeEQsSUFBSSxNQUFnQyxDQUFBO0lBQ3BDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsbUJBQW1CLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUU7UUFDdkQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUE7UUFDekMsSUFBSSxPQUFPLEdBQTRCLFNBQVMsQ0FBQTtRQUVoRCxtQkFBbUI7UUFDbkIs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QUE7SUFFM0Qsa0RBQWtEO0lBQ2xELE1BQU0sWUFBWSxHQUFHLEVBQUUsR0FBRyxTQUFTLEVBQUUsTUFBTSxFQUFFLENBQUE7SUFDN0MsZUFBZSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDL0MsT0FBTyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUE7QUFDMUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEVudGl0eSB9IGZyb20gJ0BkY2wvZWNzL2Rpc3QvZW5naW5lJ1xuaW1wb3J0IHsgQ3JkdE1lc3NhZ2VQcm90b2NvbCwgTmV0d29ya1BhcmVudCB9IGZyb20gJ0BkY2wvZWNzJ1xuaW1wb3J0IHsgUmVjZWl2ZU1lc3NhZ2UgfSBmcm9tICdAZGNsL2Vjcy9kaXN0L3J1bnRpbWUvdHlwZXMnXG5pbXBvcnQgeyBSZWNlaXZlTmV0d29ya01lc3NhZ2UgfSBmcm9tICdAZGNsL2Vjcy9kaXN0L3N5c3RlbXMvY3JkdC90eXBlcydcbmltcG9ydCB7IEJ5dGVCdWZmZXIsIFJlYWRXcml0ZUJ5dGVCdWZmZXIgfSBmcm9tICdAZGNsL2Vjcy9kaXN0L3NlcmlhbGl6YXRpb24vQnl0ZUJ1ZmZlcidcbmltcG9ydCB7IEF1dGhvcml0YXRpdmVQdXRDb21wb25lbnRPcGVyYXRpb24sIFB1dENvbXBvbmVudE9wZXJhdGlvbiB9IGZyb20gJ0BkY2wvZWNzL2Rpc3Qvc2VyaWFsaXphdGlvbi9jcmR0J1xuaW1wb3J0IHtcbiAgQ3JkdE1lc3NhZ2UsXG4gIENyZHRNZXNzYWdlQm9keSxcbiAgQ3JkdE1lc3NhZ2VIZWFkZXIsXG4gIENyZHRNZXNzYWdlVHlwZSxcbiAgRGVsZXRlQ29tcG9uZW50TWVzc2FnZSxcbiAgRGVsZXRlQ29tcG9uZW50TmV0d29ya01lc3NhZ2UsXG4gIERlbGV0ZUVudGl0eU1lc3NhZ2UsXG4gIERlbGV0ZUVudGl0eU5ldHdvcmtNZXNzYWdlLFxuICBQdXRDb21wb25lbnRNZXNzYWdlLFxuICBBdXRob3JpdGF0aXZlUHV0Q29tcG9uZW50TWVzc2FnZSxcbiAgUHV0TmV0d29ya0NvbXBvbmVudE1lc3NhZ2Vcbn0gZnJvbSAnQGRjbC9lY3MvZGlzdC9zZXJpYWxpemF0aW9uL2NyZHQvdHlwZXMnXG5pbXBvcnQgeyBEZWxldGVDb21wb25lbnQgfSBmcm9tICdAZGNsL2Vjcy9kaXN0L3NlcmlhbGl6YXRpb24vY3JkdC9kZWxldGVDb21wb25lbnQnXG5pbXBvcnQgeyBEZWxldGVFbnRpdHkgfSBmcm9tICdAZGNsL2Vjcy9kaXN0L3NlcmlhbGl6YXRpb24vY3JkdC9kZWxldGVFbnRpdHknXG5pbXBvcnQgeyBJTmV0b3dya0VudGl0eVR5cGUgfSBmcm9tICdAZGNsL2Vjcy9kaXN0L2NvbXBvbmVudHMvdHlwZXMnXG5pbXBvcnQgeyBQdXROZXR3b3JrQ29tcG9uZW50T3BlcmF0aW9uIH0gZnJvbSAnQGRjbC9lY3MvZGlzdC9zZXJpYWxpemF0aW9uL2NyZHQvbmV0d29yay9wdXRDb21wb25lbnROZXR3b3JrJ1xuaW1wb3J0IHsgRGVsZXRlQ29tcG9uZW50TmV0d29yayB9IGZyb20gJ0BkY2wvZWNzL2Rpc3Qvc2VyaWFsaXphdGlvbi9jcmR0L25ldHdvcmsvZGVsZXRlQ29tcG9uZW50TmV0d29yaydcbmltcG9ydCB7IERlbGV0ZUVudGl0eU5ldHdvcmsgfSBmcm9tICdAZGNsL2Vjcy9kaXN0L3NlcmlhbGl6YXRpb24vY3JkdC9uZXR3b3JrL2RlbGV0ZUVudGl0eU5ldHdvcmsnXG5pbXBvcnQgeyBUcmFuc2Zvcm1TY2hlbWEsIENPTVBPTkVOVF9JRCBhcyBUcmFuc2Zvcm1Db21wb25lbnRJZCB9IGZyb20gJ0BkY2wvZWNzL2Rpc3QvY29tcG9uZW50cy9tYW51YWwvVHJhbnNmb3JtJ1xuXG5leHBvcnQgdHlwZSBOZXR3b3JrTWVzc2FnZSA9IChcbiAgfCBQdXROZXR3b3JrQ29tcG9uZW50TWVzc2FnZVxuICB8IERlbGV0ZUNvbXBvbmVudE5ldHdvcmtNZXNzYWdlXG4gIHwgRGVsZXRlRW50aXR5TmV0d29ya01lc3NhZ2VcbikgJiB7IG1lc3NhZ2VCdWZmZXI6IFVpbnQ4QXJyYXkgfVxuXG5leHBvcnQgdHlwZSBSZWd1bGFyTWVzc2FnZSA9IChcbiAgfCBQdXRDb21wb25lbnRNZXNzYWdlXG4gIHwgQXV0aG9yaXRhdGl2ZVB1dENvbXBvbmVudE1lc3NhZ2VcbiAgfCBEZWxldGVDb21wb25lbnRNZXNzYWdlXG4gIHwgRGVsZXRlRW50aXR5TWVzc2FnZVxuKSAmIHtcbiAgbWVzc2FnZUJ1ZmZlcjogVWludDhBcnJheVxufVxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRNZXNzYWdlcyhkYXRhOiBVaW50OEFycmF5KTogKE5ldHdvcmtNZXNzYWdlIHwgUmVndWxhck1lc3NhZ2UpW10ge1xuICBjb25zdCBidWZmZXIgPSBuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcihkYXRhKVxuICBjb25zdCBtZXNzYWdlczogKE5ldHdvcmtNZXNzYWdlIHwgUmVndWxhck1lc3NhZ2UpW10gPSBbXVxuICBsZXQgaGVhZGVyOiBDcmR0TWVzc2FnZUhlYWRlciB8IG51bGxcbiAgd2hpbGUgKChoZWFkZXIgPSBDcmR0TWVzc2FnZVByb3RvY29sLmdldEhlYWRlcihidWZmZXIpKSkge1xuICAgIGNvbnN0IG9mZnNldCA9IGJ1ZmZlci5jdXJyZW50UmVhZE9mZnNldCgpXG4gICAgbGV0IG1lc3NhZ2U6IENyZHRNZXNzYWdlIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkXG5cbiAgICAvLyBOZXR3b3JrIG1lc3NhZ2VzXG4gICAgaWYgKGhlYWRlci50eXBlID09PSBDcmR0TWVzc2FnZVR5cGUuREVMRVRFX0NPTVBPTkVOVF9ORVRXT1JLKSB7XG4gICAgICBtZXNzYWdlID0gRGVsZXRlQ29tcG9uZW50TmV0d29yay5yZWFkKGJ1ZmZlcikhXG4gICAgfSBlbHNlIGlmIChoZWFkZXIudHlwZSA9PT0gQ3JkdE1lc3NhZ2VUeXBlLlBVVF9DT01QT05FTlRfTkVUV09SSykge1xuICAgICAgbWVzc2FnZSA9IFB1dE5ldHdvcmtDb21wb25lbnRPcGVyYXRpb24ucmVhZChidWZmZXIpIVxuICAgIH0gZWxzZSBpZiAoaGVhZGVyLnR5cGUgPT09IENyZHRNZXNzYWdlVHlwZS5ERUxFVEVfRU5USVRZX05FVFdPUkspIHtcbiAgICAgIG1lc3NhZ2UgPSBEZWxldGVFbnRpdHlOZXR3b3JrLnJlYWQoYnVmZmVyKSFcbiAgICB9XG4gICAgLy8gUmVndWxhciBtZXNzYWdlc1xuICAgIGVsc2UgaWYgKGhlYWRlci50eXBlID09PSBDcmR0TWVzc2FnZVR5cGUuUFVUX0NPTVBPTkVOVCkge1xuICAgICAgbWVzc2FnZSA9IFB1dENvbXBvbmVudE9wZXJhdGlvbi5yZWFkKGJ1ZmZlcikhXG4gICAgfSBlbHNlIGlmIChoZWFkZXIudHlwZSA9PT0gQ3JkdE1lc3NhZ2VUeXBlLkFVVEhPUklUQVRJVkVfUFVUX0NPTVBPTkVOVCkge1xuICAgICAgbWVzc2FnZSA9IEF1dGhvcml0YXRpdmVQdXRDb21wb25lbnRPcGVyYXRpb24ucmVhZChidWZmZXIpIVxuICAgIH0gZWxzZSBpZiAoaGVhZGVyLnR5cGUgPT09IENyZHRNZXNzYWdlVHlwZS5ERUxFVEVfQ09NUE9ORU5UKSB7XG4gICAgICBtZXNzYWdlID0gRGVsZXRlQ29tcG9uZW50LnJlYWQoYnVmZmVyKSFcbiAgICB9IGVsc2UgaWYgKGhlYWRlci50eXBlID09PSBDcmR0TWVzc2FnZVR5cGUuREVMRVRFX0VOVElUWSkge1xuICAgICAgbWVzc2FnZSA9IERlbGV0ZUVudGl0eS5yZWFkKGJ1ZmZlcikhXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGNvbnN1bWUgdW5rbm93biBtZXNzYWdlc1xuICAgICAgYnVmZmVyLmluY3JlbWVudFJlYWRPZmZzZXQoaGVhZGVyLmxlbmd0aClcbiAgICB9XG5cbiAgICBpZiAobWVzc2FnZSkge1xuICAgICAgbWVzc2FnZXMucHVzaCh7XG4gICAgICAgIC4uLm1lc3NhZ2UsXG4gICAgICAgIG1lc3NhZ2VCdWZmZXI6IGJ1ZmZlci5idWZmZXIoKS5zdWJhcnJheShvZmZzZXQsIGJ1ZmZlci5jdXJyZW50UmVhZE9mZnNldCgpKVxuICAgICAgfSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG1lc3NhZ2VzXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc05ldHdvcmtNZXNzYWdlKG1lc3NhZ2U6IFJlY2VpdmVNZXNzYWdlKTogbWVzc2FnZSBpcyBSZWNlaXZlTmV0d29ya01lc3NhZ2Uge1xuICByZXR1cm4gW1xuICAgIENyZHRNZXNzYWdlVHlwZS5ERUxFVEVfQ09NUE9ORU5UX05FVFdPUkssXG4gICAgQ3JkdE1lc3NhZ2VUeXBlLkRFTEVURV9FTlRJVFlfTkVUV09SSyxcbiAgICBDcmR0TWVzc2FnZVR5cGUuUFVUX0NPTVBPTkVOVF9ORVRXT1JLXG4gIF0uaW5jbHVkZXMobWVzc2FnZS50eXBlKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbmV0d29ya01lc3NhZ2VUb0xvY2FsKFxuICBtZXNzYWdlOiBSZWNlaXZlTmV0d29ya01lc3NhZ2UsXG4gIGxvY2FsRW50aXR5SWQ6IEVudGl0eSxcbiAgZGVzdGluYXRpb25CdWZmZXI6IEJ5dGVCdWZmZXIsXG4gIC8vIE9wdGlvbmFsIG5ldHdvcmsgcGFyZW50IGNvbXBvbmVudCBmb3IgdHJhbnNmb3JtIGZpeGluZ1xuICBuZXR3b3JrUGFyZW50Q29tcG9uZW50PzogdHlwZW9mIE5ldHdvcmtQYXJlbnQsXG4gIC8vIEZvcmNlIGNvcnJlY3Rpb25zIC0gY29udmVydHMgUFVUX0NPTVBPTkVOVF9ORVRXT1JLIHRvIGF1dGhvcml0YXRpdmVfUFVUX0NPTVBPTkVOVFxuICBmb3JjZUNvcnJlY3Rpb25zID0gZmFsc2Vcbik6IENyZHRNZXNzYWdlQm9keSB7XG4gIGlmIChtZXNzYWdlLnR5cGUgPT09IENyZHRNZXNzYWdlVHlwZS5QVVRfQ09NUE9ORU5UX05FVFdPUkspIHtcbiAgICBsZXQgbWVzc2FnZURhdGEgPSBtZXNzYWdlLmRhdGFcblxuICAgIC8vIEZpeCB0cmFuc2Zvcm0gcGFyZW50IGlmIG5lZWRlZCBmb3IgVW5pdHkvZW5naW5lIHByb2Nlc3NpbmdcbiAgICBpZiAobWVzc2FnZS5jb21wb25lbnRJZCA9PT0gVHJhbnNmb3JtQ29tcG9uZW50SWQgJiYgbmV0d29ya1BhcmVudENvbXBvbmVudCkge1xuICAgICAgY29uc3QgcGFyZW50TmV0d29yayA9IG5ldHdvcmtQYXJlbnRDb21wb25lbnQuZ2V0T3JOdWxsKGxvY2FsRW50aXR5SWQpXG4gICAgICBtZXNzYWdlRGF0YSA9IGZpeFRyYW5zZm9ybVBhcmVudChtZXNzYWdlLCBwYXJlbnROZXR3b3JrPy5lbnRpdHlJZClcbiAgICB9XG4gICAgaWYgKGZvcmNlQ29ycmVjdGlvbnMpIHtcbiAgICAgIC8vIFVzZSBBVVRIT1JJVEFUSVZFX1BVVF9DT01QT05FTlQgZm9yIGZvcmNlZCBzdGF0ZSB1cGRhdGVzXG4gICAgICBBdXRob3JpdGF0aXZlUHV0Q29tcG9uZW50T3BlcmF0aW9uLndyaXRlKFxuICAgICAgICBsb2NhbEVudGl0eUlkLFxuICAgICAgICBtZXNzYWdlLnRpbWVzdGFtcCxcbiAgICAgICAgbWVzc2FnZS5jb21wb25lbnRJZCxcbiAgICAgICAgbWVzc2FnZURhdGEsXG4gICAgICAgIGRlc3RpbmF0aW9uQnVmZmVyXG4gICAgICApXG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBDcmR0TWVzc2FnZVR5cGUuQVVUSE9SSVRBVElWRV9QVVRfQ09NUE9ORU5ULFxuICAgICAgICBjb21wb25lbnRJZDogbWVzc2FnZS5jb21wb25lbnRJZCxcbiAgICAgICAgdGltZXN0YW1wOiBtZXNzYWdlLnRpbWVzdGFtcCxcbiAgICAgICAgZGF0YTogbWVzc2FnZURhdGEsXG4gICAgICAgIGVudGl0eUlkOiBsb2NhbEVudGl0eUlkXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIE5vcm1hbCBQVVRfQ09NUE9ORU5UIGNvbnZlcnNpb25cbiAgICAgIFB1dENvbXBvbmVudE9wZXJhdGlvbi53cml0ZShsb2NhbEVudGl0eUlkLCBtZXNzYWdlLnRpbWVzdGFtcCwgbWVzc2FnZS5jb21wb25lbnRJZCwgbWVzc2FnZURhdGEsIGRlc3RpbmF0aW9uQnVmZmVyKVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogQ3JkdE1lc3NhZ2VUeXBlLlBVVF9DT01QT05FTlQsXG4gICAgICAgIGNvbXBvbmVudElkOiBtZXNzYWdlLmNvbXBvbmVudElkLFxuICAgICAgICB0aW1lc3RhbXA6IG1lc3NhZ2UudGltZXN0YW1wLFxuICAgICAgICBkYXRhOiBtZXNzYWdlRGF0YSxcbiAgICAgICAgZW50aXR5SWQ6IGxvY2FsRW50aXR5SWRcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBDcmR0TWVzc2FnZVR5cGUuREVMRVRFX0NPTVBPTkVOVF9ORVRXT1JLKSB7XG4gICAgRGVsZXRlQ29tcG9uZW50LndyaXRlKGxvY2FsRW50aXR5SWQsIG1lc3NhZ2UuY29tcG9uZW50SWQsIG1lc3NhZ2UudGltZXN0YW1wLCBkZXN0aW5hdGlvbkJ1ZmZlcilcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQ3JkdE1lc3NhZ2VUeXBlLkRFTEVURV9DT01QT05FTlQsXG4gICAgICBjb21wb25lbnRJZDogbWVzc2FnZS5jb21wb25lbnRJZCxcbiAgICAgIHRpbWVzdGFtcDogbWVzc2FnZS50aW1lc3RhbXAsXG4gICAgICBlbnRpdHlJZDogbG9jYWxFbnRpdHlJZFxuICAgIH1cbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IENyZHRNZXNzYWdlVHlwZS5ERUxFVEVfRU5USVRZX05FVFdPUkspIHtcbiAgICBEZWxldGVFbnRpdHkud3JpdGUobG9jYWxFbnRpdHlJZCwgZGVzdGluYXRpb25CdWZmZXIpXG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IENyZHRNZXNzYWdlVHlwZS5ERUxFVEVfRU5USVRZLFxuICAgICAgZW50aXR5SWQ6IGxvY2FsRW50aXR5SWRcbiAgICB9XG4gIH1cbiAgdGhyb3cgMVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9jYWxNZXNzYWdlVG9OZXR3b3JrKFxuICBtZXNzYWdlOiBSZWNlaXZlTWVzc2FnZSxcbiAgbmV0d29yazogSU5ldG93cmtFbnRpdHlUeXBlLFxuICBkZXN0aW5hdGlvbkJ1ZmZlcjogQnl0ZUJ1ZmZlclxuKSB7XG4gIGlmIChtZXNzYWdlLnR5cGUgPT09IENyZHRNZXNzYWdlVHlwZS5QVVRfQ09NUE9ORU5UKSB7XG4gICAgUHV0TmV0d29ya0NvbXBvbmVudE9wZXJhdGlvbi53cml0ZShcbiAgICAgIG5ldHdvcmsuZW50aXR5SWQsXG4gICAgICBtZXNzYWdlLnRpbWVzdGFtcCxcbiAgICAgIG1lc3NhZ2UuY29tcG9uZW50SWQsXG4gICAgICBuZXR3b3JrLm5ldHdvcmtJZCxcbiAgICAgIG1lc3NhZ2UuZGF0YSxcbiAgICAgIGRlc3RpbmF0aW9uQnVmZmVyXG4gICAgKVxuICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gQ3JkdE1lc3NhZ2VUeXBlLkRFTEVURV9DT01QT05FTlQpIHtcbiAgICBEZWxldGVDb21wb25lbnROZXR3b3JrLndyaXRlKFxuICAgICAgbmV0d29yay5lbnRpdHlJZCxcbiAgICAgIG1lc3NhZ2UuY29tcG9uZW50SWQsXG4gICAgICBtZXNzYWdlLnRpbWVzdGFtcCxcbiAgICAgIG5ldHdvcmsubmV0d29ya0lkLFxuICAgICAgZGVzdGluYXRpb25CdWZmZXJcbiAgICApXG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBDcmR0TWVzc2FnZVR5cGUuREVMRVRFX0VOVElUWSkge1xuICAgIERlbGV0ZUVudGl0eU5ldHdvcmsud3JpdGUobmV0d29yay5lbnRpdHlJZCwgbmV0d29yay5uZXR3b3JrSWQsIGRlc3RpbmF0aW9uQnVmZmVyKVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaXhUcmFuc2Zvcm1QYXJlbnQobWVzc2FnZTogUmVjZWl2ZU1lc3NhZ2UsIHBhcmVudD86IEVudGl0eSk6IFVpbnQ4QXJyYXkge1xuICBjb25zdCBidWZmZXIgPSBuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcigpXG4gIGNvbnN0IHRyYW5zZm9ybSA9ICdkYXRhJyBpbiBtZXNzYWdlICYmIFRyYW5zZm9ybVNjaGVtYS5kZXNlcmlhbGl6ZShuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcihtZXNzYWdlLmRhdGEpKVxuXG4gIGlmICghdHJhbnNmb3JtKSB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcGFyZW50IHRyYW5zZm9ybScpXG5cbiAgLy8gR2VuZXJhdGUgbmV3IHRyYW5zZm9ybSByYXcgZGF0YSB3aXRoIHRoZSBwYXJlbnRcbiAgY29uc3QgbmV3VHJhbnNmb3JtID0geyAuLi50cmFuc2Zvcm0sIHBhcmVudCB9XG4gIFRyYW5zZm9ybVNjaGVtYS5zZXJpYWxpemUobmV3VHJhbnNmb3JtLCBidWZmZXIpXG4gIHJldHVybiBidWZmZXIudG9CaW5hcnkoKVxufVxuIl19
|
package/server/env-var.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EnvVar provides methods to fetch environment variables from the
|
|
3
|
-
* Server Side Storage service. This module only works when running
|
|
4
|
-
* on server-side scenes.
|
|
5
|
-
*/
|
|
6
|
-
export declare const EnvVar: {
|
|
7
|
-
/**
|
|
8
|
-
* Fetches a specific environment variable by key as plain text.
|
|
9
|
-
*
|
|
10
|
-
* @param key - The name of the environment variable to fetch
|
|
11
|
-
* @returns A promise that resolves to the plain text value, or empty string if not found
|
|
12
|
-
* @throws Error if not running on a server-side scene
|
|
13
|
-
*/
|
|
14
|
-
get(key: string): Promise<string>;
|
|
15
|
-
};
|