@dcl/sdk 7.20.2-22104870534.commit-0df3cc0 → 7.20.2-22169778016.commit-030cbfe
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/atom.d.ts +19 -0
- package/atom.js +83 -0
- package/future.d.ts +8 -0
- package/future.js +26 -0
- package/network/binary-message-bus.d.ts +6 -3
- package/network/binary-message-bus.js +9 -5
- package/network/chunking.d.ts +5 -0
- package/network/chunking.js +38 -0
- package/network/events/implementation.d.ts +93 -0
- package/network/events/implementation.js +230 -0
- package/network/events/index.d.ts +42 -0
- package/network/events/index.js +43 -0
- package/network/events/protocol.d.ts +27 -0
- package/network/events/protocol.js +66 -0
- package/network/events/registry.d.ts +8 -0
- package/network/events/registry.js +3 -0
- package/network/index.d.ts +8 -2
- package/network/index.js +16 -3
- package/network/message-bus-sync.d.ts +14 -1
- package/network/message-bus-sync.js +166 -103
- package/network/server/index.d.ts +14 -0
- package/network/server/index.js +219 -0
- package/network/server/utils.d.ts +18 -0
- package/network/server/utils.js +135 -0
- package/network/state.js +3 -5
- package/package.json +6 -6
- package/server/env-var.d.ts +15 -0
- package/server/env-var.js +31 -0
- package/server/index.d.ts +2 -0
- package/server/index.js +3 -0
- package/server/storage/constants.d.ts +23 -0
- package/server/storage/constants.js +2 -0
- package/server/storage/index.d.ts +22 -0
- package/server/storage/index.js +29 -0
- package/server/storage/player.d.ts +43 -0
- package/server/storage/player.js +92 -0
- package/server/storage/scene.d.ts +38 -0
- package/server/storage/scene.js +90 -0
- package/server/storage-url.d.ts +10 -0
- package/server/storage-url.js +29 -0
- package/server/utils.d.ts +35 -0
- package/server/utils.js +56 -0
- package/src/atom.ts +98 -0
- package/src/future.ts +38 -0
- package/src/network/binary-message-bus.ts +9 -4
- package/src/network/chunking.ts +45 -0
- package/src/network/events/implementation.ts +286 -0
- package/src/network/events/index.ts +48 -0
- package/src/network/events/protocol.ts +94 -0
- package/src/network/events/registry.ts +18 -0
- package/src/network/index.ts +40 -3
- package/src/network/message-bus-sync.ts +180 -110
- package/src/network/server/index.ts +301 -0
- package/src/network/server/utils.ts +189 -0
- package/src/network/state.ts +3 -4
- package/src/server/env-var.ts +36 -0
- package/src/server/index.ts +2 -0
- package/src/server/storage/constants.ts +22 -0
- package/src/server/storage/index.ts +44 -0
- package/src/server/storage/player.ts +156 -0
- package/src/server/storage/scene.ts +149 -0
- package/src/server/storage-url.ts +34 -0
- package/src/server/utils.ts +73 -0
|
@@ -0,0 +1,219 @@
|
|
|
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=
|
|
@@ -0,0 +1,18 @@
|
|
|
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;
|
|
@@ -0,0 +1,135 @@
|
|
|
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/network/state.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReadWriteByteBuffer } from '@dcl/ecs/dist/serialization/ByteBuffer';
|
|
2
2
|
import { CrdtMessageProtocol, CrdtMessageType, PutComponentOperation, PutNetworkComponentOperation, NetworkEntity as _NetworkEntity, VideoEvent, AudioEvent, EngineInfo, GltfContainerLoadingState, PointerEventsResult, RaycastResult, RealmInfo, TweenState, UiDropdown, UiDropdownResult, UiInput, UiInputResult, UiText, UiTransform } from '@dcl/ecs';
|
|
3
|
-
import { LIVEKIT_MAX_SIZE } from '
|
|
3
|
+
import { LIVEKIT_MAX_SIZE } from './server';
|
|
4
4
|
export const NOT_SYNC_COMPONENTS = [
|
|
5
5
|
VideoEvent,
|
|
6
6
|
TweenState,
|
|
@@ -38,8 +38,7 @@ export function engineToCrdt(engine) {
|
|
|
38
38
|
continue;
|
|
39
39
|
}
|
|
40
40
|
itComponentDefinition.dumpCrdtStateToBuffer(crdtBuffer, (entity) => {
|
|
41
|
-
|
|
42
|
-
return isNetworkEntity;
|
|
41
|
+
return NetworkEntity.has(entity);
|
|
43
42
|
});
|
|
44
43
|
}
|
|
45
44
|
let header;
|
|
@@ -57,7 +56,6 @@ export function engineToCrdt(engine) {
|
|
|
57
56
|
networkBuffer.resetBuffer();
|
|
58
57
|
}
|
|
59
58
|
// If the message itself is larger than the limit, we need to handle it specially
|
|
60
|
-
// For now, we'll skip it to prevent infinite loops
|
|
61
59
|
if (messageSize / 1024 > LIVEKIT_MAX_SIZE) {
|
|
62
60
|
console.error(`Message too large (${messageSize} bytes), skipping component ${message.componentId} for entity ${message.entityId}`);
|
|
63
61
|
continue;
|
|
@@ -77,4 +75,4 @@ export function engineToCrdt(engine) {
|
|
|
77
75
|
}
|
|
78
76
|
return chunks;
|
|
79
77
|
}
|
|
80
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
78
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbmV0d29yay9zdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQTtBQUM1RSxPQUFPLEVBRUwsbUJBQW1CLEVBQ25CLGVBQWUsRUFFZixxQkFBcUIsRUFDckIsNEJBQTRCLEVBRTVCLGFBQWEsSUFBSSxjQUFjLEVBRS9CLFVBQVUsRUFDVixVQUFVLEVBQ1YsVUFBVSxFQUNWLHlCQUF5QixFQUN6QixtQkFBbUIsRUFDbkIsYUFBYSxFQUNiLFNBQVMsRUFDVCxVQUFVLEVBQ1YsVUFBVSxFQUNWLGdCQUFnQixFQUNoQixPQUFPLEVBQ1AsYUFBYSxFQUNiLE1BQU0sRUFDTixXQUFXLEVBRVosTUFBTSxVQUFVLENBQUE7QUFDakIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sVUFBVSxDQUFBO0FBRTNDLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFtQztJQUNqRSxVQUFVO0lBQ1YsVUFBVTtJQUNWLFVBQVU7SUFDVixVQUFVO0lBQ1YseUJBQXlCO0lBQ3pCLG1CQUFtQjtJQUNuQixhQUFhO0lBQ2IsU0FBUztJQUNULFVBQVU7SUFDVixnQkFBZ0I7SUFDaEIsT0FBTztJQUNQLGFBQWE7SUFDYixXQUFXO0lBQ1gsTUFBTTtDQUNQLENBQUE7QUFFRCxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQTtBQUNwRixNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBYTtJQUNqRCxxQkFBcUIsQ0FBQyx5RkFBeUY7Q0FDaEgsQ0FBQTtBQUVELE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxTQUF1QztJQUN6RSxPQUFPLENBQUMsQ0FDTix1QkFBdUIsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFdB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RSxHQUFHLENBQUMsRUFBRTtRQUMxQyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFBO0tBQ3RDO0lBRUQsT0FBTyxNQUFNLENBQUE7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUmVhZFdyaXRlQnl0ZUJ1ZmZlciB9IGZyb20gJ0BkY2wvZWNzL2Rpc3Qvc2VyaWFsaXphdGlvbi9CeXRlQnVmZmVyJ1xuaW1wb3J0IHtcbiAgQ3JkdE1lc3NhZ2VIZWFkZXIsXG4gIENyZHRNZXNzYWdlUHJvdG9jb2wsXG4gIENyZHRNZXNzYWdlVHlwZSxcbiAgSUVuZ2luZSxcbiAgUHV0Q29tcG9uZW50T3BlcmF0aW9uLFxuICBQdXROZXR3b3JrQ29tcG9uZW50T3BlcmF0aW9uLFxuICBTeW5jQ29tcG9uZW50cyBhcyBfU3luY0NvbXBvbmVudHMsXG4gIE5ldHdvcmtFbnRpdHkgYXMgX05ldHdvcmtFbnRpdHksXG4gIElOZXRvd3JrRW50aXR5LFxuICBWaWRlb0V2ZW50LFxuICBBdWRpb0V2ZW50LFxuICBFbmdpbmVJbmZvLFxuICBHbHRmQ29udGFpbmVyTG9hZGluZ1N0YXRlLFxuICBQb2ludGVyRXZlbnRzUmVzdWx0LFxuICBSYXljYXN0UmVzdWx0LFxuICBSZWFsbUluZm8sXG4gIFR3ZWVuU3RhdGUsXG4gIFVpRHJvcGRvd24sXG4gIFVpRHJvcGRvd25SZXN1bHQsXG4gIFVpSW5wdXQsXG4gIFVpSW5wdXRSZXN1bHQsXG4gIFVpVGV4dCxcbiAgVWlUcmFuc2Zvcm0sXG4gIENvbXBvbmVudERlZmluaXRpb25cbn0gZnJvbSAnQGRjbC9lY3MnXG5pbXBvcnQgeyBMSVZFS0lUX01BWF9TSVpFIH0gZnJvbSAnLi9zZXJ2ZXInXG5cbmV4cG9ydCBjb25zdCBOT1RfU1lOQ19DT01QT05FTlRTOiBDb21wb25lbnREZWZpbml0aW9uPHVua25vd24+W10gPSBbXG4gIFZpZGVvRXZlbnQsXG4gIFR3ZWVuU3RhdGUsXG4gIEF1ZGlvRXZlbnQsXG4gIEVuZ2luZUluZm8sXG4gIEdsdGZDb250YWluZXJMb2FkaW5nU3RhdGUsXG4gIFBvaW50ZXJFdmVudHNSZXN1bHQsXG4gIFJheWNhc3RSZXN1bHQsXG4gIFJlYWxtSW5mbyxcbiAgVWlEcm9wZG93bixcbiAgVWlEcm9wZG93blJlc3VsdCxcbiAgVWlJbnB1dCxcbiAgVWlJbnB1dFJlc3VsdCxcbiAgVWlUcmFuc2Zvcm0sXG4gIFVpVGV4dFxuXVxuXG5leHBvcnQgY29uc3QgTk9UX1NZTkNfQ09NUE9ORU5UU19JRFMgPSBOT1RfU1lOQ19DT01QT05FTlRTLm1hcCgoJCkgPT4gJC5jb21wb25lbnRJZClcbmV4cG9ydCBjb25zdCBOT1RfU1lOQ19DT01QT05FTlRTX05BTUVTOiBzdHJpbmdbXSA9IFtcbiAgJ2Fzc2V0LXBhY2tzOjpTY3JpcHQnIC8vIENvbXBvbmVudE5hbWUgZnJvbTogaHR0cHM6Ly9naXRodWIuY29tL2RlY2VudHJhbGFuZC9hc3NldC1wYWNrcy9ibG9iL21haW4vc3JjL2VudW1zLnRzXG5dXG5cbmV4cG9ydCBmdW5jdGlvbiBzaG91bGRTeW5jQ29tcG9uZW50KGNvbXBvbmVudDogQ29tcG9uZW50RGVmaW5pdGlvbjx1bmtub3duPik6IGJvb2xlYW4ge1xuICByZXR1cm4gIShcbiAgICBOT1RfU1lOQ19DT01QT05FTlRTX0lEUy5pbmNsdWRlcyhjb21wb25lbnQuY29tcG9uZW50SWQpIHx8XG4gICAgTk9UX1NZTkNfQ09NUE9ORU5UU19OQU1FUy5pbmNsdWRlcyhjb21wb25lbnQuY29tcG9uZW50TmFtZSlcbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGVzeW5jZWRDb21wb25lbnRzKGVuZ2luZTogSUVuZ2luZSk6IENvbXBvbmVudERlZmluaXRpb248dW5rbm93bj5bXSB7XG4gIHJldHVybiBbLi4uTk9UX1NZTkNfQ09NUE9ORU5UUywgLi4uTk9UX1NZTkNfQ09NUE9ORU5UU19OQU1FUy5tYXAoKCQpID0+IGVuZ2luZS5nZXRDb21wb25lbnRPck51bGwoJCkpXS5maWx0ZXIoXG4gICAgQm9vbGVhblxuICApIGFzIENvbXBvbmVudERlZmluaXRpb248dW5rbm93bj5bXVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5naW5lVG9DcmR0KGVuZ2luZTogSUVuZ2luZSk6IFVpbnQ4QXJyYXlbXSB7XG4gIGNvbnN0IGNyZHRCdWZmZXIgPSBuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcigpXG4gIGNvbnN0IG5ldHdvcmtCdWZmZXIgPSBuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcigpXG4gIGNvbnN0IE5ldHdvcmtFbnRpdHkgPSBlbmdpbmUuZ2V0Q29tcG9uZW50KF9OZXR3b3JrRW50aXR5LmNvbXBvbmVudElkKSBhcyBJTmV0b3dya0VudGl0eVxuICBjb25zdCBjaHVua3M6IFVpbnQ4QXJyYXlbXSA9IFtdXG5cbiAgZm9yIChjb25zdCBpdENvbXBvbmVudERlZmluaXRpb24gb2YgZW5naW5lLmNvbXBvbmVudHNJdGVyKCkpIHtcbiAgICBpZiAoIXNob3VsZFN5bmNDb21wb25lbnQoaXRDb21wb25lbnREZWZpbml0aW9uKSkge1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICBpdENvbXBvbmVudERlZmluaXRpb24uZHVtcENyZHRTdGF0ZVRvQnVmZmVyKGNyZHRCdWZmZXIsIChlbnRpdHkpID0+IHtcbiAgICAgIHJldHVybiBOZXR3b3JrRW50aXR5LmhhcyhlbnRpdHkpXG4gICAgfSlcbiAgfVxuXG4gIGxldCBoZWFkZXI6IENyZHRNZXNzYWdlSGVhZGVyIHwgbnVsbFxuICB3aGlsZSAoKGhlYWRlciA9IENyZHRNZXNzYWdlUHJvdG9jb2wuZ2V0SGVhZGVyKGNyZHRCdWZmZXIpKSkge1xuICAgIGlmIChoZWFkZXIudHlwZSA9PT0gQ3JkdE1lc3NhZ2VUeXBlLlBVVF9DT01QT05FTlQpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBQdXRDb21wb25lbnRPcGVyYXRpb24ucmVhZChjcmR0QnVmZmVyKSFcbiAgICAgIGNvbnN0IG5ldHdvcmtFbnRpdHkgPSBOZXR3b3JrRW50aXR5LmdldE9yTnVsbChtZXNzYWdlLmVudGl0eUlkKVxuXG4gICAgICAvLyBDaGVjayBpZiBhZGRpbmcgdGhpcyBtZXNzYWdlIHdvdWxkIGV4Y2VlZCB0aGUgc2l6ZSBsaW1pdFxuICAgICAgY29uc3QgY3VycmVudEJ1ZmZlclNpemUgPSBuZXR3b3JrQnVmZmVyLnRvQmluYXJ5KCkuYnl0ZUxlbmd0aFxuICAgICAgY29uc3QgbWVzc2FnZVNpemUgPSBtZXNzYWdlLmRhdGEuYnl0ZUxlbmd0aFxuXG4gICAgICBpZiAoKGN1cnJlbnRCdWZmZXJTaXplICsgbWVzc2FnZVNpemUpIC8gMTAyNCA+IExJVkVLSVRfTUFYX1NJWkUpIHtcbiAgICAgICAgLy8gSWYgdGhlIGN1cnJlbnQgYnVmZmVyIGhhcyBjb250ZW50LCBzYXZlIGl0IGFzIGEgY2h1bmtcbiAgICAgICAgaWYgKGN1cnJlbnRCdWZmZXJTaXplID4gMCkge1xuICAgICAgICAgIGNodW5rcy5wdXNoKG5ldHdvcmtCdWZmZXIudG9Db3BpZWRCaW5hcnkoKSlcbiAgICAgICAgICBuZXR3b3JrQnVmZmVyLnJlc2V0QnVmZmVyKClcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZSBtZXNzYWdlIGl0c2VsZiBpcyBsYXJnZXIgdGhhbiB0aGUgbGltaXQsIHdlIG5lZWQgdG8gaGFuZGxlIGl0IHNwZWNpYWxseVxuICAgICAgICBpZiAobWVzc2FnZVNpemUgLyAxMDI0ID4gTElWRUtJVF9NQVhfU0laRSkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICBgTWVzc2FnZSB0b28gbGFyZ2UgKCR7bWVzc2FnZVNpemV9IGJ5dGVzKSwgc2tpcHBpbmcgY29tcG9uZW50ICR7bWVzc2FnZS5jb21wb25lbnRJZH0gZm9yIGVudGl0eSAke21lc3NhZ2UuZW50aXR5SWR9YFxuICAgICAgICAgIClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChuZXR3b3JrRW50aXR5KSB7XG4gICAgICAgIFB1dE5ldHdvcmtDb21wb25lbnRPcGVyYXRpb24ud3JpdGUoXG4gICAgICAgICAgbmV0d29ya0VudGl0eS5lbnRpdHlJZCxcbiAgICAgICAgICBtZXNzYWdlLnRpbWVzdGFtcCxcbiAgICAgICAgICBtZXNzYWdlLmNvbXBvbmVudElkLFxuICAgICAgICAgIG5ldHdvcmtFbnRpdHkubmV0d29ya0lkLFxuICAgICAgICAgIG1lc3NhZ2UuZGF0YSxcbiAgICAgICAgICBuZXR3b3JrQnVmZmVyXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY3JkdEJ1ZmZlci5pbmNyZW1lbnRSZWFkT2Zmc2V0KGhlYWRlci5sZW5ndGgpXG4gICAgfVxuICB9XG5cbiAgLy8gQWRkIGFueSByZW1haW5pbmcgZGF0YSBhcyB0aGUgZmluYWwgY2h1bmtcbiAgaWYgKG5ldHdvcmtCdWZmZXIuY3VycmVudFdyaXRlT2Zmc2V0KCkgPiAwKSB7XG4gICAgY2h1bmtzLnB1c2gobmV0d29ya0J1ZmZlci50b0JpbmFyeSgpKVxuICB9XG5cbiAgcmV0dXJuIGNodW5rc1xufVxuIl19
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl/sdk",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "7.20.2-
|
|
4
|
+
"version": "7.20.2-22169778016.commit-030cbfe",
|
|
5
5
|
"author": "Decentraland",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@dcl/ecs": "7.20.2-
|
|
7
|
+
"@dcl/ecs": "7.20.2-22169778016.commit-030cbfe",
|
|
8
8
|
"@dcl/ecs-math": "2.1.0",
|
|
9
9
|
"@dcl/explorer": "1.0.164509-20240802172549.commit-fb95b9b",
|
|
10
|
-
"@dcl/js-runtime": "7.20.2-
|
|
11
|
-
"@dcl/react-ecs": "7.20.2-
|
|
12
|
-
"@dcl/sdk-commands": "7.20.2-
|
|
10
|
+
"@dcl/js-runtime": "7.20.2-22169778016.commit-030cbfe",
|
|
11
|
+
"@dcl/react-ecs": "7.20.2-22169778016.commit-030cbfe",
|
|
12
|
+
"@dcl/sdk-commands": "7.20.2-22169778016.commit-030cbfe",
|
|
13
13
|
"text-encoding": "0.7.0"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [],
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
},
|
|
36
36
|
"types": "./index.d.ts",
|
|
37
37
|
"typings": "./index.d.ts",
|
|
38
|
-
"commit": "
|
|
38
|
+
"commit": "030cbfee8a40495d9916ade20280282e63e3cc8b"
|
|
39
39
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getStorageServerUrl } from './storage-url';
|
|
2
|
+
import { assertIsServer, wrapSignedFetch } from './utils';
|
|
3
|
+
const MODULE_NAME = 'EnvVar';
|
|
4
|
+
/**
|
|
5
|
+
* EnvVar provides methods to fetch environment variables from the
|
|
6
|
+
* Server Side Storage service. This module only works when running
|
|
7
|
+
* on server-side scenes.
|
|
8
|
+
*/
|
|
9
|
+
export const EnvVar = {
|
|
10
|
+
/**
|
|
11
|
+
* Fetches a specific environment variable by key as plain text.
|
|
12
|
+
*
|
|
13
|
+
* @param key - The name of the environment variable to fetch
|
|
14
|
+
* @returns A promise that resolves to the plain text value, or empty string if not found
|
|
15
|
+
* @throws Error if not running on a server-side scene
|
|
16
|
+
*/
|
|
17
|
+
async get(key) {
|
|
18
|
+
assertIsServer(MODULE_NAME);
|
|
19
|
+
const baseUrl = await getStorageServerUrl();
|
|
20
|
+
const url = `${baseUrl}/env/${encodeURIComponent(key)}`;
|
|
21
|
+
const [error, data] = await wrapSignedFetch({
|
|
22
|
+
url
|
|
23
|
+
});
|
|
24
|
+
if (error) {
|
|
25
|
+
console.error(`Failed to fetch environment variable '${key}': ${error}`);
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
return data?.value ?? '';
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52LXZhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zZXJ2ZXIvZW52LXZhci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDbkQsT0FBTyxFQUFFLGNBQWMsRUFBRSxlQUFlLEVBQUUsTUFBTSxTQUFTLENBQUE7QUFFekQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFBO0FBRTVCOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxNQUFNLEdBQUc7SUFDcEI7Ozs7OztPQU1HO0lBQ0gsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFXO1FBQ25CLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUUzQixNQUFNLE9BQU8sR0FBRyxNQUFNLG1CQUFtQixFQUFFLENBQUE7UUFDM0MsTUFBTSxHQUFHLEdBQUcsR0FBRyxPQUFPLFFBQVEsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQTtRQUV2RCxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLE1BQU0sZUFBZSxDQUFvQjtZQUM3RCxHQUFHO1NBQ0osQ0FBQyxDQUFBO1FBRUYsSUFBSSxLQUFLLEVBQUU7WUFDVCxPQUFPLENBQUMsS0FBSyxDQUFDLHlDQUF5QyxHQUFHLE1BQU0sS0FBSyxFQUFFLENBQUMsQ0FBQTtZQUN4RSxPQUFPLEVBQUUsQ0FBQTtTQUNWO1FBRUQsT0FBTyxJQUFJLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQTtJQUMxQixDQUFDO0NBQ0YsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGdldFN0b3JhZ2VTZXJ2ZXJVcmwgfSBmcm9tICcuL3N0b3JhZ2UtdXJsJ1xuaW1wb3J0IHsgYXNzZXJ0SXNTZXJ2ZXIsIHdyYXBTaWduZWRGZXRjaCB9IGZyb20gJy4vdXRpbHMnXG5cbmNvbnN0IE1PRFVMRV9OQU1FID0gJ0VudlZhcidcblxuLyoqXG4gKiBFbnZWYXIgcHJvdmlkZXMgbWV0aG9kcyB0byBmZXRjaCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgZnJvbSB0aGVcbiAqIFNlcnZlciBTaWRlIFN0b3JhZ2Ugc2VydmljZS4gVGhpcyBtb2R1bGUgb25seSB3b3JrcyB3aGVuIHJ1bm5pbmdcbiAqIG9uIHNlcnZlci1zaWRlIHNjZW5lcy5cbiAqL1xuZXhwb3J0IGNvbnN0IEVudlZhciA9IHtcbiAgLyoqXG4gICAqIEZldGNoZXMgYSBzcGVjaWZpYyBlbnZpcm9ubWVudCB2YXJpYWJsZSBieSBrZXkgYXMgcGxhaW4gdGV4dC5cbiAgICpcbiAgICogQHBhcmFtIGtleSAtIFRoZSBuYW1lIG9mIHRoZSBlbnZpcm9ubWVudCB2YXJpYWJsZSB0byBmZXRjaFxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcGxhaW4gdGV4dCB2YWx1ZSwgb3IgZW1wdHkgc3RyaW5nIGlmIG5vdCBmb3VuZFxuICAgKiBAdGhyb3dzIEVycm9yIGlmIG5vdCBydW5uaW5nIG9uIGEgc2VydmVyLXNpZGUgc2NlbmVcbiAgICovXG4gIGFzeW5jIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgYXNzZXJ0SXNTZXJ2ZXIoTU9EVUxFX05BTUUpXG5cbiAgICBjb25zdCBiYXNlVXJsID0gYXdhaXQgZ2V0U3RvcmFnZVNlcnZlclVybCgpXG4gICAgY29uc3QgdXJsID0gYCR7YmFzZVVybH0vZW52LyR7ZW5jb2RlVVJJQ29tcG9uZW50KGtleSl9YFxuXG4gICAgY29uc3QgW2Vycm9yLCBkYXRhXSA9IGF3YWl0IHdyYXBTaWduZWRGZXRjaDx7IHZhbHVlOiBzdHJpbmcgfT4oe1xuICAgICAgdXJsXG4gICAgfSlcblxuICAgIGlmIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcihgRmFpbGVkIHRvIGZldGNoIGVudmlyb25tZW50IHZhcmlhYmxlICcke2tleX0nOiAke2Vycm9yfWApXG4gICAgICByZXR1cm4gJydcbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YT8udmFsdWUgPz8gJydcbiAgfVxufVxuIl19
|
package/server/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { EnvVar } from './env-var';
|
|
2
|
+
export { Storage } from './storage';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvc2VydmVyL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDbEMsT0FBTyxFQUFFLE9BQU8sRUFBOEUsTUFBTSxXQUFXLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyBFbnZWYXIgfSBmcm9tICcuL2Vudi12YXInXG5leHBvcnQgeyBTdG9yYWdlLCBJU3RvcmFnZSwgSVNjZW5lU3RvcmFnZSwgSVBsYXllclN0b3JhZ2UsIEdldFZhbHVlc09wdGlvbnMsIEdldFZhbHVlc1Jlc3VsdCB9IGZyb20gJy4vc3RvcmFnZSdcbiJdfQ==
|