@venturekit/runtime 0.0.0-dev.20260307234057
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/LICENSE +191 -0
- package/dist/context.d.ts +86 -0
- package/dist/context.js +76 -0
- package/dist/errors.d.ts +80 -0
- package/dist/errors.js +134 -0
- package/dist/handler.d.ts +71 -0
- package/dist/handler.js +176 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +53 -0
- package/dist/logger.d.ts +72 -0
- package/dist/logger.js +105 -0
- package/dist/middleware.d.ts +46 -0
- package/dist/middleware.js +147 -0
- package/dist/response.d.ts +75 -0
- package/dist/response.js +107 -0
- package/dist/ws.d.ts +138 -0
- package/dist/ws.js +277 -0
- package/package.json +61 -0
package/dist/ws.js
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WebSocket Connection Store
|
|
4
|
+
*
|
|
5
|
+
* DynamoDB-backed connection management for API Gateway WebSocket APIs.
|
|
6
|
+
*
|
|
7
|
+
* Authentication:
|
|
8
|
+
* Two-phase auth — the client connects without credentials, then sends
|
|
9
|
+
* an { action: "auth", token: "<jwt>" } message over the encrypted channel.
|
|
10
|
+
* The connection is stored as unauthenticated on $connect and upgraded
|
|
11
|
+
* to authenticated via connectionStore.authenticate().
|
|
12
|
+
* This avoids leaking JWTs in query strings, server logs, and access logs.
|
|
13
|
+
*
|
|
14
|
+
* Multi-tenancy:
|
|
15
|
+
* If enabled, each connection stores a tenantId alongside userId.
|
|
16
|
+
* Use sendToTenant() to broadcast within a tenant boundary.
|
|
17
|
+
*
|
|
18
|
+
* API:
|
|
19
|
+
* connectionStore.save(connectionId) — $connect (unauthenticated)
|
|
20
|
+
* connectionStore.authenticate(connectionId, metadata) — after JWT verification
|
|
21
|
+
* connectionStore.remove(connectionId) — $disconnect
|
|
22
|
+
* connectionStore.get(connectionId) — single connection
|
|
23
|
+
* connectionStore.getAll() — all connections
|
|
24
|
+
* connectionStore.getByUser(userId) — by user (GSI)
|
|
25
|
+
* connectionStore.getByTenant(tenantId) — by tenant (GSI)
|
|
26
|
+
* connectionStore.postToConnection(domain, stage, id, data) — send to one
|
|
27
|
+
* connectionStore.sendToUser(domain, stage, userId, data) — send to all user sessions
|
|
28
|
+
* connectionStore.sendToTenant(domain, stage, tenantId, data) — broadcast within tenant
|
|
29
|
+
* connectionStore.broadcast(domain, stage, data) — broadcast to all
|
|
30
|
+
*
|
|
31
|
+
* Environment variables:
|
|
32
|
+
* CONNECTIONS_TABLE — DynamoDB table name (required)
|
|
33
|
+
*
|
|
34
|
+
* DynamoDB table schema:
|
|
35
|
+
* Partition key: connectionId (String)
|
|
36
|
+
* TTL attribute: ttl
|
|
37
|
+
* GSI: userId-index (partition key: userId)
|
|
38
|
+
* GSI: tenantId-index (partition key: tenantId) — only if multi-tenancy enabled
|
|
39
|
+
*/
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.connectionStore = void 0;
|
|
42
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
43
|
+
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
44
|
+
const client_apigatewaymanagementapi_1 = require("@aws-sdk/client-apigatewaymanagementapi");
|
|
45
|
+
const DEFAULT_TTL_SECONDS = 7200; // 2 hours
|
|
46
|
+
const AUTH_GRACE_PERIOD_SECONDS = 30; // unauthenticated connections expire quickly
|
|
47
|
+
function getTableName() {
|
|
48
|
+
const table = process.env.CONNECTIONS_TABLE;
|
|
49
|
+
if (!table) {
|
|
50
|
+
throw new Error('CONNECTIONS_TABLE environment variable is not set');
|
|
51
|
+
}
|
|
52
|
+
return table;
|
|
53
|
+
}
|
|
54
|
+
let _ddb = null;
|
|
55
|
+
function ddb() {
|
|
56
|
+
if (!_ddb) {
|
|
57
|
+
_ddb = lib_dynamodb_1.DynamoDBDocumentClient.from(new client_dynamodb_1.DynamoDBClient({}));
|
|
58
|
+
}
|
|
59
|
+
return _ddb;
|
|
60
|
+
}
|
|
61
|
+
function encode(data) {
|
|
62
|
+
return new TextEncoder().encode(JSON.stringify(data));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Deliver data to a list of connections in parallel.
|
|
66
|
+
* Removes stale connections automatically.
|
|
67
|
+
* Returns count of successful deliveries.
|
|
68
|
+
*/
|
|
69
|
+
async function deliverToMany(store, domainName, stage, connections, data) {
|
|
70
|
+
let delivered = 0;
|
|
71
|
+
const results = await Promise.allSettled(connections
|
|
72
|
+
.filter((c) => c.authenticated)
|
|
73
|
+
.map((c) => store.postToConnection(domainName, stage, c.connectionId, data)));
|
|
74
|
+
for (const result of results) {
|
|
75
|
+
if (result.status === 'fulfilled' && result.value)
|
|
76
|
+
delivered++;
|
|
77
|
+
}
|
|
78
|
+
return delivered;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* WebSocket connection store backed by DynamoDB.
|
|
82
|
+
*
|
|
83
|
+
* Two-phase authentication flow:
|
|
84
|
+
*
|
|
85
|
+
* 1. $connect handler:
|
|
86
|
+
* ```typescript
|
|
87
|
+
* await connectionStore.save(connectionId);
|
|
88
|
+
* // Connection is unauthenticated, TTL = 30s
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* 2. Client sends auth message over the encrypted WebSocket:
|
|
92
|
+
* ```json
|
|
93
|
+
* { "action": "auth", "token": "<jwt>" }
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* 3. $default handler verifies JWT, then:
|
|
97
|
+
* ```typescript
|
|
98
|
+
* await connectionStore.authenticate(connectionId, { userId, tenantId, email });
|
|
99
|
+
* // Connection is now authenticated, TTL extended to 2h
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
exports.connectionStore = {
|
|
103
|
+
/**
|
|
104
|
+
* Save a new connection on $connect.
|
|
105
|
+
* The connection is unauthenticated with a short TTL.
|
|
106
|
+
* The client must send an auth message to upgrade.
|
|
107
|
+
*/
|
|
108
|
+
async save(connectionId) {
|
|
109
|
+
const now = Date.now();
|
|
110
|
+
await ddb().send(new lib_dynamodb_1.PutCommand({
|
|
111
|
+
TableName: getTableName(),
|
|
112
|
+
Item: {
|
|
113
|
+
connectionId,
|
|
114
|
+
authenticated: false,
|
|
115
|
+
connectedAt: now,
|
|
116
|
+
ttl: Math.floor(now / 1000) + AUTH_GRACE_PERIOD_SECONDS,
|
|
117
|
+
},
|
|
118
|
+
}));
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* Authenticate a connection after JWT verification.
|
|
122
|
+
* Updates the record with user metadata and extends the TTL.
|
|
123
|
+
*
|
|
124
|
+
* @param connectionId — the connection to authenticate
|
|
125
|
+
* @param metadata — must include userId, optionally tenantId, email, etc.
|
|
126
|
+
*/
|
|
127
|
+
async authenticate(connectionId, metadata) {
|
|
128
|
+
const now = Date.now();
|
|
129
|
+
const { userId, tenantId, email, ...extra } = metadata;
|
|
130
|
+
const updateParts = [
|
|
131
|
+
'authenticated = :auth',
|
|
132
|
+
'userId = :uid',
|
|
133
|
+
'authenticatedAt = :authAt',
|
|
134
|
+
'ttl = :ttl',
|
|
135
|
+
];
|
|
136
|
+
const values = {
|
|
137
|
+
':auth': true,
|
|
138
|
+
':uid': userId,
|
|
139
|
+
':authAt': now,
|
|
140
|
+
':ttl': Math.floor(now / 1000) + DEFAULT_TTL_SECONDS,
|
|
141
|
+
};
|
|
142
|
+
if (tenantId) {
|
|
143
|
+
updateParts.push('tenantId = :tid');
|
|
144
|
+
values[':tid'] = tenantId;
|
|
145
|
+
}
|
|
146
|
+
if (email) {
|
|
147
|
+
updateParts.push('email = :email');
|
|
148
|
+
values[':email'] = email;
|
|
149
|
+
}
|
|
150
|
+
// Store any extra metadata fields
|
|
151
|
+
let extraIdx = 0;
|
|
152
|
+
for (const [key, val] of Object.entries(extra)) {
|
|
153
|
+
const placeholder = `:extra${extraIdx}`;
|
|
154
|
+
updateParts.push(`#extra${extraIdx} = ${placeholder}`);
|
|
155
|
+
values[placeholder] = val;
|
|
156
|
+
extraIdx++;
|
|
157
|
+
}
|
|
158
|
+
const names = {};
|
|
159
|
+
for (let i = 0; i < extraIdx; i++) {
|
|
160
|
+
names[`#extra${i}`] = Object.keys(extra)[i];
|
|
161
|
+
}
|
|
162
|
+
await ddb().send(new lib_dynamodb_1.UpdateCommand({
|
|
163
|
+
TableName: getTableName(),
|
|
164
|
+
Key: { connectionId },
|
|
165
|
+
UpdateExpression: `SET ${updateParts.join(', ')}`,
|
|
166
|
+
ExpressionAttributeValues: values,
|
|
167
|
+
...(extraIdx > 0 ? { ExpressionAttributeNames: names } : {}),
|
|
168
|
+
}));
|
|
169
|
+
},
|
|
170
|
+
/**
|
|
171
|
+
* Remove a connection on $disconnect.
|
|
172
|
+
*/
|
|
173
|
+
async remove(connectionId) {
|
|
174
|
+
await ddb().send(new lib_dynamodb_1.DeleteCommand({
|
|
175
|
+
TableName: getTableName(),
|
|
176
|
+
Key: { connectionId },
|
|
177
|
+
}));
|
|
178
|
+
},
|
|
179
|
+
/**
|
|
180
|
+
* Get a single connection record.
|
|
181
|
+
*/
|
|
182
|
+
async get(connectionId) {
|
|
183
|
+
const result = await ddb().send(new lib_dynamodb_1.GetCommand({
|
|
184
|
+
TableName: getTableName(),
|
|
185
|
+
Key: { connectionId },
|
|
186
|
+
}));
|
|
187
|
+
return result.Item ?? null;
|
|
188
|
+
},
|
|
189
|
+
/**
|
|
190
|
+
* Get all authenticated connections.
|
|
191
|
+
* For large-scale apps, prefer getByUser() or getByTenant().
|
|
192
|
+
*/
|
|
193
|
+
async getAll() {
|
|
194
|
+
const result = await ddb().send(new lib_dynamodb_1.ScanCommand({
|
|
195
|
+
TableName: getTableName(),
|
|
196
|
+
FilterExpression: 'authenticated = :auth',
|
|
197
|
+
ExpressionAttributeValues: { ':auth': true },
|
|
198
|
+
}));
|
|
199
|
+
return (result.Items ?? []);
|
|
200
|
+
},
|
|
201
|
+
/**
|
|
202
|
+
* Get all connections for a specific user.
|
|
203
|
+
* A user can have multiple active connections (e.g. multiple tabs/devices).
|
|
204
|
+
* Requires GSI: userId-index (partition key: userId).
|
|
205
|
+
*/
|
|
206
|
+
async getByUser(userId) {
|
|
207
|
+
const result = await ddb().send(new lib_dynamodb_1.QueryCommand({
|
|
208
|
+
TableName: getTableName(),
|
|
209
|
+
IndexName: 'userId-index',
|
|
210
|
+
KeyConditionExpression: 'userId = :uid',
|
|
211
|
+
ExpressionAttributeValues: { ':uid': userId },
|
|
212
|
+
}));
|
|
213
|
+
return (result.Items ?? []);
|
|
214
|
+
},
|
|
215
|
+
/**
|
|
216
|
+
* Get all connections for a specific tenant.
|
|
217
|
+
* Requires GSI: tenantId-index (partition key: tenantId).
|
|
218
|
+
*/
|
|
219
|
+
async getByTenant(tenantId) {
|
|
220
|
+
const result = await ddb().send(new lib_dynamodb_1.QueryCommand({
|
|
221
|
+
TableName: getTableName(),
|
|
222
|
+
IndexName: 'tenantId-index',
|
|
223
|
+
KeyConditionExpression: 'tenantId = :tid',
|
|
224
|
+
ExpressionAttributeValues: { ':tid': tenantId },
|
|
225
|
+
}));
|
|
226
|
+
return (result.Items ?? []);
|
|
227
|
+
},
|
|
228
|
+
/**
|
|
229
|
+
* Send data to a specific connection via API Gateway Management API.
|
|
230
|
+
* Automatically cleans up stale connections (GoneException).
|
|
231
|
+
* Returns true if sent, false if the connection was stale and removed.
|
|
232
|
+
*/
|
|
233
|
+
async postToConnection(domainName, stage, connectionId, data) {
|
|
234
|
+
const apigw = new client_apigatewaymanagementapi_1.ApiGatewayManagementApiClient({
|
|
235
|
+
endpoint: `https://${domainName}/${stage}`,
|
|
236
|
+
});
|
|
237
|
+
try {
|
|
238
|
+
await apigw.send(new client_apigatewaymanagementapi_1.PostToConnectionCommand({
|
|
239
|
+
ConnectionId: connectionId,
|
|
240
|
+
Data: encode(data),
|
|
241
|
+
}));
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
if (err instanceof client_apigatewaymanagementapi_1.GoneException) {
|
|
246
|
+
await this.remove(connectionId);
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
throw err;
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
/**
|
|
253
|
+
* Send data to all connections belonging to a specific user.
|
|
254
|
+
* Returns the number of connections that received the message.
|
|
255
|
+
*/
|
|
256
|
+
async sendToUser(domainName, stage, userId, data) {
|
|
257
|
+
const connections = await this.getByUser(userId);
|
|
258
|
+
return deliverToMany(this, domainName, stage, connections, data);
|
|
259
|
+
},
|
|
260
|
+
/**
|
|
261
|
+
* Send data to all connections within a specific tenant.
|
|
262
|
+
* Returns the number of connections that received the message.
|
|
263
|
+
*/
|
|
264
|
+
async sendToTenant(domainName, stage, tenantId, data) {
|
|
265
|
+
const connections = await this.getByTenant(tenantId);
|
|
266
|
+
return deliverToMany(this, domainName, stage, connections, data);
|
|
267
|
+
},
|
|
268
|
+
/**
|
|
269
|
+
* Broadcast data to all authenticated connections.
|
|
270
|
+
* Returns the number of clients that received the message.
|
|
271
|
+
*/
|
|
272
|
+
async broadcast(domainName, stage, data) {
|
|
273
|
+
const connections = await this.getAll();
|
|
274
|
+
return deliverToMany(this, domainName, stage, connections, data);
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUNHOzs7QUFFSCw4REFBMEQ7QUFDMUQsd0RBUStCO0FBQy9CLDRGQUlpRDtBQXFCakQsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVO0FBQzVDLE1BQU0seUJBQXlCLEdBQUcsRUFBRSxDQUFDLENBQUMsNkNBQTZDO0FBRW5GLFNBQVMsWUFBWTtJQUNuQixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDO0lBQzVDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBRUQsSUFBSSxJQUFJLEdBQWtDLElBQUksQ0FBQztBQUUvQyxTQUFTLEdBQUc7SUFDVixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDVixJQUFJLEdBQUcscUNBQXNCLENBQUMsSUFBSSxDQUFDLElBQUksZ0NBQWMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRCxTQUFTLE1BQU0sQ0FBQyxJQUFhO0lBQzNCLE9BQU8sSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ3hELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLGFBQWEsQ0FDMUIsS0FBNkIsRUFDN0IsVUFBa0IsRUFDbEIsS0FBYSxFQUNiLFdBQStCLEVBQy9CLElBQWE7SUFFYixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFDbEIsTUFBTSxPQUFPLEdB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QUssRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxTQUFTLENBQUMsVUFBa0IsRUFBRSxLQUFhLEVBQUUsSUFBYTtRQUM5RCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN4QyxPQUFPLGFBQWEsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDbkUsQ0FBQztDQUNGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFdlYlNvY2tldCBDb25uZWN0aW9uIFN0b3JlXG4gKiBcbiAqIER5bmFtb0RCLWJhY2tlZCBjb25uZWN0aW9uIG1hbmFnZW1lbnQgZm9yIEFQSSBHYXRld2F5IFdlYlNvY2tldCBBUElzLlxuICogXG4gKiBBdXRoZW50aWNhdGlvbjpcbiAqICAgVHdvLXBoYXNlIGF1dGgg4oCUIHRoZSBjbGllbnQgY29ubmVjdHMgd2l0aG91dCBjcmVkZW50aWFscywgdGhlbiBzZW5kc1xuICogICBhbiB7IGFjdGlvbjogXCJhdXRoXCIsIHRva2VuOiBcIjxqd3Q+XCIgfSBtZXNzYWdlIG92ZXIgdGhlIGVuY3J5cHRlZCBjaGFubmVsLlxuICogICBUaGUgY29ubmVjdGlvbiBpcyBzdG9yZWQgYXMgdW5hdXRoZW50aWNhdGVkIG9uICRjb25uZWN0IGFuZCB1cGdyYWRlZFxuICogICB0byBhdXRoZW50aWNhdGVkIHZpYSBjb25uZWN0aW9uU3RvcmUuYXV0aGVudGljYXRlKCkuXG4gKiAgIFRoaXMgYXZvaWRzIGxlYWtpbmcgSldUcyBpbiBxdWVyeSBzdHJpbmdzLCBzZXJ2ZXIgbG9ncywgYW5kIGFjY2VzcyBsb2dzLlxuICogXG4gKiBNdWx0aS10ZW5hbmN5OlxuICogICBJZiBlbmFibGVkLCBlYWNoIGNvbm5lY3Rpb24gc3RvcmVzIGEgdGVuYW50SWQgYWxvbmdzaWRlIHVzZXJJZC5cbiAqICAgVXNlIHNlbmRUb1RlbmFudCgpIHRvIGJyb2FkY2FzdCB3aXRoaW4gYSB0ZW5hbnQgYm91bmRhcnkuXG4gKiBcbiAqIEFQSTpcbiAqICAgY29ubmVjdGlvblN0b3JlLnNhdmUoY29ubmVjdGlvbklkKSAgICAgICAgICAgICAgICAgICAgICAgIOKAlCAkY29ubmVjdCAodW5hdXRoZW50aWNhdGVkKVxuICogICBjb25uZWN0aW9uU3RvcmUuYXV0aGVudGljYXRlKGNvbm5lY3Rpb25JZCwgbWV0YWRhdGEpICAgICAg4oCUIGFmdGVyIEpXVCB2ZXJpZmljYXRpb25cbiAqICAgY29ubmVjdGlvblN0b3JlLnJlbW92ZShjb25uZWN0aW9uSWQpICAgICAgICAgICAgICAgICAgICAgIOKAlCAkZGlzY29ubmVjdFxuICogICBjb25uZWN0aW9uU3RvcmUuZ2V0KGNvbm5lY3Rpb25JZCkgICAgICAgICAgICAgICAgICAgICAgICAg4oCUIHNpbmdsZSBjb25uZWN0aW9uXG4gKiAgIGNvbm5lY3Rpb25TdG9yZS5nZXRBbGwoKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDigJQgYWxsIGNvbm5lY3Rpb25zXG4gKiAgIGNvbm5lY3Rpb25TdG9yZS5nZXRCeVVzZXIodXNlcklkKSAgICAgICAgICAgICAgICAgICAgICAgICDigJQgYnkgdXNlciAoR1NJKVxuICogICBjb25uZWN0aW9uU3RvcmUuZ2V0QnlUZW5hbnQodGVuYW50SWQpICAgICAgICAgICAgICAgICAgICAg4oCUIGJ5IHRlbmFudCAoR1NJKVxuICogICBjb25uZWN0aW9uU3RvcmUucG9zdFRvQ29ubmVjdGlvbihkb21haW4sIHN0YWdlLCBpZCwgZGF0YSkg4oCUIHNlbmQgdG8gb25lXG4gKiAgIGNvbm5lY3Rpb25TdG9yZS5zZW5kVG9Vc2VyKGRvbWFpbiwgc3RhZ2UsIHVzZXJJZCwgZGF0YSkgICDigJQgc2VuZCB0byBhbGwgdXNlciBzZXNzaW9uc1xuICogICBjb25uZWN0aW9uU3RvcmUuc2VuZFRvVGVuYW50KGRvbWFpbiwgc3RhZ2UsIHRlbmFudElkLCBkYXRhKSDigJQgYnJvYWRjYXN0IHdpdGhpbiB0ZW5hbnRcbiAqICAgY29ubmVjdGlvblN0b3JlLmJyb2FkY2FzdChkb21haW4sIHN0YWdlLCBkYXRhKSAgICAgICAgICAgIOKAlCBicm9hZGNhc3QgdG8gYWxsXG4gKiBcbiAqIEVudmlyb25tZW50IHZhcmlhYmxlczpcbiAqICAgQ09OTkVDVElPTlNfVEFCTEUg4oCUIER5bmFtb0RCIHRhYmxlIG5hbWUgKHJlcXVpcmVkKVxuICogXG4gKiBEeW5hbW9EQiB0YWJsZSBzY2hlbWE6XG4gKiAgIFBhcnRpdGlvbiBrZXk6IGNvbm5lY3Rpb25JZCAoU3RyaW5nKVxuICogICBUVEwgYXR0cmlidXRlOiB0dGxcbiAqICAgR1NJOiB1c2VySWQtaW5kZXggIChwYXJ0aXRpb24ga2V5OiB1c2VySWQpXG4gKiAgIEdTSTogdGVuYW50SWQtaW5kZXggKHBhcnRpdGlvbiBrZXk6IHRlbmFudElkKSDigJQgb25seSBpZiBtdWx0aS10ZW5hbmN5IGVuYWJsZWRcbiAqL1xuXG5pbXBvcnQgeyBEeW5hbW9EQkNsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1keW5hbW9kYic7XG5pbXBvcnQge1xuICBEeW5hbW9EQkRvY3VtZW50Q2xpZW50LFxuICBQdXRDb21tYW5kLFxuICBHZXRDb21tYW5kLFxuICBVcGRhdGVDb21tYW5kLFxuICBEZWxldGVDb21tYW5kLFxuICBTY2FuQ29tbWFuZCxcbiAgUXVlcnlDb21tYW5kLFxufSBmcm9tICdAYXdzLXNkay9saWItZHluYW1vZGInO1xuaW1wb3J0IHtcbiAgQXBpR2F0ZXdheU1hbmFnZW1lbnRBcGlDbGllbnQsXG4gIFBvc3RUb0Nvbm5lY3Rpb25Db21tYW5kLFxuICBHb25lRXhjZXB0aW9uLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtYXBpZ2F0ZXdheW1hbmFnZW1lbnRhcGknO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbm5lY3Rpb25SZWNvcmQge1xuICBjb25uZWN0aW9uSWQ6IHN0cmluZztcbiAgYXV0aGVudGljYXRlZDogYm9vbGVhbjtcbiAgdXNlcklkPzogc3RyaW5nO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbiAgZW1haWw/OiBzdHJpbmc7XG4gIGNvbm5lY3RlZEF0OiBudW1iZXI7XG4gIGF1dGhlbnRpY2F0ZWRBdD86IG51bWJlcjtcbiAgdHRsOiBudW1iZXI7XG4gIFtrZXk6IHN0cmluZ106IHVua25vd247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29ubmVjdGlvbk1ldGFkYXRhIHtcbiAgdXNlcklkOiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICBlbWFpbD86IHN0cmluZztcbiAgW2tleTogc3RyaW5nXTogdW5rbm93bjtcbn1cblxuY29uc3QgREVGQVVMVF9UVExfU0VDT05EUyA9IDcyMDA7IC8vIDIgaG91cnNcbmNvbnN0IEFVVEhfR1JBQ0VfUEVSSU9EX1NFQ09ORFMgPSAzMDsgLy8gdW5hdXRoZW50aWNhdGVkIGNvbm5lY3Rpb25zIGV4cGlyZSBxdWlja2x5XG5cbmZ1bmN0aW9uIGdldFRhYmxlTmFtZSgpOiBzdHJpbmcge1xuICBjb25zdCB0YWJsZSA9IHByb2Nlc3MuZW52LkNPTk5FQ1RJT05TX1RBQkxFO1xuICBpZiAoIXRhYmxlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDT05ORUNUSU9OU19UQUJMRSBlbnZpcm9ubWVudCB2YXJpYWJsZSBpcyBub3Qgc2V0Jyk7XG4gIH1cbiAgcmV0dXJuIHRhYmxlO1xufVxuXG5sZXQgX2RkYjogRHluYW1vREJEb2N1bWVudENsaWVudCB8IG51bGwgPSBudWxsO1xuXG5mdW5jdGlvbiBkZGIoKTogRHluYW1vREJEb2N1bWVudENsaWVudCB7XG4gIGlmICghX2RkYikge1xuICAgIF9kZGIgPSBEeW5hbW9EQkRvY3VtZW50Q2xpZW50LmZyb20obmV3IER5bmFtb0RCQ2xpZW50KHt9KSk7XG4gIH1cbiAgcmV0dXJuIF9kZGI7XG59XG5cbmZ1bmN0aW9uIGVuY29kZShkYXRhOiB1bmtub3duKTogVWludDhBcnJheSB7XG4gIHJldHVybiBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoSlNPTi5zdHJpbmdpZnkoZGF0YSkpO1xufVxuXG4vKipcbiAqIERlbGl2ZXIgZGF0YSB0byBhIGxpc3Qgb2YgY29ubmVjdGlvbnMgaW4gcGFyYWxsZWwuXG4gKiBSZW1vdmVzIHN0YWxlIGNvbm5lY3Rpb25zIGF1dG9tYXRpY2FsbHkuXG4gKiBSZXR1cm5zIGNvdW50IG9mIHN1Y2Nlc3NmdWwgZGVsaXZlcmllcy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVsaXZlclRvTWFueShcbiAgc3RvcmU6IHR5cGVvZiBjb25uZWN0aW9uU3RvcmUsXG4gIGRvbWFpbk5hbWU6IHN0cmluZyxcbiAgc3RhZ2U6IHN0cmluZyxcbiAgY29ubmVjdGlvbnM6IENvbm5lY3Rpb25SZWNvcmRbXSxcbiAgZGF0YTogdW5rbm93bixcbik6IFByb21pc2U8bnVtYmVyPiB7XG4gIGxldCBkZWxpdmVyZWQgPSAwO1xuICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgIGNvbm5lY3Rpb25zXG4gICAgICAuZmlsdGVyKChjKSA9PiBjLmF1dGhlbnRpY2F0ZWQpXG4gICAgICAubWFwKChjKSA9PiBzdG9yZS5wb3N0VG9Db25uZWN0aW9uKGRvbWFpbk5hbWUsIHN0YWdlLCBjLmNvbm5lY3Rpb25JZCwgZGF0YSkpLFxuICApO1xuICBmb3IgKGNvbnN0IHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdmdWxmaWxsZWQnICYmIHJlc3VsdC52YWx1ZSkgZGVsaXZlcmVkKys7XG4gIH1cbiAgcmV0dXJuIGRlbGl2ZXJlZDtcbn1cblxuLyoqXG4gKiBXZWJTb2NrZXQgY29ubmVjdGlvbiBzdG9yZSBiYWNrZWQgYnkgRHluYW1vREIuXG4gKiBcbiAqIFR3by1waGFzZSBhdXRoZW50aWNhdGlvbiBmbG93OlxuICogXG4gKiAxLiAkY29ubmVjdCBoYW5kbGVyOlxuICogYGBgdHlwZXNjcmlwdFxuICogYXdhaXQgY29ubmVjdGlvblN0b3JlLnNhdmUoY29ubmVjdGlvbklkKTtcbiAqIC8vIENvbm5lY3Rpb24gaXMgdW5hdXRoZW50aWNhdGVkLCBUVEwgPSAzMHNcbiAqIGBgYFxuICogXG4gKiAyLiBDbGllbnQgc2VuZHMgYXV0aCBtZXNzYWdlIG92ZXIgdGhlIGVuY3J5cHRlZCBXZWJTb2NrZXQ6XG4gKiBgYGBqc29uXG4gKiB7IFwiYWN0aW9uXCI6IFwiYXV0aFwiLCBcInRva2VuXCI6IFwiPGp3dD5cIiB9XG4gKiBgYGBcbiAqIFxuICogMy4gJGRlZmF1bHQgaGFuZGxlciB2ZXJpZmllcyBKV1QsIHRoZW46XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBhd2FpdCBjb25uZWN0aW9uU3RvcmUuYXV0aGVudGljYXRlKGNvbm5lY3Rpb25JZCwgeyB1c2VySWQsIHRlbmFudElkLCBlbWFpbCB9KTtcbiAqIC8vIENvbm5lY3Rpb24gaXMgbm93IGF1dGhlbnRpY2F0ZWQsIFRUTCBleHRlbmRlZCB0byAyaFxuICogYGBgXG4gKi9cbmV4cG9ydCBjb25zdCBjb25uZWN0aW9uU3RvcmUgPSB7XG4gIC8qKlxuICAgKiBTYXZlIGEgbmV3IGNvbm5lY3Rpb24gb24gJGNvbm5lY3QuXG4gICAqIFRoZSBjb25uZWN0aW9uIGlzIHVuYXV0aGVudGljYXRlZCB3aXRoIGEgc2hvcnQgVFRMLlxuICAgKiBUaGUgY2xpZW50IG11c3Qgc2VuZCBhbiBhdXRoIG1lc3NhZ2UgdG8gdXBncmFkZS5cbiAgICovXG4gIGFzeW5jIHNhdmUoY29ubmVjdGlvbklkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGF3YWl0IGRkYigpLnNlbmQobmV3IFB1dENvbW1hbmQoe1xuICAgICAgVGFibGVOYW1lOiBnZXRUYWJsZU5hbWUoKSxcbiAgICAgIEl0ZW06IHtcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgICBhdXRoZW50aWNhdGVkOiBmYWxzZSxcbiAgICAgICAgY29ubmVjdGVkQXQ6IG5vdyxcbiAgICAgICAgdHRsOiBNYXRoLmZsb29yKG5vdyAvIDEwMDApICsgQVVUSF9HUkFDRV9QRVJJT0RfU0VDT05EUyxcbiAgICAgIH0sXG4gICAgfSkpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBBdXRoZW50aWNhdGUgYSBjb25uZWN0aW9uIGFmdGVyIEpXVCB2ZXJpZmljYXRpb24uXG4gICAqIFVwZGF0ZXMgdGhlIHJlY29yZCB3aXRoIHVzZXIgbWV0YWRhdGEgYW5kIGV4dGVuZHMgdGhlIFRUTC5cbiAgICogXG4gICAqIEBwYXJhbSBjb25uZWN0aW9uSWQg4oCUIHRoZSBjb25uZWN0aW9uIHRvIGF1dGhlbnRpY2F0ZVxuICAgKiBAcGFyYW0gbWV0YWRhdGEg4oCUIG11c3QgaW5jbHVkZSB1c2VySWQsIG9wdGlvbmFsbHkgdGVuYW50SWQsIGVtYWlsLCBldGMuXG4gICAqL1xuICBhc3luYyBhdXRoZW50aWNhdGUoY29ubmVjdGlvbklkOiBzdHJpbmcsIG1ldGFkYXRhOiBDb25uZWN0aW9uTWV0YWRhdGEpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHsgdXNlcklkLCB0ZW5hbnRJZCwgZW1haWwsIC4uLmV4dHJhIH0gPSBtZXRhZGF0YTtcblxuICAgIGNvbnN0IHVwZGF0ZVBhcnRzID0gW1xuICAgICAgJ2F1dGhlbnRpY2F0ZWQgPSA6YXV0aCcsXG4gICAgICAndXNlcklkID0gOnVpZCcsXG4gICAgICAnYXV0aGVudGljYXRlZEF0ID0gOmF1dGhBdCcsXG4gICAgICAndHRsID0gOnR0bCcsXG4gICAgXTtcbiAgICBjb25zdCB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgICAgJzphdXRoJzogdHJ1ZSxcbiAgICAgICc6dWlkJzogdXNlcklkLFxuICAgICAgJzphdXRoQXQnOiBub3csXG4gICAgICAnOnR0bCc6IE1hdGguZmxvb3Iobm93IC8gMTAwMCkgKyBERUZBVUxUX1RUTF9TRUNPTkRTLFxuICAgIH07XG5cbiAgICBpZiAodGVuYW50SWQpIHtcbiAgICAgIHVwZGF0ZVBhcnRzLnB1c2goJ3RlbmFudElkID0gOnRpZCcpO1xuICAgICAgdmFsdWVzWyc6dGlkJ10gPSB0ZW5hbnRJZDtcbiAgICB9XG5cbiAgICBpZiAoZW1haWwpIHtcbiAgICAgIHVwZGF0ZVBhcnRzLnB1c2goJ2VtYWlsID0gOmVtYWlsJyk7XG4gICAgICB2YWx1ZXNbJzplbWFpbCddID0gZW1haWw7XG4gICAgfVxuXG4gICAgLy8gU3RvcmUgYW55IGV4dHJhIG1ldGFkYXRhIGZpZWxkc1xuICAgIGxldCBleHRyYUlkeCA9IDA7XG4gICAgZm9yIChjb25zdCBba2V5LCB2YWxdIG9mIE9iamVjdC5lbnRyaWVzKGV4dHJhKSkge1xuICAgICAgY29uc3QgcGxhY2Vob2xkZXIgPSBgOmV4dHJhJHtleHRyYUlkeH1gO1xuICAgICAgdXBkYXRlUGFydHMucHVzaChgI2V4dHJhJHtleHRyYUlkeH0gPSAke3BsYWNlaG9sZGVyfWApO1xuICAgICAgdmFsdWVzW3BsYWNlaG9sZGVyXSA9IHZhbDtcbiAgICAgIGV4dHJhSWR4Kys7XG4gICAgfVxuXG4gICAgY29uc3QgbmFtZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4dHJhSWR4OyBpKyspIHtcbiAgICAgIG5hbWVzW2AjZXh0cmEke2l9YF0gPSBPYmplY3Qua2V5cyhleHRyYSlbaV07XG4gICAgfVxuXG4gICAgYXdhaXQgZGRiKCkuc2VuZChuZXcgVXBkYXRlQ29tbWFuZCh7XG4gICAgICBUYWJsZU5hbWU6IGdldFRhYmxlTmFtZSgpLFxuICAgICAgS2V5OiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgVXBkYXRlRXhwcmVzc2lvbjogYFNFVCAke3VwZGF0ZVBhcnRzLmpvaW4oJywgJyl9YCxcbiAgICAgIEV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHZhbHVlcyxcbiAgICAgIC4uLihleHRyYUlkeCA+IDAgPyB7IEV4cHJlc3Npb25BdHRyaWJ1dGVOYW1lczogbmFtZXMgfSA6IHt9KSxcbiAgICB9KSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJlbW92ZSBhIGNvbm5lY3Rpb24gb24gJGRpc2Nvbm5lY3QuXG4gICAqL1xuICBhc3luYyByZW1vdmUoY29ubmVjdGlvbklkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBkZGIoKS5zZW5kKG5ldyBEZWxldGVDb21tYW5kKHtcbiAgICAgIFRhYmxlTmFtZTogZ2V0VGFibGVOYW1lKCksXG4gICAgICBLZXk6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgfSkpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZXQgYSBzaW5nbGUgY29ubmVjdGlvbiByZWNvcmQuXG4gICAqL1xuICBhc3luYyBnZXQoY29ubmVjdGlvbklkOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb25SZWNvcmQgfCBudWxsPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGRiKCkuc2VuZChuZXcgR2V0Q29tbWFuZCh7XG4gICAgICBUYWJsZU5hbWU6IGdldFRhYmxlTmFtZSgpLFxuICAgICAgS2V5OiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgIH0pKTtcbiAgICByZXR1cm4gKHJlc3VsdC5JdGVtIGFzIENvbm5lY3Rpb25SZWNvcmQpID8/IG51bGw7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBhbGwgYXV0aGVudGljYXRlZCBjb25uZWN0aW9ucy5cbiAgICogRm9yIGxhcmdlLXNjYWxlIGFwcHMsIHByZWZlciBnZXRCeVVzZXIoKSBvciBnZXRCeVRlbmFudCgpLlxuICAgKi9cbiAgYXN5bmMgZ2V0QWxsKCk6IFByb21pc2U8Q29ubmVjdGlvblJlY29yZFtdPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGRiKCkuc2VuZChuZXcgU2NhbkNvbW1hbmQoe1xuICAgICAgVGFibGVOYW1lOiBnZXRUYWJsZU5hbWUoKSxcbiAgICAgIEZpbHRlckV4cHJlc3Npb246ICdhdXRoZW50aWNhdGVkID0gOmF1dGgnLFxuICAgICAgRXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczogeyAnOmF1dGgnOiB0cnVlIH0sXG4gICAgfSkpO1xuICAgIHJldHVybiAocmVzdWx0Lkl0ZW1zID8/IFtdKSBhcyBDb25uZWN0aW9uUmVjb3JkW107XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBhbGwgY29ubmVjdGlvbnMgZm9yIGEgc3BlY2lmaWMgdXNlci5cbiAgICogQSB1c2VyIGNhbiBoYXZlIG11bHRpcGxlIGFjdGl2ZSBjb25uZWN0aW9ucyAoZS5nLiBtdWx0aXBsZSB0YWJzL2RldmljZXMpLlxuICAgKiBSZXF1aXJlcyBHU0k6IHVzZXJJZC1pbmRleCAocGFydGl0aW9uIGtleTogdXNlcklkKS5cbiAgICovXG4gIGFzeW5jIGdldEJ5VXNlcih1c2VySWQ6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvblJlY29yZFtdPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGRiKCkuc2VuZChuZXcgUXVlcnlDb21tYW5kKHtcbiAgICAgIFRhYmxlTmFtZTogZ2V0VGFibGVOYW1lKCksXG4gICAgICBJbmRleE5hbWU6ICd1c2VySWQtaW5kZXgnLFxuICAgICAgS2V5Q29uZGl0aW9uRXhwcmVzc2lvbjogJ3VzZXJJZCA9IDp1aWQnLFxuICAgICAgRXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczogeyAnOnVpZCc6IHVzZXJJZCB9LFxuICAgIH0pKTtcbiAgICByZXR1cm4gKHJlc3VsdC5JdGVtcyA/PyBbXSkgYXMgQ29ubmVjdGlvblJlY29yZFtdO1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZXQgYWxsIGNvbm5lY3Rpb25zIGZvciBhIHNwZWNpZmljIHRlbmFudC5cbiAgICogUmVxdWlyZXMgR1NJOiB0ZW5hbnRJZC1pbmRleCAocGFydGl0aW9uIGtleTogdGVuYW50SWQpLlxuICAgKi9cbiAgYXN5bmMgZ2V0QnlUZW5hbnQodGVuYW50SWQ6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvblJlY29yZFtdPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGRiKCkuc2VuZChuZXcgUXVlcnlDb21tYW5kKHtcbiAgICAgIFRhYmxlTmFtZTogZ2V0VGFibGVOYW1lKCksXG4gICAgICBJbmRleE5hbWU6ICd0ZW5hbnRJZC1pbmRleCcsXG4gICAgICBLZXlDb25kaXRpb25FeHByZXNzaW9uOiAndGVuYW50SWQgPSA6dGlkJyxcbiAgICAgIEV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHsgJzp0aWQnOiB0ZW5hbnRJZCB9LFxuICAgIH0pKTtcbiAgICByZXR1cm4gKHJlc3VsdC5JdGVtcyA/PyBbXSkgYXMgQ29ubmVjdGlvblJlY29yZFtdO1xuICB9LFxuXG4gIC8qKlxuICAgKiBTZW5kIGRhdGEgdG8gYSBzcGVjaWZpYyBjb25uZWN0aW9uIHZpYSBBUEkgR2F0ZXdheSBNYW5hZ2VtZW50IEFQSS5cbiAgICogQXV0b21hdGljYWxseSBjbGVhbnMgdXAgc3RhbGUgY29ubmVjdGlvbnMgKEdvbmVFeGNlcHRpb24pLlxuICAgKiBSZXR1cm5zIHRydWUgaWYgc2VudCwgZmFsc2UgaWYgdGhlIGNvbm5lY3Rpb24gd2FzIHN0YWxlIGFuZCByZW1vdmVkLlxuICAgKi9cbiAgYXN5bmMgcG9zdFRvQ29ubmVjdGlvbihcbiAgICBkb21haW5OYW1lOiBzdHJpbmcsXG4gICAgc3RhZ2U6IHN0cmluZyxcbiAgICBjb25uZWN0aW9uSWQ6IHN0cmluZyxcbiAgICBkYXRhOiB1bmtub3duLFxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBhcGlndyA9IG5ldyBBcGlHYXRld2F5TWFuYWdlbWVudEFwaUNsaWVudCh7XG4gICAgICBlbmRwb2ludDogYGh0dHBzOi8vJHtkb21haW5OYW1lfS8ke3N0YWdlfWAsXG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgYXBpZ3cuc2VuZChuZXcgUG9zdFRvQ29ubmVjdGlvbkNvbW1hbmQoe1xuICAgICAgICBDb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb25JZCxcbiAgICAgICAgRGF0YTogZW5jb2RlKGRhdGEpLFxuICAgICAgfSkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoZXJyIGluc3RhbmNlb2YgR29uZUV4Y2VwdGlvbikge1xuICAgICAgICBhd2FpdCB0aGlzLnJlbW92ZShjb25uZWN0aW9uSWQpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBTZW5kIGRhdGEgdG8gYWxsIGNvbm5lY3Rpb25zIGJlbG9uZ2luZyB0byBhIHNwZWNpZmljIHVzZXIuXG4gICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBjb25uZWN0aW9ucyB0aGF0IHJlY2VpdmVkIHRoZSBtZXNzYWdlLlxuICAgKi9cbiAgYXN5bmMgc2VuZFRvVXNlcihcbiAgICBkb21haW5OYW1lOiBzdHJpbmcsXG4gICAgc3RhZ2U6IHN0cmluZyxcbiAgICB1c2VySWQ6IHN0cmluZyxcbiAgICBkYXRhOiB1bmtub3duLFxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGNvbm5lY3Rpb25zID0gYXdhaXQgdGhpcy5nZXRCeVVzZXIodXNlcklkKTtcbiAgICByZXR1cm4gZGVsaXZlclRvTWFueSh0aGlzLCBkb21haW5OYW1lLCBzdGFnZSwgY29ubmVjdGlvbnMsIGRhdGEpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBTZW5kIGRhdGEgdG8gYWxsIGNvbm5lY3Rpb25zIHdpdGhpbiBhIHNwZWNpZmljIHRlbmFudC5cbiAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGNvbm5lY3Rpb25zIHRoYXQgcmVjZWl2ZWQgdGhlIG1lc3NhZ2UuXG4gICAqL1xuICBhc3luYyBzZW5kVG9UZW5hbnQoXG4gICAgZG9tYWluTmFtZTogc3RyaW5nLFxuICAgIHN0YWdlOiBzdHJpbmcsXG4gICAgdGVuYW50SWQ6IHN0cmluZyxcbiAgICBkYXRhOiB1bmtub3duLFxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGNvbm5lY3Rpb25zID0gYXdhaXQgdGhpcy5nZXRCeVRlbmFudCh0ZW5hbnRJZCk7XG4gICAgcmV0dXJuIGRlbGl2ZXJUb01hbnkodGhpcywgZG9tYWluTmFtZSwgc3RhZ2UsIGNvbm5lY3Rpb25zLCBkYXRhKTtcbiAgfSxcblxuICAvKipcbiAgICogQnJvYWRjYXN0IGRhdGEgdG8gYWxsIGF1dGhlbnRpY2F0ZWQgY29ubmVjdGlvbnMuXG4gICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBjbGllbnRzIHRoYXQgcmVjZWl2ZWQgdGhlIG1lc3NhZ2UuXG4gICAqL1xuICBhc3luYyBicm9hZGNhc3QoZG9tYWluTmFtZTogc3RyaW5nLCBzdGFnZTogc3RyaW5nLCBkYXRhOiB1bmtub3duKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBjb25uZWN0aW9ucyA9IGF3YWl0IHRoaXMuZ2V0QWxsKCk7XG4gICAgcmV0dXJuIGRlbGl2ZXJUb01hbnkodGhpcywgZG9tYWluTmFtZSwgc3RhZ2UsIGNvbm5lY3Rpb25zLCBkYXRhKTtcbiAgfSxcbn07XG4iXX0=
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@venturekit/runtime",
|
|
3
|
+
"version": "0.0.0-dev.20260307234057",
|
|
4
|
+
"description": "VentureKit runtime utilities - handlers, context, middleware, logging",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/venturekit-dev/venturekit.private.git",
|
|
13
|
+
"directory": "packages/runtime"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"registry": "https://registry.npmjs.org",
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"venturekit",
|
|
21
|
+
"saas",
|
|
22
|
+
"lambda",
|
|
23
|
+
"runtime"
|
|
24
|
+
],
|
|
25
|
+
"license": "Apache-2.0",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@venturekit/core": "0.0.0-dev.20260307234057",
|
|
28
|
+
"pino": "^9.0.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@venturekit/data": "0.0.0-dev.20260307234057",
|
|
32
|
+
"@aws-sdk/client-dynamodb": "^3.500.0",
|
|
33
|
+
"@aws-sdk/lib-dynamodb": "^3.500.0",
|
|
34
|
+
"@aws-sdk/client-apigatewaymanagementapi": "^3.500.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"@venturekit/data": {
|
|
38
|
+
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"@aws-sdk/client-dynamodb": {
|
|
41
|
+
"optional": true
|
|
42
|
+
},
|
|
43
|
+
"@aws-sdk/lib-dynamodb": {
|
|
44
|
+
"optional": true
|
|
45
|
+
},
|
|
46
|
+
"@aws-sdk/client-apigatewaymanagementapi": {
|
|
47
|
+
"optional": true
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@venturekit/data": "0.0.0-dev.20260307234057",
|
|
52
|
+
"@types/aws-lambda": "^8.10.131",
|
|
53
|
+
"@types/node": "^20.10.0",
|
|
54
|
+
"typescript": "^5.3.0"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsc",
|
|
58
|
+
"dev": "tsc --watch",
|
|
59
|
+
"clean": "rm -rf dist"
|
|
60
|
+
}
|
|
61
|
+
}
|