@nlabs/rip-hunter 2.6.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +278 -138
- package/benchmark.js +85 -0
- package/index.js +1 -1
- package/lex.config.js +8 -2
- package/lib/errors/ApiError.d.ts +4 -0
- package/lib/errors/ApiError.js +2 -34
- package/lib/index.d.ts +28 -0
- package/lib/index.js +2 -185
- package/package.json +14 -13
- package/tsconfig.build.json +16 -0
- package/tsconfig.json +29 -18
- package/tsconfig.lint.json +25 -0
- package/tsconfig.test.json +14 -0
- package/.eslintrc +0 -5
package/README.md
CHANGED
|
@@ -1,211 +1,351 @@
|
|
|
1
|
-
|
|
1
|
+
# rip-hunter
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Universal REST & GraphQL Client for Modern JavaScript/TypeScript Projects**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**rip-hunter** is the all-in-one HTTP utility for developers who want a seamless, ESM-first way to connect to REST and GraphQL APIs. Whether you're building in Node.js, the browser, or serverless, rip-hunter makes data fetching, mutations, and error handling effortless—so you can focus on building features, not plumbing.
|
|
7
8
|
|
|
8
9
|
[](https://www.npmjs.com/package/rip-hunter)
|
|
9
|
-
[](https://travis-ci.org/nitrogenlabs/rip-hunter)
|
|
10
10
|
[](https://www.npmjs.com/package/rip-hunter)
|
|
11
|
-
[](https://github.com/nitrogenlabs/rip-hunter/issues)
|
|
12
11
|
[](http://opensource.org/licenses/MIT)
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🚀 Why rip-hunter?
|
|
16
|
+
|
|
17
|
+
- **Unified API**: One package for both REST and GraphQL endpoints
|
|
18
|
+
- **ESM & TypeScript Native**: Modern, type-safe, and tree-shakable
|
|
19
|
+
- **Works Everywhere**: Node, browser, serverless—no config needed
|
|
20
|
+
- **Built-in Auth & Headers**: Effortlessly add tokens and custom headers
|
|
21
|
+
- **Automatic Error Handling**: Consistent, developer-friendly errors
|
|
22
|
+
- **Tiny & Fast**: Minimal dependencies, zero bloat
|
|
23
|
+
- **Request Caching**: Built-in caching for GET requests
|
|
24
|
+
- **Timeout Support**: Configurable request timeouts
|
|
25
|
+
- **Request Deduplication**: Prevents duplicate requests
|
|
26
|
+
- **Real-time Updates**: Server-Sent Events (SSE) support
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 📦 Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @nlabs/rip-hunter
|
|
34
|
+
# or
|
|
35
|
+
yarn add @nlabs/rip-hunter
|
|
36
|
+
|
|
37
|
+
# For Node.js SSE support (optional)
|
|
38
|
+
npm install eventsource
|
|
39
|
+
```
|
|
15
40
|
|
|
16
|
-
|
|
41
|
+
---
|
|
17
42
|
|
|
18
|
-
|
|
43
|
+
## ⚡ Quick Start
|
|
19
44
|
|
|
20
|
-
###
|
|
21
|
-
Then with a module bundler like [webpack](https://webpack.github.io/) that supports either CommonJS or ES2015 modules, use as you would anything else:
|
|
45
|
+
### REST Example
|
|
22
46
|
|
|
23
47
|
```js
|
|
24
|
-
import {
|
|
48
|
+
import { get, post } from '@nlabs/rip-hunter';
|
|
49
|
+
|
|
50
|
+
const url = 'https://api.example.com/data';
|
|
51
|
+
|
|
52
|
+
// GET request with caching
|
|
53
|
+
const data = await get(url, { userId: 123 }, { cache: true });
|
|
54
|
+
|
|
55
|
+
// POST request with auth token and timeout
|
|
56
|
+
const result = await post(url, { name: 'Rip Hunter' }, {
|
|
57
|
+
token: 'your_jwt_token',
|
|
58
|
+
timeout: 5000
|
|
59
|
+
});
|
|
25
60
|
```
|
|
26
61
|
|
|
27
|
-
###
|
|
62
|
+
### GraphQL Example
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
import { query, mutation, toGql } from '@nlabs/rip-hunter';
|
|
66
|
+
|
|
67
|
+
const url = 'https://api.example.com/graphql';
|
|
68
|
+
const gql = '{ user { id name } }';
|
|
28
69
|
|
|
29
|
-
|
|
70
|
+
// Query with timeout
|
|
71
|
+
const userData = await query(url, gql, { timeout: 10000 });
|
|
72
|
+
|
|
73
|
+
// Mutation with variables
|
|
74
|
+
const input = { name: 'Rip Hunter' };
|
|
75
|
+
const mutationGql = `mutation { createUser(input: ${toGql(input)}) { id name } }`;
|
|
76
|
+
const created = await mutation(url, mutationGql, { timeout: 5000 });
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### SSE Example
|
|
30
80
|
|
|
31
81
|
```js
|
|
32
|
-
import {
|
|
33
|
-
|
|
34
|
-
const AppActions = {
|
|
35
|
-
getData: () => {
|
|
36
|
-
// Variables
|
|
37
|
-
const url = 'http://www.example.com/graphql';
|
|
38
|
-
const gql = '{ app { ping } }';
|
|
39
|
-
|
|
40
|
-
// Query data
|
|
41
|
-
return query(url, gql)
|
|
42
|
-
.then(results => {
|
|
43
|
-
console.log(results);
|
|
44
|
-
// Assuming the results will return the JSON object, {status: 'ok'}
|
|
45
|
-
// Output: {status: 'ok'}
|
|
46
|
-
})
|
|
47
|
-
.catch(error => {
|
|
48
|
-
// ApiError will be returned if any problems occur.
|
|
49
|
-
});
|
|
50
|
-
},
|
|
82
|
+
import { subscribeSSE } from '@nlabs/rip-hunter';
|
|
51
83
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// Assuming the results will return the JSON object, {id: 'test', hello: 'world'}
|
|
63
|
-
// Output: {id: 'test', hello: 'world'}
|
|
64
|
-
})
|
|
65
|
-
.catch(error => {
|
|
66
|
-
// ApiError will be returned if any problems occur.
|
|
67
|
-
});
|
|
84
|
+
// Subscribe to real-time updates
|
|
85
|
+
const unsubscribe = subscribeSSE('https://api.example.com/stream', {
|
|
86
|
+
onMessage: (event) => {
|
|
87
|
+
console.log('Received:', event.data);
|
|
88
|
+
},
|
|
89
|
+
onError: (error) => {
|
|
90
|
+
console.error('SSE Error:', error);
|
|
91
|
+
},
|
|
92
|
+
onOpen: () => {
|
|
93
|
+
console.log('SSE connection opened');
|
|
68
94
|
}
|
|
69
|
-
}
|
|
70
|
-
|
|
95
|
+
}, {
|
|
96
|
+
token: 'your_jwt_token',
|
|
97
|
+
timeout: 30000,
|
|
98
|
+
retryInterval: 1000,
|
|
99
|
+
maxRetries: 5
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Later, to stop listening:
|
|
103
|
+
unsubscribe();
|
|
71
104
|
```
|
|
72
105
|
|
|
73
|
-
|
|
106
|
+
---
|
|
74
107
|
|
|
75
|
-
|
|
108
|
+
## 🛠️ API Reference
|
|
76
109
|
|
|
77
|
-
|
|
110
|
+
### REST Functions
|
|
111
|
+
|
|
112
|
+
#### `ajax(url, method, params?, options?)`
|
|
113
|
+
|
|
114
|
+
Low-level HTTP request for any method.
|
|
78
115
|
|
|
79
|
-
|
|
80
|
-
|
|
116
|
+
- **url**: `string` – Absolute URL
|
|
117
|
+
- **method**: `string` – HTTP method (GET, POST, etc.)
|
|
118
|
+
- **params**: `object` – Data to send (query for GET, body for others)
|
|
119
|
+
- **options**: `{ headers?, token?, timeout?, cache? }`
|
|
120
|
+
- **Returns**: `Promise<any>`
|
|
81
121
|
|
|
82
|
-
|
|
122
|
+
#### `get(url, params?, options?)`
|
|
83
123
|
|
|
84
|
-
|
|
124
|
+
HTTP GET request.
|
|
85
125
|
|
|
86
|
-
|
|
126
|
+
- **url**: `string`
|
|
127
|
+
- **params**: `object`
|
|
128
|
+
- **options**: `{ headers?, token?, timeout?, cache? }`
|
|
129
|
+
- **Returns**: `Promise<any>`
|
|
87
130
|
|
|
131
|
+
#### `post(url, params?, options?)`
|
|
88
132
|
|
|
89
|
-
|
|
133
|
+
HTTP POST request.
|
|
90
134
|
|
|
91
|
-
|
|
135
|
+
- **url**: `string`
|
|
136
|
+
- **params**: `object`
|
|
137
|
+
- **options**: `{ headers?, token?, timeout? }`
|
|
138
|
+
- **Returns**: `Promise<any>`
|
|
92
139
|
|
|
93
|
-
|
|
140
|
+
#### `put(url, params?, options?)`
|
|
94
141
|
|
|
95
|
-
|
|
96
|
-
* [`listener`] \(*Function*): The callback to be invoked any time an action has been dispatched.
|
|
142
|
+
HTTP PUT request.
|
|
97
143
|
|
|
98
|
-
|
|
144
|
+
- **url**: `string`
|
|
145
|
+
- **params**: `object`
|
|
146
|
+
- **options**: `{ headers?, token?, timeout? }`
|
|
147
|
+
- **Returns**: `Promise<any>`
|
|
99
148
|
|
|
100
|
-
|
|
149
|
+
#### `del(url, params?, options?)`
|
|
101
150
|
|
|
102
|
-
|
|
103
|
-
* [`listener`] \(*Function*): The callback associated with the subscribed event.
|
|
151
|
+
HTTP DELETE request.
|
|
104
152
|
|
|
153
|
+
- **url**: `string`
|
|
154
|
+
- **params**: `object`
|
|
155
|
+
- **options**: `{ headers?, token?, timeout? }`
|
|
156
|
+
- **Returns**: `Promise<any>`
|
|
105
157
|
|
|
106
|
-
|
|
158
|
+
---
|
|
107
159
|
|
|
108
|
-
|
|
160
|
+
### GraphQL Functions
|
|
109
161
|
|
|
110
|
-
|
|
162
|
+
#### `query(url, body, options?)`
|
|
111
163
|
|
|
112
|
-
|
|
113
|
-
* [`method`] \(*String*): The HTTP method for the request.
|
|
114
|
-
* [`params`] \(*Object*): Data to be sent with the request. Params will be converted to a query string for GET methods.
|
|
115
|
-
* [`options`] \(*Object*): Rip Hunter options.
|
|
116
|
-
* [`headers`] \(*Object*): Overwrite the default headers.
|
|
117
|
-
* [`token`] \(*String*): Add an _Authorization_ header with the value _Bearer [token]_.
|
|
164
|
+
Send a GraphQL query.
|
|
118
165
|
|
|
119
|
-
|
|
166
|
+
- **url**: `string` – GraphQL endpoint
|
|
167
|
+
- **body**: `string` – GraphQL query string
|
|
168
|
+
- **options**: `{ headers?, token?, variables?, stripWhitespace?, timeout? }`
|
|
169
|
+
- **Returns**: `Promise<any>`
|
|
120
170
|
|
|
121
|
-
|
|
171
|
+
#### `mutation(url, body, options?)`
|
|
172
|
+
|
|
173
|
+
Send a GraphQL mutation.
|
|
174
|
+
|
|
175
|
+
- **url**: `string`
|
|
176
|
+
- **body**: `string`
|
|
177
|
+
- **options**: `{ headers?, token?, variables?, stripWhitespace?, timeout? }`
|
|
178
|
+
- **Returns**: `Promise<any>`
|
|
179
|
+
|
|
180
|
+
#### `graphqlQuery(url, query, options?)`
|
|
181
|
+
|
|
182
|
+
Low-level GraphQL request.
|
|
183
|
+
|
|
184
|
+
- **url**: `string` – GraphQL endpoint
|
|
185
|
+
- **query**: `HunterQueryType | HunterQueryType[]` – Query object(s)
|
|
186
|
+
- **options**: `{ headers?, token?, timeout? }`
|
|
187
|
+
- **Returns**: `Promise<any>`
|
|
188
|
+
|
|
189
|
+
#### `toGql(data)`
|
|
122
190
|
|
|
123
|
-
|
|
191
|
+
Convert JS objects, arrays, or primitives to GraphQL input strings.
|
|
124
192
|
|
|
125
|
-
|
|
193
|
+
- **data**: `any`
|
|
194
|
+
- **Returns**: `string`
|
|
195
|
+
- **Example**:
|
|
126
196
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
* [`headers`] \(*Object*): Overwrite the default headers.
|
|
131
|
-
* [`token`] \(*String*): Add an _Authorization_ header with the value _Bearer [token]_.
|
|
197
|
+
```js
|
|
198
|
+
toGql({ name: 'Rip', age: 42 }) // => '{name: "Rip", age: 42}'
|
|
199
|
+
```
|
|
132
200
|
|
|
133
|
-
|
|
201
|
+
---
|
|
134
202
|
|
|
135
|
-
|
|
203
|
+
### SSE Functions
|
|
136
204
|
|
|
137
|
-
#### `
|
|
205
|
+
#### `subscribeSSE(url, callbacks, options?)`
|
|
138
206
|
|
|
139
|
-
|
|
207
|
+
Subscribe to Server-Sent Events.
|
|
140
208
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
209
|
+
- **url**: `string` – SSE endpoint URL
|
|
210
|
+
- **callbacks**: `HunterSSECallbackType` – Event handlers
|
|
211
|
+
- `onMessage?: (event: HunterSSEEventType) => void`
|
|
212
|
+
- `onOpen?: (event: Event) => void`
|
|
213
|
+
- `onError?: (error: Error | Event) => void`
|
|
214
|
+
- `onRetry?: (attempt: number, delay: number) => void`
|
|
215
|
+
- **options**: `HunterSSEOptionsType` – Connection options
|
|
216
|
+
- `headers?: Headers`
|
|
217
|
+
- `token?: string`
|
|
218
|
+
- `timeout?: number` (default: 30000)
|
|
219
|
+
- `retryInterval?: number` (default: 1000)
|
|
220
|
+
- `maxRetries?: number` (default: 5)
|
|
221
|
+
- **Returns**: `() => void` – Cleanup function
|
|
146
222
|
|
|
147
|
-
|
|
223
|
+
#### `HunterSSEEventType`
|
|
148
224
|
|
|
149
|
-
|
|
225
|
+
SSE event object with:
|
|
150
226
|
|
|
151
|
-
|
|
227
|
+
- `data: string` – Event data
|
|
228
|
+
- `type: string` – Event type
|
|
229
|
+
- `id?: string` – Event ID
|
|
230
|
+
- `retry?: number` – Retry interval (if specified by server)
|
|
152
231
|
|
|
153
|
-
|
|
232
|
+
---
|
|
154
233
|
|
|
155
|
-
|
|
156
|
-
* [`params`] \(*Object*): Data to be sent with the request.
|
|
157
|
-
* [`options`] \(*Object*): Rip Hunter options.
|
|
158
|
-
* [`headers`] \(*Object*): Overwrite the default headers.
|
|
159
|
-
* [`token`] \(*String*): Add an _Authorization_ header with the value _Bearer [token]_.
|
|
234
|
+
### Events & Error Handling
|
|
160
235
|
|
|
161
|
-
|
|
236
|
+
#### `on(eventType, listener)`
|
|
162
237
|
|
|
163
|
-
|
|
238
|
+
Subscribe to events (e.g., error events).
|
|
164
239
|
|
|
165
|
-
|
|
240
|
+
- **eventType**: `string` (e.g., 'rip_hunter_error')
|
|
241
|
+
- **listener**: `Function`
|
|
166
242
|
|
|
167
|
-
|
|
243
|
+
#### `off(eventType, listener)`
|
|
168
244
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
245
|
+
Unsubscribe from events.
|
|
246
|
+
|
|
247
|
+
#### `ApiError`
|
|
248
|
+
|
|
249
|
+
All errors are wrapped in a consistent `ApiError` object for easy handling.
|
|
250
|
+
|
|
251
|
+
- **.errors**: `string[]` – List of error messages
|
|
252
|
+
- **.source**: `Error` – Original error object
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## 💡 Advanced Usage
|
|
257
|
+
|
|
258
|
+
### Request Caching
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
// Cache GET requests for 5 minutes
|
|
262
|
+
const data = await get('/api/users', {}, { cache: true });
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Timeout Handling
|
|
266
|
+
|
|
267
|
+
```js
|
|
268
|
+
// Set 10 second timeout
|
|
269
|
+
const result = await post('/api/data', payload, { timeout: 10000 });
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Custom Headers
|
|
273
|
+
|
|
274
|
+
```js
|
|
275
|
+
const headers = new Headers({
|
|
276
|
+
'X-Custom-Header': 'value',
|
|
277
|
+
'Content-Type': 'application/json'
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const data = await get('/api/data', {}, { headers });
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### GraphQL Variables
|
|
284
|
+
|
|
285
|
+
```js
|
|
286
|
+
const query = `
|
|
287
|
+
query GetUser($id: ID!) {
|
|
288
|
+
user(id: $id) { name email }
|
|
289
|
+
}
|
|
290
|
+
`;
|
|
291
|
+
|
|
292
|
+
const variables = { id: '123' };
|
|
293
|
+
const user = await query('/graphql', query, { variables });
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### SSE with Authentication
|
|
297
|
+
|
|
298
|
+
```js
|
|
299
|
+
const headers = new Headers({
|
|
300
|
+
'Authorization': 'Bearer your-token',
|
|
301
|
+
'Accept': 'text/event-stream'
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
const unsubscribe = subscribeSSE('/api/notifications', {
|
|
305
|
+
onMessage: (event) => {
|
|
306
|
+
const notification = JSON.parse(event.data);
|
|
307
|
+
console.log('New notification:', notification);
|
|
308
|
+
},
|
|
309
|
+
onError: (error) => {
|
|
310
|
+
console.error('SSE error:', error);
|
|
311
|
+
}
|
|
312
|
+
}, {
|
|
313
|
+
headers,
|
|
314
|
+
timeout: 60000,
|
|
315
|
+
maxRetries: 10
|
|
316
|
+
});
|
|
317
|
+
```
|
|
174
318
|
|
|
175
|
-
|
|
319
|
+
---
|
|
176
320
|
|
|
177
|
-
|
|
321
|
+
## 🚀 Performance Features
|
|
178
322
|
|
|
179
|
-
|
|
323
|
+
- **Request Deduplication**: Prevents duplicate requests to the same endpoint
|
|
324
|
+
- **Built-in Caching**: Automatic caching for GET requests with 5-minute TTL
|
|
325
|
+
- **Timeout Support**: Configurable request timeouts (default: 30s)
|
|
326
|
+
- **Optimized Functions**: Lightweight utility functions for better performance
|
|
327
|
+
- **Memory Efficient**: Minimal object creation and garbage collection
|
|
328
|
+
- **SSE Reconnection**: Automatic retry with exponential backoff for SSE connections
|
|
180
329
|
|
|
181
|
-
|
|
330
|
+
---
|
|
182
331
|
|
|
183
|
-
|
|
332
|
+
## 🌐 Environment Support
|
|
184
333
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
* [`headers`] \(*Object*): Overwrite the default headers.
|
|
189
|
-
* [`stripWhitespace`] \(*Boolean*): Removes whitespace in body. Default: false.
|
|
190
|
-
* [`token`] \(*String*): Add an _Authorization_ header with the value _Bearer [token]_.
|
|
191
|
-
* [`variables`] \(*Object*): Variables used in query. Default: {}.
|
|
334
|
+
- **Browser**: Full support for all features including SSE
|
|
335
|
+
- **Node.js**: Full REST/GraphQL support, SSE requires `eventsource` package
|
|
336
|
+
- **Serverless**: REST/GraphQL support (SSE not recommended in serverless)
|
|
192
337
|
|
|
193
|
-
|
|
338
|
+
---
|
|
194
339
|
|
|
195
|
-
|
|
340
|
+
## 🤝 Contributing
|
|
196
341
|
|
|
197
|
-
|
|
342
|
+
PRs and issues welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
198
343
|
|
|
199
|
-
|
|
344
|
+
## 📄 License
|
|
200
345
|
|
|
201
|
-
|
|
202
|
-
* [`body`] \(*String*): GraphQL query.
|
|
203
|
-
* [`options`] \(*Object*): Rip Hunter options.
|
|
204
|
-
* [`headers`] \(*Object*): Overwrite the default headers.
|
|
205
|
-
* [`stripWhitespace`] \(*Boolean*): Removes whitespace in body. Default: false.
|
|
206
|
-
* [`token`] \(*String*): Add an _Authorization_ header with the value _Bearer [token]_.
|
|
207
|
-
* [`variables`] \(*Object*): Variables used in query. Default: {}.
|
|
346
|
+
MIT © Nitrogen Labs, Inc.
|
|
208
347
|
|
|
209
|
-
|
|
348
|
+
## 🔗 Links
|
|
210
349
|
|
|
211
|
-
|
|
350
|
+
- [GitHub](https://github.com/nitrogenlabs/rip-hunter)
|
|
351
|
+
- [NPM](https://www.npmjs.com/package/rip-hunter)
|
package/benchmark.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Performance benchmark for rip-hunter
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Mock fetch for benchmarking
|
|
8
|
+
global.fetch = () => Promise.resolve({
|
|
9
|
+
json: () => Promise.resolve({}),
|
|
10
|
+
text: () => Promise.resolve(''),
|
|
11
|
+
headers: new Headers()
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
import { queryString, removeSpaces, toGql } from './src/index.js';
|
|
15
|
+
|
|
16
|
+
console.log('🚀 rip-hunter Performance Benchmark\n');
|
|
17
|
+
|
|
18
|
+
// Benchmark toGql function
|
|
19
|
+
console.log('📊 toGql Performance Test:');
|
|
20
|
+
const testObject = {
|
|
21
|
+
name: 'Rip Hunter',
|
|
22
|
+
age: 42,
|
|
23
|
+
skills: ['time travel', 'combat'],
|
|
24
|
+
metadata: {
|
|
25
|
+
universe: 'DC',
|
|
26
|
+
team: 'Legion of Super-Heroes'
|
|
27
|
+
},
|
|
28
|
+
nullValue: null,
|
|
29
|
+
undefinedValue: undefined
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const iterations = 100000;
|
|
33
|
+
const startTime = performance.now();
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < iterations; i++) {
|
|
36
|
+
toGql(testObject);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const endTime = performance.now();
|
|
40
|
+
const duration = endTime - startTime;
|
|
41
|
+
const opsPerSecond = Math.round(iterations / (duration / 1000));
|
|
42
|
+
|
|
43
|
+
console.log(` ✅ ${iterations.toLocaleString()} iterations in ${duration.toFixed(2)}ms`);
|
|
44
|
+
console.log(` 📈 ${opsPerSecond.toLocaleString()} operations/second\n`);
|
|
45
|
+
|
|
46
|
+
// Benchmark queryString function
|
|
47
|
+
console.log('📊 queryString Performance Test:');
|
|
48
|
+
const testParams = {
|
|
49
|
+
userId: 123,
|
|
50
|
+
name: 'Rip Hunter',
|
|
51
|
+
skills: ['time travel', 'combat'],
|
|
52
|
+
metadata: { universe: 'DC' }
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const startTime2 = performance.now();
|
|
56
|
+
|
|
57
|
+
for (let i = 0; i < iterations; i++) {
|
|
58
|
+
queryString(testParams);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const endTime2 = performance.now();
|
|
62
|
+
const duration2 = endTime2 - startTime2;
|
|
63
|
+
const opsPerSecond2 = Math.round(iterations / (duration2 / 1000));
|
|
64
|
+
|
|
65
|
+
console.log(` ✅ ${iterations.toLocaleString()} iterations in ${duration2.toFixed(2)}ms`);
|
|
66
|
+
console.log(` 📈 ${opsPerSecond2.toLocaleString()} operations/second\n`);
|
|
67
|
+
|
|
68
|
+
// Benchmark removeSpaces function
|
|
69
|
+
console.log('📊 removeSpaces Performance Test:');
|
|
70
|
+
const testString = 'query { user { id name email } }';
|
|
71
|
+
|
|
72
|
+
const startTime3 = performance.now();
|
|
73
|
+
|
|
74
|
+
for (let i = 0; i < iterations; i++) {
|
|
75
|
+
removeSpaces(testString);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const endTime3 = performance.now();
|
|
79
|
+
const duration3 = endTime3 - startTime3;
|
|
80
|
+
const opsPerSecond3 = Math.round(iterations / (duration3 / 1000));
|
|
81
|
+
|
|
82
|
+
console.log(` ✅ ${iterations.toLocaleString()} iterations in ${duration3.toFixed(2)}ms`);
|
|
83
|
+
console.log(` 📈 ${opsPerSecond3.toLocaleString()} operations/second\n`);
|
|
84
|
+
|
|
85
|
+
console.log('🎉 Benchmark completed!');
|
package/index.js
CHANGED
package/lex.config.js
CHANGED
package/lib/errors/ApiError.d.ts
CHANGED
package/lib/errors/ApiError.js
CHANGED
|
@@ -1,34 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
var __export = (target, all) => {
|
|
6
|
-
for (var name in all)
|
|
7
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
-
};
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
-
var ApiError_exports = {};
|
|
19
|
-
__export(ApiError_exports, {
|
|
20
|
-
ApiError: () => ApiError
|
|
21
|
-
});
|
|
22
|
-
module.exports = __toCommonJS(ApiError_exports);
|
|
23
|
-
class ApiError extends Error {
|
|
24
|
-
constructor(list, error) {
|
|
25
|
-
super("API Error");
|
|
26
|
-
this.source = error;
|
|
27
|
-
this.errors = list ? list.map((errorItem) => errorItem.message) : [];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
31
|
-
0 && (module.exports = {
|
|
32
|
-
ApiError
|
|
33
|
-
});
|
|
34
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2Vycm9ycy9BcGlFcnJvci50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiZXhwb3J0IGNsYXNzIEFwaUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBzb3VyY2U6IEVycm9yO1xuICBlcnJvcnM6IHN0cmluZ1tdO1xuXG4gIGNvbnN0cnVjdG9yKGxpc3QsIGVycm9yKSB7XG4gICAgc3VwZXIoJ0FQSSBFcnJvcicpO1xuICAgIHRoaXMuc291cmNlID0gZXJyb3I7XG4gICAgdGhpcy5lcnJvcnMgPSBsaXN0ID8gbGlzdC5tYXAoKGVycm9ySXRlbTogRXJyb3IpID0+IGVycm9ySXRlbS5tZXNzYWdlKSA6IFtdO1xuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBTyxNQUFNLGlCQUFpQixNQUFNO0FBQUEsRUFJbEMsWUFBWSxNQUFNLE9BQU87QUFDdkIsVUFBTSxXQUFXO0FBQ2pCLFNBQUssU0FBUztBQUNkLFNBQUssU0FBUyxPQUFPLEtBQUssSUFBSSxDQUFDLGNBQXFCLFVBQVUsT0FBTyxJQUFJLENBQUM7QUFBQSxFQUM1RTtBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo=
|
|
1
|
+
class t extends Error{source;errors;constructor(r,s){super("API Error"),this.source=s,this.errors=r?r.map(o=>o.message):[]}}export{t as ApiError};
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2Vycm9ycy9BcGlFcnJvci50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTctUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBBcGlFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgc291cmNlOiBFcnJvcjtcbiAgZXJyb3JzOiBzdHJpbmdbXTtcblxuICBjb25zdHJ1Y3RvcihsaXN0LCBlcnJvcikge1xuICAgIHN1cGVyKCdBUEkgRXJyb3InKTtcbiAgICB0aGlzLnNvdXJjZSA9IGVycm9yO1xuICAgIHRoaXMuZXJyb3JzID0gbGlzdCA/IGxpc3QubWFwKChlcnJvckl0ZW06IEVycm9yKSA9PiBlcnJvckl0ZW0ubWVzc2FnZSkgOiBbXTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIkFBSU8sTUFBTUEsVUFBaUIsS0FBTSxDQUNsQyxPQUNBLE9BRUEsWUFBWUMsRUFBTUMsRUFBTyxDQUN2QixNQUFNLFdBQVcsRUFDakIsS0FBSyxPQUFTQSxFQUNkLEtBQUssT0FBU0QsRUFBT0EsRUFBSyxJQUFLRSxHQUFxQkEsRUFBVSxPQUFPLEVBQUksQ0FBQyxDQUM1RSxDQUNGIiwKICAibmFtZXMiOiBbIkFwaUVycm9yIiwgImxpc3QiLCAiZXJyb3IiLCAiZXJyb3JJdGVtIl0KfQo=
|
package/lib/index.d.ts
CHANGED
|
@@ -1,12 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-Present, Nitrogen Labs, Inc.
|
|
3
|
+
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
4
|
+
*/
|
|
1
5
|
export interface HunterOptionsType {
|
|
2
6
|
readonly headers?: Headers;
|
|
3
7
|
readonly token?: string;
|
|
4
8
|
readonly variables?: any;
|
|
9
|
+
readonly timeout?: number;
|
|
10
|
+
readonly cache?: boolean;
|
|
5
11
|
}
|
|
6
12
|
export interface HunterQueryType {
|
|
7
13
|
readonly query: string;
|
|
8
14
|
readonly variables?: any;
|
|
9
15
|
}
|
|
16
|
+
export interface HunterSSEOptionsType {
|
|
17
|
+
readonly headers?: Headers;
|
|
18
|
+
readonly token?: string;
|
|
19
|
+
readonly timeout?: number;
|
|
20
|
+
readonly retryInterval?: number;
|
|
21
|
+
readonly maxRetries?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface HunterSSEEventType {
|
|
24
|
+
readonly data: string;
|
|
25
|
+
readonly type: string;
|
|
26
|
+
readonly id?: string;
|
|
27
|
+
readonly retry?: number | undefined;
|
|
28
|
+
}
|
|
29
|
+
export interface HunterSSECallbackType {
|
|
30
|
+
onMessage?: (event: HunterSSEEventType) => void;
|
|
31
|
+
onOpen?: (event: Event) => void;
|
|
32
|
+
onError?: (error: Error | Event) => void;
|
|
33
|
+
onRetry?: (attempt: number, delay: number) => void;
|
|
34
|
+
}
|
|
10
35
|
export declare const removeSpaces: (str: string) => string;
|
|
11
36
|
export declare const queryString: (json: any) => string;
|
|
12
37
|
export declare const ajax: (url: string, method: string, params?: any, options?: HunterOptionsType) => Promise<any>;
|
|
@@ -16,4 +41,7 @@ export declare const put: (url: string, params?: any, options?: HunterOptionsTyp
|
|
|
16
41
|
export declare const del: (url: string, params?: any, options?: HunterOptionsType) => Promise<any>;
|
|
17
42
|
export declare const toGql: (obj: any) => string;
|
|
18
43
|
export declare const graphqlQuery: (url: string, query: HunterQueryType | HunterQueryType[], options?: HunterOptionsType) => Promise<any>;
|
|
44
|
+
export declare const query: (url: string, body: string, options?: HunterOptionsType) => Promise<any>;
|
|
45
|
+
export declare const mutation: (url: string, body: string, options?: HunterOptionsType) => Promise<any>;
|
|
46
|
+
export declare const subscribeSSE: (url: string, callbacks: HunterSSECallbackType, options?: HunterSSEOptionsType) => (() => void);
|
|
19
47
|
export { ApiError } from './errors/ApiError';
|
package/lib/index.js
CHANGED
|
@@ -1,185 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
-
var src_exports = {};
|
|
29
|
-
__export(src_exports, {
|
|
30
|
-
ApiError: () => import_ApiError2.ApiError,
|
|
31
|
-
ajax: () => ajax,
|
|
32
|
-
del: () => del,
|
|
33
|
-
get: () => get,
|
|
34
|
-
graphqlQuery: () => graphqlQuery,
|
|
35
|
-
post: () => post,
|
|
36
|
-
put: () => put,
|
|
37
|
-
queryString: () => queryString,
|
|
38
|
-
removeSpaces: () => removeSpaces,
|
|
39
|
-
toGql: () => toGql
|
|
40
|
-
});
|
|
41
|
-
module.exports = __toCommonJS(src_exports);
|
|
42
|
-
var import_isArray = __toESM(require("lodash/isArray"));
|
|
43
|
-
var import_isEmpty = __toESM(require("lodash/isEmpty"));
|
|
44
|
-
var import_isNull = __toESM(require("lodash/isNull"));
|
|
45
|
-
var import_isPlainObject = __toESM(require("lodash/isPlainObject"));
|
|
46
|
-
var import_isString = __toESM(require("lodash/isString"));
|
|
47
|
-
var import_isUndefined = __toESM(require("lodash/isUndefined"));
|
|
48
|
-
var import_omit = __toESM(require("lodash/omit"));
|
|
49
|
-
var import_ApiError = require("./errors/ApiError");
|
|
50
|
-
var import_ApiError2 = require("./errors/ApiError");
|
|
51
|
-
if (typeof window === "undefined") {
|
|
52
|
-
require("cross-fetch/polyfill");
|
|
53
|
-
}
|
|
54
|
-
const removeSpaces = (str) => str.replace(/\s+(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/gm, "");
|
|
55
|
-
const queryString = (json) => Object.keys(json).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(json[key])}`).join("&");
|
|
56
|
-
const ajax = (url, method, params, options = {}) => {
|
|
57
|
-
const { headers, token } = options;
|
|
58
|
-
let formatUrl = (url || "").trim();
|
|
59
|
-
const formatToken = (token || "").trim();
|
|
60
|
-
const formatHeaders = headers || new Headers();
|
|
61
|
-
const formatMethod = (method || "GET").toUpperCase();
|
|
62
|
-
let formatParams;
|
|
63
|
-
if (params && formatMethod === "GET") {
|
|
64
|
-
formatUrl = `${formatUrl}?${queryString(params)}`;
|
|
65
|
-
formatParams = null;
|
|
66
|
-
} else if (params) {
|
|
67
|
-
formatHeaders.set("Accept", "application/json");
|
|
68
|
-
formatHeaders.set("Content-Type", "application/json");
|
|
69
|
-
formatParams = JSON.stringify(params);
|
|
70
|
-
} else {
|
|
71
|
-
formatParams = params;
|
|
72
|
-
}
|
|
73
|
-
if (!(0, import_isEmpty.default)(formatToken)) {
|
|
74
|
-
formatHeaders.set("Authorization", `Bearer ${formatToken}`);
|
|
75
|
-
}
|
|
76
|
-
let isResponseJson;
|
|
77
|
-
return fetch(formatUrl, { body: formatParams, headers: formatHeaders, method: formatMethod }).then((response) => {
|
|
78
|
-
const regex = /application\/json/i;
|
|
79
|
-
isResponseJson = regex.test(response.headers.get("Content-Type") || "");
|
|
80
|
-
if (isResponseJson) {
|
|
81
|
-
return response.json();
|
|
82
|
-
}
|
|
83
|
-
return response.text();
|
|
84
|
-
}).then((results) => {
|
|
85
|
-
if (isResponseJson) {
|
|
86
|
-
return results;
|
|
87
|
-
}
|
|
88
|
-
return results;
|
|
89
|
-
}).catch((error) => {
|
|
90
|
-
if ((error || {}).message === "only absolute urls are supported") {
|
|
91
|
-
return Promise.reject(new import_ApiError.ApiError([{ message: "invalid_url" }], error));
|
|
92
|
-
}
|
|
93
|
-
return Promise.reject(new import_ApiError.ApiError([{ message: "network_error" }], error));
|
|
94
|
-
});
|
|
95
|
-
};
|
|
96
|
-
const get = (url, params, options) => ajax(url, "GET", params, options);
|
|
97
|
-
const post = (url, params, options) => ajax(url, "POST", params, options);
|
|
98
|
-
const put = (url, params, options) => ajax(url, "PUT", params, options);
|
|
99
|
-
const del = (url, params, options) => ajax(url, "DELETE", params, options);
|
|
100
|
-
const toGql = (obj) => {
|
|
101
|
-
if ((0, import_isString.default)(obj)) {
|
|
102
|
-
return JSON.stringify(obj);
|
|
103
|
-
} else if ((0, import_isPlainObject.default)(obj)) {
|
|
104
|
-
let cleanObj = (0, import_omit.default)(obj, import_isUndefined.default);
|
|
105
|
-
cleanObj = (0, import_omit.default)(cleanObj, import_isNull.default);
|
|
106
|
-
const gqlProps = Object.keys(cleanObj).reduce((props, key) => {
|
|
107
|
-
const item = obj[key];
|
|
108
|
-
if ((0, import_isPlainObject.default)(item)) {
|
|
109
|
-
props.push(toGql(item));
|
|
110
|
-
} else if ((0, import_isArray.default)(item)) {
|
|
111
|
-
const list = item.map((listItem) => toGql(listItem));
|
|
112
|
-
props.push(`${key}: [${list.join(", ")}]`);
|
|
113
|
-
} else {
|
|
114
|
-
const val = JSON.stringify(item);
|
|
115
|
-
if (val) {
|
|
116
|
-
props.push(`${key}: ${val}`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return props;
|
|
120
|
-
}, []);
|
|
121
|
-
const values = gqlProps.join(", ");
|
|
122
|
-
if (values === "") {
|
|
123
|
-
return '""';
|
|
124
|
-
}
|
|
125
|
-
return `{${gqlProps.join(", ")}}`;
|
|
126
|
-
} else if ((0, import_isArray.default)(obj)) {
|
|
127
|
-
return `[${obj.map((objItem) => toGql(objItem)).toString()}]`;
|
|
128
|
-
}
|
|
129
|
-
return obj;
|
|
130
|
-
};
|
|
131
|
-
const graphqlQuery = (url, query, options = {}) => {
|
|
132
|
-
const { headers, token } = options;
|
|
133
|
-
const formatUrl = url ? url.trim() : "";
|
|
134
|
-
const formatToken = (token || "").trim();
|
|
135
|
-
const formatHeaders = headers || new Headers({ "Content-Type": "application/json" });
|
|
136
|
-
if (formatToken !== "") {
|
|
137
|
-
formatHeaders.set("Authorization", `Bearer ${formatToken}`);
|
|
138
|
-
}
|
|
139
|
-
return fetch(formatUrl, { body: JSON.stringify(query), headers: formatHeaders, method: "post" }).then((response) => {
|
|
140
|
-
const regex = /application\/json/i;
|
|
141
|
-
const isJson = regex.test(response.headers.get("Content-Type") || "");
|
|
142
|
-
if (isJson && response.body) {
|
|
143
|
-
return response.json();
|
|
144
|
-
}
|
|
145
|
-
return null;
|
|
146
|
-
}).catch((error) => {
|
|
147
|
-
if ((error || {}).message === "only absolute urls are supported") {
|
|
148
|
-
return Promise.reject(new import_ApiError.ApiError([{ message: "invalid_url" }], error));
|
|
149
|
-
}
|
|
150
|
-
return Promise.reject(new import_ApiError.ApiError([{ message: "network_error" }], error));
|
|
151
|
-
}).then((json) => {
|
|
152
|
-
let updatedJson = {};
|
|
153
|
-
if (!json || json.errors) {
|
|
154
|
-
if (!json) {
|
|
155
|
-
return Promise.reject(new import_ApiError.ApiError([{ message: "api_error" }], new Error()));
|
|
156
|
-
} else if ((json.errors || []).some((error) => error.message === "Must provide query string.")) {
|
|
157
|
-
return Promise.reject(new import_ApiError.ApiError([{ message: "required_query" }], new Error()));
|
|
158
|
-
}
|
|
159
|
-
return json.errors ? Promise.reject(new import_ApiError.ApiError(json.errors, new Error())) : updatedJson;
|
|
160
|
-
} else if (json) {
|
|
161
|
-
updatedJson = { ...json };
|
|
162
|
-
}
|
|
163
|
-
return updatedJson.data || {};
|
|
164
|
-
}).catch((error) => {
|
|
165
|
-
let updatedError = error;
|
|
166
|
-
if (!error.source) {
|
|
167
|
-
updatedError = new import_ApiError.ApiError([{ message: "network_error" }], error);
|
|
168
|
-
}
|
|
169
|
-
return Promise.reject(updatedError);
|
|
170
|
-
});
|
|
171
|
-
};
|
|
172
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
173
|
-
0 && (module.exports = {
|
|
174
|
-
ApiError,
|
|
175
|
-
ajax,
|
|
176
|
-
del,
|
|
177
|
-
get,
|
|
178
|
-
graphqlQuery,
|
|
179
|
-
post,
|
|
180
|
-
put,
|
|
181
|
-
queryString,
|
|
182
|
-
removeSpaces,
|
|
183
|
-
toGql
|
|
184
|
-
});
|
|
185
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIENvcHlyaWdodCAoYykgMjAxNy1QcmVzZW50LCBOaXRyb2dlbiBMYWJzLCBJbmMuXG4gKiBDb3B5cmlnaHRzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIHRoZSBhY2NvbXBhbnlpbmcgTElDRU5TRSBmaWxlIGZvciB0ZXJtcy5cbiAqL1xuaW1wb3J0IGlzQXJyYXkgZnJvbSAnbG9kYXNoL2lzQXJyYXknO1xuaW1wb3J0IGlzRW1wdHkgZnJvbSAnbG9kYXNoL2lzRW1wdHknO1xuaW1wb3J0IGlzTnVsbCBmcm9tICdsb2Rhc2gvaXNOdWxsJztcbmltcG9ydCBpc1BsYWluT2JqZWN0IGZyb20gJ2xvZGFzaC9pc1BsYWluT2JqZWN0JztcbmltcG9ydCBpc1N0cmluZyBmcm9tICdsb2Rhc2gvaXNTdHJpbmcnO1xuaW1wb3J0IGlzVW5kZWZpbmVkIGZyb20gJ2xvZGFzaC9pc1VuZGVmaW5lZCc7XG5pbXBvcnQgb21pdCBmcm9tICdsb2Rhc2gvb21pdCc7XG5cbmltcG9ydCB7QXBpRXJyb3J9IGZyb20gJy4vZXJyb3JzL0FwaUVycm9yJztcblxuaWYodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgcmVxdWlyZSgnY3Jvc3MtZmV0Y2gvcG9seWZpbGwnKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIdW50ZXJPcHRpb25zVHlwZSB7XG4gIHJlYWRvbmx5IGhlYWRlcnM/OiBIZWFkZXJzO1xuICByZWFkb25seSB0b2tlbj86IHN0cmluZztcbiAgcmVhZG9ubHkgdmFyaWFibGVzPzogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEh1bnRlclF1ZXJ5VHlwZSB7XG4gIHJlYWRvbmx5IHF1ZXJ5OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHZhcmlhYmxlcz86IGFueTtcbn1cblxuLyoqXG4gKiBKUyB1dGlsaXRpZXMgZm9yIEdyYXBoUUxcbiAqL1xuZXhwb3J0IGNvbnN0IHJlbW92ZVNwYWNlcyA9IChzdHI6IHN0cmluZyk6IHN0cmluZyA9PiBzdHIucmVwbGFjZSgvXFxzKyg/PSg/OlteJ1wiXSpbJ1wiXVteJ1wiXSpbJ1wiXSkqW14nXCJdKiQpL2dtLCAnJyk7XG5cbmV4cG9ydCBjb25zdCBxdWVyeVN0cmluZyA9IChqc29uOiBhbnkpOiBzdHJpbmcgPT4gT2JqZWN0XG4gIC5rZXlzKGpzb24pXG4gIC5tYXAoKGtleTogc3RyaW5nKSA9PiBgJHtlbmNvZGVVUklDb21wb25lbnQoa2V5KX09JHtlbmNvZGVVUklDb21wb25lbnQoanNvbltrZXldKX1gKS5qb2luKCcmJyk7XG5cbi8vIEFKQVhcbmV4cG9ydCBjb25zdCBhamF4ID0gKHVybDogc3RyaW5nLCBtZXRob2Q6IHN0cmluZywgcGFyYW1zPywgb3B0aW9uczogSHVudGVyT3B0aW9uc1R5cGUgPSB7fSk6IFByb21pc2U8YW55PiA9PiB7XG4gIGNvbnN0IHtoZWFkZXJzLCB0b2tlbn0gPSBvcHRpb25zO1xuXG4gIGxldCBmb3JtYXRVcmw6IHN0cmluZyA9ICh1cmwgfHwgJycpLnRyaW0oKTtcbiAgY29uc3QgZm9ybWF0VG9rZW46IHN0cmluZyA9ICh0b2tlbiB8fCAnJykudHJpbSgpO1xuICBjb25zdCBmb3JtYXRIZWFkZXJzOiBIZWFkZXJzID0gaGVhZGVycyB8fCBuZXcgSGVhZGVycygpO1xuXG4gIC8vIE1ldGhvZFxuICBjb25zdCBmb3JtYXRNZXRob2Q6IHN0cmluZyA9IChtZXRob2QgfHwgJ0dFVCcpLnRvVXBwZXJDYXNlKCk7XG4gIGxldCBmb3JtYXRQYXJhbXM7XG5cbiAgLy8gUGFyYW1ldGVyc1xuICBpZihwYXJhbXMgJiYgZm9ybWF0TWV0aG9kID09PSAnR0VUJykge1xuICAgIGZvcm1hdFVybCA9IGAke2Zvcm1hdFVybH0/JHtxdWVyeVN0cmluZyhwYXJhbXMpfWA7XG4gICAgZm9ybWF0UGFyYW1zID0gbnVsbDtcbiAgfSBlbHNlIGlmKHBhcmFtcykge1xuICAgIGZvcm1hdEhlYWRlcnMuc2V0KCdBY2NlcHQnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgIGZvcm1hdEhlYWRlcnMuc2V0KCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgIGZvcm1hdFBhcmFtcyA9IEpTT04uc3RyaW5naWZ5KHBhcmFtcyk7XG4gIH0gZWxzZSB7XG4gICAgZm9ybWF0UGFyYW1zID0gcGFyYW1zO1xuICB9XG5cbiAgLy8gQXV0aGVudGljYXRpb24gdG9rZW5cbiAgaWYoIWlzRW1wdHkoZm9ybWF0VG9rZW4pKSB7XG4gICAgZm9ybWF0SGVhZGVycy5zZXQoJ0F1dGhvcml6YXRpb24nLCBgQmVhcmVyICR7Zm9ybWF0VG9rZW59YCk7XG4gIH1cblxuICBsZXQgaXNSZXNwb25zZUpzb246IGJvb2xlYW47XG5cbiAgcmV0dXJuIGZldGNoKGZvcm1hdFVybCwge2JvZHk6IGZvcm1hdFBhcmFtcywgaGVhZGVyczogZm9ybWF0SGVhZGVycywgbWV0aG9kOiBmb3JtYXRNZXRob2R9KVxuICAgIC50aGVuKChyZXNwb25zZTogUmVzcG9uc2UpID0+IHtcbiAgICAgIGNvbnN0IHJlZ2V4ID0gL2FwcGxpY2F0aW9uXFwvanNvbi9pO1xuXG4gICAgICAvLyBDaGVjayBpZiByZXNwb25zZSBpcyBqc29uXG4gICAgICBpc1Jlc3BvbnNlSnNvbiA9IHJlZ2V4LnRlc3QocmVzcG9uc2UuaGVhZGVycy5nZXQoJ0NvbnRlbnQtVHlwZScpIHx8ICcnKTtcblxuICAgICAgaWYoaXNSZXNwb25zZUpzb24pIHtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3BvbnNlLnRleHQoKTtcbiAgICB9KVxuICAgIC50aGVuKChyZXN1bHRzKSA9PiB7XG4gICAgICBpZihpc1Jlc3BvbnNlSnNvbikge1xuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICBpZigoZXJyb3IgfHwge30pLm1lc3NhZ2UgPT09ICdvbmx5IGFic29sdXRlIHVybHMgYXJlIHN1cHBvcnRlZCcpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBBcGlFcnJvcihbe21lc3NhZ2U6ICdpbnZhbGlkX3VybCd9XSwgZXJyb3IpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBBcGlFcnJvcihbe21lc3NhZ2U6ICduZXR3b3JrX2Vycm9yJ31dLCBlcnJvcikpO1xuICAgIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldCA9ICh1cmw6IHN0cmluZywgcGFyYW1zPywgb3B0aW9ucz86IEh1bnRlck9wdGlvbnNUeXBlKTogUHJvbWlzZTxhbnk+ID0+IGFqYXgodXJsLCAnR0VUJywgcGFyYW1zLCBvcHRpb25zKTtcblxuZXhwb3J0IGNvbnN0IHBvc3QgPSAodXJsOiBzdHJpbmcsIHBhcmFtcz8sIG9wdGlvbnM/OiBIdW50ZXJPcHRpb25zVHlwZSk6IFByb21pc2U8YW55PiA9PiBhamF4KHVybCwgJ1BPU1QnLCBwYXJhbXMsIG9wdGlvbnMpO1xuXG5leHBvcnQgY29uc3QgcHV0ID0gKHVybDogc3RyaW5nLCBwYXJhbXM/LCBvcHRpb25zPzogSHVudGVyT3B0aW9uc1R5cGUpOiBQcm9taXNlPGFueT4gPT4gYWpheCh1cmwsICdQVVQnLCBwYXJhbXMsIG9wdGlvbnMpO1xuXG5leHBvcnQgY29uc3QgZGVsID0gKHVybDogc3RyaW5nLCBwYXJhbXM/LCBvcHRpb25zPzogSHVudGVyT3B0aW9uc1R5cGUpOiBQcm9taXNlPGFueT4gPT4gYWpheCh1cmwsICdERUxFVEUnLCBwYXJhbXMsIG9wdGlvbnMpO1xuXG4vLyBHcmFwaFFMXG5leHBvcnQgY29uc3QgdG9HcWwgPSAob2JqOiBhbnkpOiBzdHJpbmcgPT4ge1xuICBpZihpc1N0cmluZyhvYmopKSB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaik7XG4gIH0gZWxzZSBpZihpc1BsYWluT2JqZWN0KG9iaikpIHtcbiAgICBsZXQgY2xlYW5PYmogPSBvbWl0KG9iaiwgaXNVbmRlZmluZWQpO1xuICAgIGNsZWFuT2JqID0gb21pdChjbGVhbk9iaiwgaXNOdWxsKTtcblxuICAgIGNvbnN0IGdxbFByb3BzOiBzdHJpbmdbXSA9IE9iamVjdC5rZXlzKGNsZWFuT2JqKS5yZWR1Y2UoKHByb3BzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGl0ZW0gPSBvYmpba2V5XTtcblxuICAgICAgaWYoaXNQbGFpbk9iamVjdChpdGVtKSkge1xuICAgICAgICBwcm9wcy5wdXNoKHRvR3FsKGl0ZW0pKTtcbiAgICAgIH0gZWxzZSBpZihpc0FycmF5KGl0ZW0pKSB7XG4gICAgICAgIGNvbnN0IGxpc3QgPSBpdGVtLm1hcCgobGlzdEl0ZW0pID0+IHRvR3FsKGxpc3RJdGVtKSk7XG4gICAgICAgIHByb3BzLnB1c2goYCR7a2V5fTogWyR7bGlzdC5qb2luKCcsICcpfV1gKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHZhbCA9IEpTT04uc3RyaW5naWZ5KGl0ZW0pO1xuXG4gICAgICAgIGlmKHZhbCkge1xuICAgICAgICAgIHByb3BzLnB1c2goYCR7a2V5fTogJHt2YWx9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHByb3BzO1xuICAgIH0sIFtdKTtcblxuICAgIGNvbnN0IHZhbHVlcyA9IGdxbFByb3BzLmpvaW4oJywgJyk7XG5cbiAgICBpZih2YWx1ZXMgPT09ICcnKSB7XG4gICAgICByZXR1cm4gJ1wiXCInO1xuICAgIH1cblxuICAgIHJldHVybiBgeyR7Z3FsUHJvcHMuam9pbignLCAnKX19YDtcbiAgfSBlbHNlIGlmKGlzQXJyYXkob2JqKSkge1xuICAgIHJldHVybiBgWyR7b2JqLm1hcCgob2JqSXRlbSkgPT4gdG9HcWwob2JqSXRlbSkpLnRvU3RyaW5nKCl9XWA7XG4gIH1cblxuICByZXR1cm4gb2JqO1xufTtcblxuZXhwb3J0IGNvbnN0IGdyYXBocWxRdWVyeSA9IChcbiAgdXJsOiBzdHJpbmcsXG4gIHF1ZXJ5OiBIdW50ZXJRdWVyeVR5cGUgfCBIdW50ZXJRdWVyeVR5cGVbXSxcbiAgb3B0aW9uczogSHVudGVyT3B0aW9uc1R5cGUgPSB7fVxuKTogUHJvbWlzZTxhbnk+ID0+IHtcbiAgY29uc3Qge2hlYWRlcnMsIHRva2VufSA9IG9wdGlvbnM7XG4gIGNvbnN0IGZvcm1hdFVybDogc3RyaW5nID0gdXJsID8gdXJsLnRyaW0oKSA6ICcnO1xuICBjb25zdCBmb3JtYXRUb2tlbjogc3RyaW5nID0gKHRva2VuIHx8ICcnKS50cmltKCk7XG4gIGNvbnN0IGZvcm1hdEhlYWRlcnM6IEhlYWRlcnMgPSBoZWFkZXJzIHx8IG5ldyBIZWFkZXJzKHsnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nfSk7XG5cbiAgaWYoZm9ybWF0VG9rZW4gIT09ICcnKSB7XG4gICAgZm9ybWF0SGVhZGVycy5zZXQoJ0F1dGhvcml6YXRpb24nLCBgQmVhcmVyICR7Zm9ybWF0VG9rZW59YCk7XG4gIH1cblxuICByZXR1cm4gZmV0Y2goZm9ybWF0VXJsLCB7Ym9keTogSlNPTi5zdHJpbmdpZnkocXVlcnkpLCBoZWFkZXJzOiBmb3JtYXRIZWFkZXJzLCBtZXRob2Q6ICdwb3N0J30pXG4gICAgLnRoZW4oKHJlc3BvbnNlOiBSZXNwb25zZSkgPT4ge1xuICAgICAgY29uc3QgcmVnZXg6IFJlZ0V4cCA9IC9hcHBsaWNhdGlvblxcL2pzb24vaTtcbiAgICAgIGNvbnN0IGlzSnNvbjogYm9vbGVhbiA9IHJlZ2V4LnRlc3QocmVzcG9uc2UuaGVhZGVycy5nZXQoJ0NvbnRlbnQtVHlwZScpIHx8ICcnKTtcblxuICAgICAgaWYoaXNKc29uICYmIHJlc3BvbnNlLmJvZHkpIHtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7IC8vIHtkYXRhOiB7fX07XG4gICAgfSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICBpZigoZXJyb3IgfHwge30pLm1lc3NhZ2UgPT09ICdvbmx5IGFic29sdXRlIHVybHMgYXJlIHN1cHBvcnRlZCcpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBBcGlFcnJvcihbe21lc3NhZ2U6ICdpbnZhbGlkX3VybCd9XSwgZXJyb3IpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBBcGlFcnJvcihbe21lc3NhZ2U6ICduZXR3b3JrX2Vycm9yJ31dLCBlcnJvcikpO1xuICAgIH0pXG4gICAgLnRoZW4oKGpzb24pID0+IHtcbiAgICAgIGxldCB1cGRhdGVkSnNvbjogYW55ID0ge307XG5cbiAgICAgIGlmKCFqc29uIHx8IGpzb24uZXJyb3JzKSB7XG4gICAgICAgIGlmKCFqc29uKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBBcGlFcnJvcihbe21lc3NhZ2U6ICdhcGlfZXJyb3InfV0sIG5ldyBFcnJvcigpKSk7XG4gICAgICAgIH0gZWxzZSBpZigoanNvbi5lcnJvcnMgfHwgW10pLnNvbWUoKGVycm9yKSA9PiBlcnJvci5tZXNzYWdlID09PSAnTXVzdCBwcm92aWRlIHF1ZXJ5IHN0cmluZy4nKSkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgQXBpRXJyb3IoW3ttZXNzYWdlOiAncmVxdWlyZWRfcXVlcnknfV0sIG5ldyBFcnJvcigpKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ganNvbi5lcnJvcnMgPyBQcm9taXNlLnJlamVjdChuZXcgQXBpRXJyb3IoanNvbi5lcnJvcnMsIG5ldyBFcnJvcigpKSkgOiB1cGRhdGVkSnNvbjtcbiAgICAgIH0gZWxzZSBpZihqc29uKSB7XG4gICAgICAgIHVwZGF0ZWRKc29uID0gey4uLmpzb259O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdXBkYXRlZEpzb24uZGF0YSB8fCB7fTtcbiAgICB9KVxuICAgIC5jYXRjaCgoZXJyb3I6IEFwaUVycm9yKSA9PiB7XG4gICAgICBsZXQgdXBkYXRlZEVycm9yID0gZXJyb3I7XG5cbiAgICAgIGlmKCFlcnJvci5zb3VyY2UpIHtcbiAgICAgICAgdXBkYXRlZEVycm9yID0gbmV3IEFwaUVycm9yKFt7bWVzc2FnZTogJ25ldHdvcmtfZXJyb3InfV0sIGVycm9yKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHVwZGF0ZWRFcnJvcik7XG4gICAgfSk7XG59O1xuXG5leHBvcnQge0FwaUVycm9yfSBmcm9tICcuL2Vycm9ycy9BcGlFcnJvcic7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBSUEscUJBQW9CO0FBQ3BCLHFCQUFvQjtBQUNwQixvQkFBbUI7QUFDbkIsMkJBQTBCO0FBQzFCLHNCQUFxQjtBQUNyQix5QkFBd0I7QUFDeEIsa0JBQWlCO0FBRWpCLHNCQUF1QjtBQW1NdkIsSUFBQUEsbUJBQXVCO0FBak12QixJQUFHLE9BQU8sV0FBVyxhQUFhO0FBQ2hDLFVBQVEsc0JBQXNCO0FBQ2hDO0FBZ0JPLE1BQU0sZUFBZSxDQUFDLFFBQXdCLElBQUksUUFBUSw2Q0FBNkMsRUFBRTtBQUV6RyxNQUFNLGNBQWMsQ0FBQyxTQUFzQixPQUMvQyxLQUFLLElBQUksRUFDVCxJQUFJLENBQUMsUUFBZ0IsR0FBRyxtQkFBbUIsR0FBRyxLQUFLLG1CQUFtQixLQUFLLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxHQUFHO0FBR3hGLE1BQU0sT0FBTyxDQUFDLEtBQWEsUUFBZ0IsUUFBUyxVQUE2QixDQUFDLE1BQW9CO0FBQzNHLFFBQU0sRUFBQyxTQUFTLE1BQUssSUFBSTtBQUV6QixNQUFJLGFBQXFCLE9BQU8sSUFBSSxLQUFLO0FBQ3pDLFFBQU0sZUFBdUIs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YSxDQUFDLEdBQUcsS0FBSyxDQUFDO0FBQUEsSUFDdkU7QUFFQSxXQUFPLFFBQVEsT0FBTyxJQUFJLHlCQUFTLENBQUMsRUFBQyxTQUFTLGdCQUFlLENBQUMsR0FBRyxLQUFLLENBQUM7QUFBQSxFQUN6RSxDQUFDLEVBQ0EsS0FBSyxDQUFDLFNBQVM7QUFDZCxRQUFJLGNBQW1CLENBQUM7QUFFeEIsUUFBRyxDQUFDLFFBQVEsS0FBSyxRQUFRO0FBQ3ZCLFVBQUcsQ0FBQyxNQUFNO0FBQ1IsZUFBTyxRQUFRLE9BQU8sSUFBSSx5QkFBUyxDQUFDLEVBQUMsU0FBUyxZQUFXLENBQUMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxDQUFDO0FBQUEsTUFDM0UsWUFBVyxLQUFLLFVBQVUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxVQUFVLE1BQU0sWUFBWSw0QkFBNEIsR0FBRztBQUM3RixlQUFPLFFBQVEsT0FBTyxJQUFJLHlCQUFTLENBQUMsRUFBQyxTQUFTLGlCQUFnQixDQUFDLEdBQUcsSUFBSSxNQUFNLENBQUMsQ0FBQztBQUFBLE1BQ2hGO0FBRUEsYUFBTyxLQUFLLFNBQVMsUUFBUSxPQUFPLElBQUkseUJBQVMsS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLENBQUMsSUFBSTtBQUFBLElBQ2hGLFdBQVUsTUFBTTtBQUNkLG9CQUFjLEVBQUMsR0FBRyxLQUFJO0FBQUEsSUFDeEI7QUFFQSxXQUFPLFlBQVksUUFBUSxDQUFDO0FBQUEsRUFDOUIsQ0FBQyxFQUNBLE1BQU0sQ0FBQyxVQUFvQjtBQUMxQixRQUFJLGVBQWU7QUFFbkIsUUFBRyxDQUFDLE1BQU0sUUFBUTtBQUNoQixxQkFBZSxJQUFJLHlCQUFTLENBQUMsRUFBQyxTQUFTLGdCQUFlLENBQUMsR0FBRyxLQUFLO0FBQUEsSUFDakU7QUFFQSxXQUFPLFFBQVEsT0FBTyxZQUFZO0FBQUEsRUFDcEMsQ0FBQztBQUNMOyIsCiAgIm5hbWVzIjogWyJpbXBvcnRfQXBpRXJyb3IiLCAiaXNFbXB0eSIsICJpc1N0cmluZyIsICJpc1BsYWluT2JqZWN0IiwgIm9taXQiLCAiaXNVbmRlZmluZWQiLCAiaXNOdWxsIiwgImlzQXJyYXkiXQp9Cg==
|
|
1
|
+
import{ApiError as l}from"./errors/ApiError";import{ApiError as B}from"./errors/ApiError";const v=e=>Array.isArray(e),q=e=>typeof e=="string",P=e=>e!==null&&typeof e=="object"&&!v(e),H=e=>e==null||e==="",C=e=>e===null,R=e=>e===void 0,w=/application\/json/i,S=new Map,A=e=>e.replace(/\s+(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/gm,""),J=e=>Object.keys(e).map(r=>`${encodeURIComponent(r)}=${encodeURIComponent(e[r])}`).join("&"),x=e=>new Promise((r,t)=>setTimeout(()=>t(new Error("Request timeout")),e)),O=(e,r,t,i)=>{const a=JSON.stringify({method:r,options:i,params:t,url:e});return btoa(a).slice(0,50)},N=(e,r)=>{if(typeof EventSource<"u")return new EventSource(e);throw new Error('EventSource not available in this environment. For Node.js support, install the "eventsource" package and import it manually.')},T=(e,r,t,i={})=>{const{headers:a,token:c,timeout:m=3e4,cache:f=!1}=i;let p=(e||"").trim();const d=(c||"").trim(),n=a||new Headers,u=(r||"GET").toUpperCase();let s;if(t&&u==="GET"?(p=`${p}?${J(t)}`,s=null):t?(n.set("Accept","application/json"),n.set("Content-Type","application/json"),s=JSON.stringify(t)):s=t,H(d)||n.set("Authorization",`Bearer ${d}`),f&&u==="GET"){const o=O(p,u,t,i),E=S.get(o);if(E)return E}const y=fetch(p,{body:s,headers:n,method:u}).then(o=>w.test(o.headers.get("Content-Type")||"")?o.json():o.text()).then(o=>o).catch(o=>(o||{}).message==="only absolute urls are supported"?Promise.reject(new l([{message:"invalid_url"}],o)):Promise.reject(new l([{message:"network_error"}],o))),g=m>0?Promise.race([y,x(m)]):y;if(f&&u==="GET"){const o=O(p,u,t,i);S.set(o,g),setTimeout(()=>S.delete(o),3e5)}return g},j=(e,r,t)=>T(e,"GET",r,t),b=(e,r,t)=>T(e,"POST",r,t),U=(e,r,t)=>T(e,"PUT",r,t),G=(e,r,t)=>T(e,"DELETE",r,t),h=e=>{if(q(e))return JSON.stringify(e);if(P(e)){const r=[];for(const i in e)if(e.hasOwnProperty(i)){const a=e[i];if(R(a)||C(a))continue;if(P(a))r.push(`${i}: ${h(a)}`);else if(v(a)){const c=a.map(m=>h(m));r.push(`${i}: [${c.join(", ")}]`)}else{const c=JSON.stringify(a);c&&r.push(`${i}: ${c}`)}}return r.join(", ")===""?'""':`{${r.join(", ")}}`}else if(v(e))return`[${e.map(r=>h(r)).join(", ")}]`;return String(e)},$=(e,r,t={})=>{const{headers:i,token:a,timeout:c=3e4}=t,m=e?e.trim():"",f=(a||"").trim(),p=i||new Headers({"Content-Type":"application/json"});H(f)||p.set("Authorization",`Bearer ${f}`);const d=fetch(m,{body:JSON.stringify(r),headers:p,method:"post"}).then(n=>w.test(n.headers.get("Content-Type")||"")&&n.body?n.json():null).catch(n=>(n||{}).message==="only absolute urls are supported"?Promise.reject(new l([{message:"invalid_url"}],n)):Promise.reject(new l([{message:"network_error"}],n))).then(n=>{if(!n||n.errors){if(n){if((n.errors||[]).some(u=>u.message==="Must provide query string."))return Promise.reject(new l([{message:"required_query"}],new Error))}else return Promise.reject(new l([{message:"api_error"}],new Error));return n.errors?Promise.reject(new l(n.errors,new Error)):{}}return n.data||{}}).catch(n=>Promise.reject(n.source?n:new l([{message:"network_error"}],n)));return c>0?Promise.race([d,x(c)]):d},I=(e,r,t={})=>$(e,{query:r},t),M=(e,r,t={})=>$(e,{query:r},t),Q=(e,r,t={})=>{const{headers:i,token:a,timeout:c=3e4,retryInterval:m=1e3,maxRetries:f=5}=t,p=(e||"").trim(),d=(a||"").trim(),n=i||new Headers;H(d)||n.set("Authorization",`Bearer ${d}`);let u=0,s=null,y=null;const g=()=>{try{s=N(p,{headers:n}),c>0&&(y=setTimeout(()=>{s&&(s.close(),r.onError&&r.onError(new Error("SSE connection timeout")))},c)),s.onopen=o=>{y&&(clearTimeout(y),y=null),u=0,r.onOpen&&r.onOpen(o)},s.onmessage=o=>{if(r.onMessage){const E={data:o.data,id:o.lastEventId,retry:o.data.includes("retry:")?parseInt(o.data.split("retry:")[1]):void 0,type:o.type};r.onMessage(E)}},s.onerror=o=>{y&&(clearTimeout(y),y=null),s&&s.readyState===EventSource.CLOSED?u<f?(u++,r.onRetry&&r.onRetry(u,m),setTimeout(g,m)):r.onError&&r.onError(new Error("SSE connection failed after max retries")):r.onError&&r.onError(o)}}catch(o){r.onError&&r.onError(o instanceof Error?o:new Error("Failed to create SSE connection"))}};return g(),()=>{y&&(clearTimeout(y),y=null),s&&(s.close(),s=null)}};export{B as ApiError,T as ajax,G as del,j as get,$ as graphqlQuery,M as mutation,b as post,U as put,I as query,J as queryString,A as removeSpaces,Q as subscribeSSE,h as toGql};
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIENvcHlyaWdodCAoYykgMjAxNy1QcmVzZW50LCBOaXRyb2dlbiBMYWJzLCBJbmMuXG4gKiBDb3B5cmlnaHRzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIHRoZSBhY2NvbXBhbnlpbmcgTElDRU5TRSBmaWxlIGZvciB0ZXJtcy5cbiAqL1xuXG5pbXBvcnQge0FwaUVycm9yfSBmcm9tICcuL2Vycm9ycy9BcGlFcnJvcic7XG5cbmNvbnN0IGlzQXJyYXkgPSAodmFsdWU6IGFueSk6IHZhbHVlIGlzIGFueVtdID0+IEFycmF5LmlzQXJyYXkodmFsdWUpO1xuY29uc3QgaXNTdHJpbmcgPSAodmFsdWU6IGFueSk6IHZhbHVlIGlzIHN0cmluZyA9PiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xuY29uc3QgaXNQbGFpbk9iamVjdCA9ICh2YWx1ZTogYW55KTogdmFsdWUgaXMgUmVjb3JkPHN0cmluZywgYW55PiA9PlxuICB2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmICFpc0FycmF5KHZhbHVlKTtcbmNvbnN0IGlzRW1wdHkgPSAodmFsdWU6IGFueSk6IGJvb2xlYW4gPT5cbiAgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJyc7XG5jb25zdCBpc051bGwgPSAodmFsdWU6IGFueSk6IGJvb2xlYW4gPT4gdmFsdWUgPT09IG51bGw7XG5jb25zdCBpc1VuZGVmaW5lZCA9ICh2YWx1ZTogYW55KTogYm9vbGVhbiA9PiB2YWx1ZSA9PT0gdW5kZWZpbmVkO1xuXG4vLyBDYWNoZSBmb3IgY29tcGlsZWQgcmVnZXggcGF0dGVybnNcbmNvbnN0IEpTT05fQ09OVEVOVF9UWVBFX1JFR0VYID0gL2FwcGxpY2F0aW9uXFwvanNvbi9pO1xuXG4vLyBSZXF1ZXN0IGNhY2hlIGZvciBkZWR1cGxpY2F0aW9uXG5jb25zdCByZXF1ZXN0Q2FjaGUgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxhbnk+PigpO1xuXG5leHBvcnQgaW50ZXJmYWNlIEh1bnRlck9wdGlvbnNUeXBlIHtcbiAgcmVhZG9ubHkgaGVhZGVycz86IEhlYWRlcnM7XG4gIHJlYWRvbmx5IHRva2VuPzogc3RyaW5nO1xuICByZWFkb25seSB2YXJpYWJsZXM/OiBhbnk7XG4gIHJlYWRvbmx5IHRpbWVvdXQ/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGNhY2hlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIdW50ZXJRdWVyeVR5cGUge1xuICByZWFkb25seSBxdWVyeTogc3RyaW5nO1xuICByZWFkb25seSB2YXJpYWJsZXM/OiBhbnk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSHVudGVyU1NFT3B0aW9uc1R5cGUge1xuICByZWFkb25seSBoZWFkZXJzPzogSGVhZGVycztcbiAgcmVhZG9ubHkgdG9rZW4/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHRpbWVvdXQ/OiBudW1iZXI7XG4gIHJlYWRvbmx5IHJldHJ5SW50ZXJ2YWw/OiBudW1iZXI7XG4gIHJlYWRvbmx5IG1heFJldHJpZXM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSHVudGVyU1NFRXZlbnRUeXBlIHtcbiAgcmVhZG9ubHkgZGF0YTogc3RyaW5nO1xuICByZWFkb25seSB0eXBlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGlkPzogc3RyaW5nO1xuICByZWFkb25seSByZXRyeT86IG51bWJlciB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIdW50ZXJTU0VDYWxsYmFja1R5cGUge1xuICBvbk1lc3NhZ2U/OiAoZXZlbnQ6IEh1bnRlclNTRUV2ZW50VHlwZSkgPT4gdm9pZDtcbiAgb25PcGVuPzogKGV2ZW50OiBFdmVudCkgPT4gdm9pZDtcbiAgb25FcnJvcj86IChlcnJvcjogRXJyb3IgfCBFdmVudCkgPT4gdm9pZDtcbiAgb25SZXRyeT86IChhdHRlbXB0OiBudW1iZXIsIGRlbGF5OiBudW1iZXIpID0+IHZvaWQ7XG59XG5cbmV4cG9ydCBjb25zdCByZW1vdmVTcGFjZXMgPSAoc3RyOiBzdHJpbmcpOiBzdHJpbmcgPT5cbiAgc3RyLnJlcGxhY2UoL1xccysoPz0oPzpbXidcIl0qWydcIl1bXidcIl0qWydcIl0pKlteJ1wiXSokKS9nbSwgJycpO1xuXG5leHBvcnQgY29uc3QgcXVlcnlTdHJpbmcgPSAoanNvbjogYW55KTogc3RyaW5nID0+XG4gIE9iamVjdC5rZXlzKGpzb24pXG4gICAgLm1hcChcbiAgICAgIChrZXk6IHN0cmluZykgPT5cbiAgICAgICAgYCR7ZW5jb2RlVVJJQ29tcG9uZW50KGtleSl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KGpzb25ba2V5XSl9YFxuICAgIClcbiAgICAuam9pbignJicpO1xuXG4vLyBDcmVhdGUgYSB0aW1lb3V0IHByb21pc2VcbmNvbnN0IGNyZWF0ZVRpbWVvdXQgPSAobXM6IG51bWJlcik6IFByb21pc2U8bmV2ZXI+ID0+XG4gIG5ldyBQcm9taXNlKChfLCByZWplY3QpID0+XG4gICAgc2V0VGltZW91dCgoKSA9PiByZWplY3QobmV3IEVycm9yKCdSZXF1ZXN0IHRpbWVvdXQnKSksIG1zKVxuICApO1xuXG4vLyBHZW5lcmF0ZSBjYWNoZSBrZXkgZm9yIHJlcXVlc3QgZGVkdXBsaWNhdGlvblxuY29uc3QgZ2VuZXJhdGVDYWNoZUtleSA9ICh1cmw6IHN0cmluZywgbWV0aG9kOiBzdHJpbmcsIHBhcmFtcz86IGFueSwgb3B0aW9ucz86IEh1bnRlck9wdGlvbnNUeXBlKTogc3RyaW5nID0+IHtcbiAgY29uc3Qga2V5ID0gSlNPTi5zdHJpbmdpZnkoe21ldGhvZCwgb3B0aW9ucywgcGFyYW1zLCB1cmx9KTtcbiAgcmV0dXJuIGJ0b2Eoa2V5KS5zbGljZSgwLCA1MCk7IC8vIFRydW5jYXRlIHRvIHJlYXNvbmFibGUgbGVuZ3RoXG59O1xuXG4vLyBTU0UgRXZlbnRTb3VyY2UgcG9seWZpbGwgZm9yIE5vZGUuanNcbmNvbnN0IGNyZWF0ZUV2ZW50U291cmNlID0gKHVybDogc3RyaW5nLCBvcHRpb25zPzogSHVudGVyU1NFT3B0aW9uc1R5cGUpOiBFdmVudFNvdXJjZSA9PiB7XG4gIGlmKHR5cGVvZiBFdmVudFNvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gbmV3IEV2ZW50U291cmNlKHVybCk7XG4gIH1cblxuICAvLyBGb3IgTm9kZS5qcywgd2UnbGwgdGhyb3cgYW4gZXJyb3Igc3VnZ2VzdGluZyB0aGUgdXNlciBpbnN0YWxsIGV2ZW50c291cmNlXG4gIHRocm93IG5ldyBFcnJvcignRXZlbnRTb3VyY2Ugbm90IGF2YWlsYWJsZSBpbiB0aGlzIGVudmlyb25tZW50LiBGb3IgTm9kZS5qcyBzdXBwb3J0LCBpbnN0YWxsIHRoZSBcImV2ZW50c291cmNlXCIgcGFja2FnZSBhbmQgaW1wb3J0IGl0IG1hbnVhbGx5LicpO1xufTtcblxuLy8gQUpBWFxuZXhwb3J0IGNvbnN0IGFqYXggPSAoXG4gIHVybDogc3RyaW5nLFxuICBtZXRob2Q6IHN0cmluZyxcbiAgcGFyYW1zPyxcbiAgb3B0aW9uczogSHVudGVyT3B0aW9uc1R5cGUgPSB7fVxuKTogUHJvbWlzZTxhbnk+ID0+IHtcbiAgY29uc3Qge2hlYWRlcnMsIHRva2VuLCB0aW1lb3V0ID0gMzAwMDAsIGNhY2hlID0gZmFsc2V9ID0gb3B0aW9ucztcblxuICBsZXQgZm9ybWF0VXJsOiBzdHJpbmcgPSAodXJsIHx8ICcnKS50cmltKCk7XG4gIGNvbnN0IGZvcm1hdFRva2VuOiBzdHJpbmcgPSAodG9rZW4gfHwgJycpLnRyaW0oKTtcbiAgY29uc3QgZm9ybWF0SGVhZGVyczogSGVhZGVycyA9IGhlYWRlcnMgfHwgbmV3IEhlYWRlcnMoKTtcblxuICAvLyBNZXRob2RcbiAgY29uc3QgZm9ybWF0TWV0aG9kOiBzdHJpbmcgPSAobWV0aG9kIHx8ICdHRVQnKS50b1VwcGVyQ2FzZSgpO1xuICBsZXQgZm9ybWF0UGFyYW1zO1xuXG4gIC8vIFBhcmFtZXRlcnNcbiAgaWYocGFyYW1zICYmIGZvcm1hdE1ldGhvZCA9PT0gJ0dFVCcpIHtcbiAgICBmb3JtYXRVcmwgPSBgJHtmb3JtYXRVcmx9PyR7cXVlcnlTdHJpbmcocGFyYW1zKX1gO1xuICAgIGZvcm1hdFBhcmFtcyA9IG51bGw7XG4gIH0gZWxzZSBpZihwYXJhbXMpIHtcbiAgICBmb3JtYXRIZWFkZXJzLnNldCgnQWNjZXB0JywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcbiAgICBmb3JtYXRIZWFkZXJzLnNldCgnQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcbiAgICBmb3JtYXRQYXJhbXMgPSBKU09OLnN0cmluZ2lmeShwYXJhbXMpO1xuICB9IGVsc2Uge1xuICAgIGZvcm1hdFBhcmFtcyA9IHBhcmFtcztcbiAgfVxuXG4gIC8vIEF1dGhlbnRpY2F0aW9uIHRva2VuXG4gIGlmKCFpc0VtcHR5KGZvcm1hdFRva2VuKSkge1xuICAgIGZvcm1hdEhlYWRlcnMuc2V0KCdBdXRob3JpemF0aW9uJywgYEJlYXJlciAke2Zvcm1hdFRva2VufWApO1xuICB9XG5cbiAgLy8gQ2hlY2sgY2FjaGUgZm9yIEdFVCByZXF1ZXN0c1xuICBpZihjYWNoZSAmJiBmb3JtYXRNZXRob2QgPT09ICdHRVQnKSB7XG4gICAgY29uc3QgY2FjaGVLZXkgPSBnZW5lcmF0ZUNhY2hlS2V5KGZvcm1hdFVybCwgZm9ybWF0TWV0aG9kLCBwYXJhbXMsIG9wdGlvbnMpO1xuICAgIGNvbnN0IGNhY2hlZCA9IHJlcXVlc3RDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgIGlmKGNhY2hlZCkge1xuICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG4gIH1cblxuICAvLyBDcmVhdGUgdGhlIHJlcXVlc3QgcHJvbWlzZVxuICBjb25zdCByZXF1ZXN0UHJvbWlzZSA9IGZldGNoKGZvcm1hdFVybCwge1xuICAgIGJvZHk6IGZvcm1hdFBhcmFtcyxcbiAgICBoZWFkZXJzOiBmb3JtYXRIZWFkZXJzLFxuICAgIG1ldGhvZDogZm9ybWF0TWV0aG9kXG4gIH0pXG4gICAgLnRoZW4oKHJlc3BvbnNlOiBSZXNwb25zZSkgPT4ge1xuICAgICAgLy8gQ2hlY2sgaWYgcmVzcG9uc2UgaXMganNvbiB1c2luZyBjYWNoZWQgcmVnZXhcbiAgICAgIGNvbnN0IGlzUmVzcG9uc2VKc29uID0gSlNPTl9DT05URU5UX1RZUEVfUkVHRVgudGVzdChcbiAgICAgICAgcmVzcG9uc2UuaGVhZGVycy5nZXQoJ0NvbnRlbnQtVHlwZScpIHx8ICcnXG4gICAgICApO1xuXG4gICAgICBpZihpc1Jlc3BvbnNlSnNvbikge1xuICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgIH0pXG4gICAgLnRoZW4oKHJlc3VsdHMpID0+IHJlc3VsdHMpIC8vIFNpbXBsaWZpZWQgLSBubyBuZWVkIGZvciByZWR1bmRhbnQgY2hlY2tcbiAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICBpZigoZXJyb3IgfHwge30pLm1lc3NhZ2UgPT09ICdvbmx5IGFic29sdXRlIHVybHMgYXJlIHN1cHBvcnRlZCcpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICAgIG5ldyBBcGlFcnJvcihbe21lc3NhZ2U6ICdpbnZhbGlkX3VybCd9XSwgZXJyb3IpXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgbmV3IEFwaUVycm9yKFt7bWVzc2FnZTogJ25ldHdvcmtfZXJyb3InfV0sIGVycm9yKVxuICAgICAgKTtcbiAgICB9KTtcblxuICAvLyBBZGQgdGltZW91dCBpZiBzcGVjaWZpZWRcbiAgY29uc3QgZmluYWxQcm9taXNlID0gdGltZW91dCA+IDBcbiAgICA/IFByb21pc2UucmFjZShbcmVxdWVzdFByb21pc2UsIGNyZWF0ZVRpbWVvdXQodGltZW91dCldKVxuICAgIDogcmVxdWVzdFByb21pc2U7XG5cbiAgLy8gQ2FjaGUgdGhlIHByb21pc2UgZm9yIEdFVCByZXF1ZXN0c1xuICBpZihjYWNoZSAmJiBmb3JtYXRNZXRob2QgPT09ICdHRVQnKSB7XG4gICAgY29uc3QgY2FjaGVLZXkgPSBnZW5lcmF0ZUNhY2hlS2V5KGZvcm1hdFVybCwgZm9ybWF0TWV0aG9kLCBwYXJhbXMsIG9wdGlvbnMpO1xuICAgIHJlcXVlc3RDYWNoZS5zZXQoY2FjaGVLZXksIGZpbmFsUHJvbWlzZSk7XG5cbiAgICAvLyBDbGVhbiB1cCBjYWNoZSBhZnRlciA1IG1pbnV0ZXNcbiAgICBzZXRUaW1lb3V0KCgpID0+IHJlcXVlc3RDYWNoZS5kZWxldGUoY2FjaGVLZXkpLCAzMDAwMDApO1xuICB9XG5cbiAgcmV0dXJuIGZpbmFsUHJvbWlzZTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXQgPSAoXG4gIHVybDogc3RyaW5nLFxuICBwYXJhbXM/LFxuICBvcHRpb25zPzogSHVudGVyT3B0aW9uc1R5cGVcbik6IFByb21pc2U8YW55PiA9PiBhamF4KHVybCwgJ0dFVCcsIHBhcmFtcywgb3B0aW9ucyk7XG5cbmV4cG9ydCBjb25zdCBwb3N0ID0gKFxuICB1cmw6IHN0cmluZyxcbiAgcGFyYW1zPyxcbiAgb3B0aW9ucz86IEh1bnRlck9wdGlvbnNUeXBlXG4pOiBQcm9taXNlPGFueT4gPT4gYWpheCh1cmwsICdQT1NUJywgcGFyYW1zLCBvcHRpb25zKTtcblxuZXhwb3J0IGNvbnN0IHB1dCA9IChcbiAgdXJsOiBzdHJpbmcsXG4gIHBhcmFtcz8sXG4gIG9wdGlvbnM/OiBIdW50ZXJPcHRpb25zVHlwZVxuKTogUHJvbWlzZTxhbnk+ID0+IGFqYXgodXJsLCAnUFVUJywgcGFyYW1zLCBvcHRpb25zKTtcblxuZXhwb3J0IGNvbnN0IGRlbCA9IChcbiAgdXJsOiBzdHJpbmcsXG4gIHBhcmFtcz8sXG4gIG9wdGlvbnM/OiBIdW50ZXJPcHRpb25zVHlwZVxuKTogUHJvbWlzZTxhbnk+ID0+IGFqYXgodXJsLCAnREVMRVRFJywgcGFyYW1zLCBvcHRpb25zKTtcblxuLy8gT3B0aW1pemVkIHRvR3FsIGZ1bmN0aW9uXG5leHBvcnQgY29uc3QgdG9HcWwgPSAob2JqOiBhbnkpOiBzdHJpbmcgPT4ge1xuICBpZihpc1N0cmluZyhvYmopKSB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaik7XG4gIH0gZWxzZSBpZihpc1BsYWluT2JqZWN0KG9iaikpIHtcbiAgICAvLyBGaWx0ZXIgb3V0IHVuZGVmaW5lZCBhbmQgbnVsbCB2YWx1ZXMgaW4gb25lIHBhc3NcbiAgICBjb25zdCBncWxQcm9wczogc3RyaW5nW10gPSBbXTtcblxuICAgIGZvcihjb25zdCBrZXkgaW4gb2JqKSB7XG4gICAgICBpZihvYmouaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICBjb25zdCBpdGVtID0gb2JqW2tleV07XG5cbiAgICAgICAgLy8gU2tpcCB1bmRlZmluZWQgYW5kIG51bGwgdmFsdWVzXG4gICAgICAgIGlmKGlzVW5kZWZpbmVkKGl0ZW0pIHx8IGlzTnVsbChpdGVtKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaXNQbGFpbk9iamVjdChpdGVtKSkge1xuICAgICAgICAgIGdxbFByb3BzLnB1c2goYCR7a2V5fTogJHt0b0dxbChpdGVtKX1gKTtcbiAgICAgICAgfSBlbHNlIGlmKGlzQXJyYXkoaXRlbSkpIHtcbiAgICAgICAgICBjb25zdCBsaXN0ID0gaXRlbS5tYXAoKGxpc3RJdGVtKSA9PiB0b0dxbChsaXN0SXRlbSkpO1xuICAgICAgICAgIGdxbFByb3BzLnB1c2goYCR7a2V5fTogWyR7bGlzdC5qb2luKCcsICcpfV1gKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCB2YWwgPSBKU09OLnN0cmluZ2lmeShpdGVtKTtcbiAgICAgICAgICBpZih2YWwpIHtcbiAgICAgICAgICAgIGdxbFByb3BzLnB1c2goYCR7a2V5fTogJHt2YWx9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdmFsdWVzID0gZ3FsUHJvcHMuam9pbignLCAnKTtcbiAgICByZXR1cm4gdmFsdWVzID09PSAnJyA/ICdcIlwiJyA6IGB7JHtncWxQcm9wcy5qb2luKCcsICcpfX1gO1xuICB9IGVsc2UgaWYoaXNBcnJheShvYmopKSB7XG4gICAgcmV0dXJuIGBbJHtvYmoubWFwKChvYmpJdGVtKSA9PiB0b0dxbChvYmpJdGVtKSkuam9pbignLCAnKX1dYDtcbiAgfVxuXG4gIHJldHVybiBTdHJpbmcob2JqKTtcbn07XG5cbmV4cG9ydCBjb25zdCBncmFwaHFsUXVlcnkgPSAoXG4gIHVybDogc3RyaW5nLFxuICBxdWVyeTogSHVudGVyUXVlcnlUeXBlIHwgSHVudGVyUXVlcnlUeXBlW10sXG4gIG9wdGlvbnM6IEh1bnRlck9wdGlvbnNUeXBlID0ge31cbik6IFByb21pc2U8YW55PiA9PiB7XG4gIGNvbnN0IHtoZWFkZXJzLCB0b2tlbiwgdGltZW91dCA9IDMwMDAwfSA9IG9wdGlvbnM7XG4gIGNvbnN0IGZvcm1hdFVybDogc3RyaW5nID0gdXJsID8gdXJsLnRyaW0oKSA6ICcnO1xuICBjb25zdCBmb3JtYXRUb2tlbjogc3RyaW5nID0gKHRva2VuIHx8ICcnKS50cmltKCk7XG4gIGNvbnN0IGZvcm1hdEhlYWRlcnM6IEhlYWRlcnMgPVxuICAgIGhlYWRlcnMgfHwgbmV3IEhlYWRlcnMoeydDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbid9KTtcblxuICBpZighaXNFbXB0eShmb3JtYXRUb2tlbikpIHtcbiAgICBmb3JtYXRIZWFkZXJzLnNldCgnQXV0aG9yaXphdGlvbicsIGBCZWFyZXIgJHtmb3JtYXRUb2tlbn1gKTtcbiAgfVxuXG4gIGNvbnN0IHJlcXVlc3RQcm9taXNlID0gZmV0Y2goZm9ybWF0VXJsLCB7XG4gICAgYm9keTogSlNPTi5zdHJpbmdpZnkocXVlcnkpLFxuICAgIGhlYWRlcnM6IGZvcm1hdEhlYWRlcnMsXG4gICAgbWV0aG9kOiAncG9zdCdcbiAgfSlcbiAgICAudGhlbigocmVzcG9uc2U6IFJlc3BvbnNlKSA9PiB7XG4gICAgICBjb25zdCBpc0pzb246IGJvb2xlYW4gPSBKU09OX0NPTlRFTlRfVFlQRV9SRUdFWC50ZXN0KFxuICAgICAgICByZXNwb25zZS5oZWFkZXJzLmdldCgnQ29udGVudC1UeXBlJykgfHwgJydcbiAgICAgICk7XG5cbiAgICAgIGlmKGlzSnNvbiAmJiByZXNwb25zZS5ib2R5KSB7XG4gICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0pXG4gICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgaWYoKGVycm9yIHx8IHt9KS5tZXNzYWdlID09PSAnb25seSBhYnNvbHV0ZSB1cmxzIGFyZSBzdXBwb3J0ZWQnKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICBuZXcgQXBpRXJyb3IoW3ttZXNzYWdlOiAnaW52YWxpZF91cmwnfV0sIGVycm9yKVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgIG5ldyBBcGlFcnJvcihbe21lc3NhZ2U6ICduZXR3b3JrX2Vycm9yJ31dLCBlcnJvcilcbiAgICAgICk7XG4gICAgfSlcbiAgICAudGhlbigoanNvbikgPT4ge1xuICAgICAgaWYoIWpzb24gfHwganNvbi5lcnJvcnMpIHtcbiAgICAgICAgaWYoIWpzb24pIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgICAgICBuZXcgQXBpRXJyb3IoW3ttZXNzYWdlOiAnYXBpX2Vycm9yJ31dLCBuZXcgRXJyb3IoKSlcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYoXG4gICAgICAgICAgKGpzb24uZXJyb3JzIHx8IFtdKS5zb21lKFxuICAgICAgICAgICAgKGVycm9yKSA9PiBlcnJvci5tZXNzYWdlID09PSAnTXVzdCBwcm92aWRlIHF1ZXJ5IHN0cmluZy4nXG4gICAgICAgICAgKVxuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgICAgICBuZXcgQXBpRXJyb3IoW3ttZXNzYWdlOiAncmVxdWlyZWRfcXVlcnknfV0sIG5ldyBFcnJvcigpKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ganNvbi5lcnJvcnNcbiAgICAgICAgICA/IFByb21pc2UucmVqZWN0KG5ldyBBcGlFcnJvcihqc29uLmVycm9ycywgbmV3IEVycm9yKCkpKVxuICAgICAgICAgIDoge307XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBqc29uLmRhdGEgfHwge307XG4gICAgfSlcbiAgICAuY2F0Y2goKGVycm9yOiBBcGlFcnJvcikgPT5cbiAgICAgIC8vIFNpbXBsaWZpZWQgZXJyb3IgaGFuZGxpbmcgLSBubyBuZWVkIHRvIGNyZWF0ZSBuZXcgZXJyb3IgaWYgc291cmNlIGV4aXN0c1xuICAgICAgUHJvbWlzZS5yZWplY3QoZXJyb3Iuc291cmNlID8gZXJyb3IgOiBuZXcgQXBpRXJyb3IoW3ttZXNzYWdlOiAnbmV0d29ya19lcnJvcid9XSwgZXJyb3IpKVxuICAgICk7XG5cbiAgLy8gQWRkIHRpbWVvdXQgaWYgc3BlY2lmaWVkXG4gIHJldHVybiB0aW1lb3V0ID4gMFxuICAgID8gUHJvbWlzZS5yYWNlKFtyZXF1ZXN0UHJvbWlzZSwgY3JlYXRlVGltZW91dCh0aW1lb3V0KV0pXG4gICAgOiByZXF1ZXN0UHJvbWlzZTtcbn07XG5cbi8vIEFkZCBxdWVyeSBhbmQgbXV0YXRpb24gZnVuY3Rpb25zIGZvciBiZXR0ZXIgQVBJIGNvbnNpc3RlbmN5XG5leHBvcnQgY29uc3QgcXVlcnkgPSAoXG4gIHVybDogc3RyaW5nLFxuICBib2R5OiBzdHJpbmcsXG4gIG9wdGlvbnM6IEh1bnRlck9wdGlvbnNUeXBlID0ge31cbik6IFByb21pc2U8YW55PiA9PiBncmFwaHFsUXVlcnkodXJsLCB7cXVlcnk6IGJvZHl9LCBvcHRpb25zKTtcblxuZXhwb3J0IGNvbnN0IG11dGF0aW9uID0gKFxuICB1cmw6IHN0cmluZyxcbiAgYm9keTogc3RyaW5nLFxuICBvcHRpb25zOiBIdW50ZXJPcHRpb25zVHlwZSA9IHt9XG4pOiBQcm9taXNlPGFueT4gPT4gZ3JhcGhxbFF1ZXJ5KHVybCwge3F1ZXJ5OiBib2R5fSwgb3B0aW9ucyk7XG5cbi8vIFNTRSBTdXBwb3J0XG5leHBvcnQgY29uc3Qgc3Vic2NyaWJlU1NFID0gKFxuICB1cmw6IHN0cmluZyxcbiAgY2FsbGJhY2tzOiBIdW50ZXJTU0VDYWxsYmFja1R5cGUsXG4gIG9wdGlvbnM6IEh1bnRlclNTRU9wdGlvbnNUeXBlID0ge31cbik6ICgoKSA9PiB2b2lkKSA9PiB7XG4gIGNvbnN0IHtoZWFkZXJzLCB0b2tlbiwgdGltZW91dCA9IDMwMDAwLCByZXRyeUludGVydmFsID0gMTAwMCwgbWF4UmV0cmllcyA9IDV9ID0gb3B0aW9ucztcbiAgY29uc3QgZm9ybWF0VXJsOiBzdHJpbmcgPSAodXJsIHx8ICcnKS50cmltKCk7XG4gIGNvbnN0IGZvcm1hdFRva2VuOiBzdHJpbmcgPSAodG9rZW4gfHwgJycpLnRyaW0oKTtcbiAgY29uc3QgZm9ybWF0SGVhZGVyczogSGVhZGVycyA9IGhlYWRlcnMgfHwgbmV3IEhlYWRlcnMoKTtcblxuICAvLyBBZGQgYXV0aG9yaXphdGlvbiBoZWFkZXIgaWYgdG9rZW4gcHJvdmlkZWRcbiAgaWYoIWlzRW1wdHkoZm9ybWF0VG9rZW4pKSB7XG4gICAgZm9ybWF0SGVhZGVycy5zZXQoJ0F1dGhvcml6YXRpb24nLCBgQmVhcmVyICR7Zm9ybWF0VG9rZW59YCk7XG4gIH1cblxuICBsZXQgcmV0cnlDb3VudCA9IDA7XG4gIGxldCBldmVudFNvdXJjZTogRXZlbnRTb3VyY2UgfCBudWxsID0gbnVsbDtcbiAgbGV0IHRpbWVvdXRJZDogTm9kZUpTLlRpbWVvdXQgfCBudWxsID0gbnVsbDtcblxuICBjb25zdCBjb25uZWN0ID0gKCk6IHZvaWQgPT4ge1xuICAgIHRyeSB7XG4gICAgICBldmVudFNvdXJjZSA9IGNyZWF0ZUV2ZW50U291cmNlKGZvcm1hdFVybCwge2hlYWRlcnM6IGZvcm1hdEhlYWRlcnN9KTtcblxuICAgICAgLy8gU2V0IHVwIHRpbWVvdXRcbiAgICAgIGlmKHRpbWVvdXQgPiAwKSB7XG4gICAgICAgIHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIGlmKGV2ZW50U291cmNlKSB7XG4gICAgICAgICAgICBldmVudFNvdXJjZS5jbG9zZSgpO1xuICAgICAgICAgICAgaWYoY2FsbGJhY2tzLm9uRXJyb3IpIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2tzLm9uRXJyb3IobmV3IEVycm9yKCdTU0UgY29ubmVjdGlvbiB0aW1lb3V0JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSwgdGltZW91dCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEV2ZW50IGhhbmRsZXJzXG4gICAgICBldmVudFNvdXJjZS5vbm9wZW4gPSAoZXZlbnQpID0+IHtcbiAgICAgICAgaWYodGltZW91dElkKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAgICAgdGltZW91dElkID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXRyeUNvdW50ID0gMDsgLy8gUmVzZXQgcmV0cnkgY291bnQgb24gc3VjY2Vzc2Z1bCBjb25uZWN0aW9uXG4gICAgICAgIGlmKGNhbGxiYWNrcy5vbk9wZW4pIHtcbiAgICAgICAgICBjYWxsYmFja3Mub25PcGVuKGV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgZXZlbnRTb3VyY2Uub25tZXNzYWdlID0gKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmKGNhbGxiYWNrcy5vbk1lc3NhZ2UpIHtcbiAgICAgICAgICBjb25zdCBzc2VFdmVudDogSHVudGVyU1NFRXZlbnRUeXBlID0ge1xuICAgICAgICAgICAgZGF0YTogZXZlbnQuZGF0YSxcbiAgICAgICAgICAgIGlkOiBldmVudC5sYXN0RXZlbnRJZCxcbiAgICAgICAgICAgIHJldHJ5OiBldmVudC5kYXRhLmluY2x1ZGVzKCdyZXRyeTonKSA/IHBhcnNlSW50KGV2ZW50LmRhdGEuc3BsaXQoJ3JldHJ5OicpWzFdKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHR5cGU6IGV2ZW50LnR5cGVcbiAgICAgICAgICB9O1xuICAgICAgICAgIGNhbGxiYWNrcy5vbk1lc3NhZ2Uoc3NlRXZlbnQpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBldmVudFNvdXJjZS5vbmVycm9yID0gKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmKHRpbWVvdXRJZCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgICAgICAgIHRpbWVvdXRJZCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZihldmVudFNvdXJjZSAmJiBldmVudFNvdXJjZS5yZWFkeVN0YXRlID09PSBFdmVudFNvdXJjZS5DTE9TRUQpIHtcbiAgICAgICAgICAvLyBDb25uZWN0aW9uIGNsb3NlZCwgYXR0ZW1wdCByZXRyeSBpZiB3aXRoaW4gbGltaXRzXG4gICAgICAgICAgaWYocmV0cnlDb3VudCA8IG1heFJldHJpZXMpIHtcbiAgICAgICAgICAgIHJldHJ5Q291bnQrKztcbiAgICAgICAgICAgIGlmKGNhbGxiYWNrcy5vblJldHJ5KSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrcy5vblJldHJ5KHJldHJ5Q291bnQsIHJldHJ5SW50ZXJ2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2V0VGltZW91dChjb25uZWN0LCByZXRyeUludGVydmFsKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYoY2FsbGJhY2tzLm9uRXJyb3IpIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2tzLm9uRXJyb3IobmV3IEVycm9yKCdTU0UgY29ubmVjdGlvbiBmYWlsZWQgYWZ0ZXIgbWF4IHJldHJpZXMnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmKGNhbGxiYWNrcy5vbkVycm9yKSB7XG4gICAgICAgICAgICBjYWxsYmFja3Mub25FcnJvcihldmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgIGlmKGNhbGxiYWNrcy5vbkVycm9yKSB7XG4gICAgICAgIGNhbGxiYWNrcy5vbkVycm9yKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcignRmFpbGVkIHRvIGNyZWF0ZSBTU0UgY29ubmVjdGlvbicpKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLy8gU3RhcnQgdGhlIGNvbm5lY3Rpb25cbiAgY29ubmVjdCgpO1xuXG4gIC8vIFJldHVybiBjbGVhbnVwIGZ1bmN0aW9uXG4gIHJldHVybiAoKSA9PiB7XG4gICAgaWYodGltZW91dElkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgIHRpbWVvdXRJZCA9IG51bGw7XG4gICAgfVxuICAgIGlmKGV2ZW50U291cmNlKSB7XG4gICAgICBldmVudFNvdXJjZS5jbG9zZSgpO1xuICAgICAgZXZlbnRTb3VyY2UgPSBudWxsO1xuICAgIH1cbiAgfTtcbn07XG5cbmV4cG9ydCB7QXBpRXJyb3J9IGZyb20gJy4vZXJyb3JzL0FwaUVycm9yJztcbiJdLAogICJtYXBwaW5ncyI6ICJBQUtBLE9BQVEsWUFBQUEsTUFBZSxvQkFxYnZCLE9BQVEsWUFBQUEsTUFBZSxvQkFuYnZCLE1BQU1DLEVBQVdDLEdBQStCLE1BQU0sUUFBUUEsQ0FBSyxFQUM3REMsRUFBWUQsR0FBZ0MsT0FBT0EsR0FBVSxTQUM3REUsRUFBaUJGLEdBQ3JCQSxJQUFVLE1BQVEsT0FBT0EsR0FBVSxVQUFZLENBQUNELEVBQVFDLENBQUssRUFDekRHLEVBQVdILEdBQ2ZBLEdBQVUs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QUFZRixDQUFhLEVBRTdDLFdBQVdLLEVBQVNMLENBQWEsR0FFOUJELEVBQVUsU0FDWEEsRUFBVSxRQUFRLElBQUksTUFBTSx5Q0FBeUMsQ0FBQyxFQUl2RUEsRUFBVSxTQUNYQSxFQUFVLFFBQVFPLENBQUssQ0FHN0IsQ0FDRixPQUFRMUIsRUFBTyxDQUNWbUIsRUFBVSxTQUNYQSxFQUFVLFFBQVFuQixhQUFpQixNQUFRQSxFQUFRLElBQUksTUFBTSxpQ0FBaUMsQ0FBQyxDQUVuRyxDQUNGLEVBR0EsT0FBQXlCLEVBQVEsRUFHRCxJQUFNLENBQ1JELElBQ0QsYUFBYUEsQ0FBUyxFQUN0QkEsRUFBWSxNQUVYRCxJQUNEQSxFQUFZLE1BQU0sRUFDbEJBLEVBQWMsS0FFbEIsQ0FDRiIsCiAgIm5hbWVzIjogWyJBcGlFcnJvciIsICJpc0FycmF5IiwgInZhbHVlIiwgImlzU3RyaW5nIiwgImlzUGxhaW5PYmplY3QiLCAiaXNFbXB0eSIsICJpc051bGwiLCAiaXNVbmRlZmluZWQiLCAiSlNPTl9DT05URU5UX1RZUEVfUkVHRVgiLCAicmVxdWVzdENhY2hlIiwgInJlbW92ZVNwYWNlcyIsICJzdHIiLCAicXVlcnlTdHJpbmciLCAianNvbiIsICJrZXkiLCAiY3JlYXRlVGltZW91dCIsICJtcyIsICJfIiwgInJlamVjdCIsICJnZW5lcmF0ZUNhY2hlS2V5IiwgInVybCIsICJtZXRob2QiLCAicGFyYW1zIiwgIm9wdGlvbnMiLCAiY3JlYXRlRXZlbnRTb3VyY2UiLCAiYWpheCIsICJoZWFkZXJzIiwgInRva2VuIiwgInRpbWVvdXQiLCAiY2FjaGUiLCAiZm9ybWF0VXJsIiwgImZvcm1hdFRva2VuIiwgImZvcm1hdEhlYWRlcnMiLCAiZm9ybWF0TWV0aG9kIiwgImZvcm1hdFBhcmFtcyIsICJjYWNoZUtleSIsICJjYWNoZWQiLCAicmVxdWVzdFByb21pc2UiLCAicmVzcG9uc2UiLCAicmVzdWx0cyIsICJlcnJvciIsICJmaW5hbFByb21pc2UiLCAiZ2V0IiwgInBvc3QiLCAicHV0IiwgImRlbCIsICJ0b0dxbCIsICJvYmoiLCAiZ3FsUHJvcHMiLCAiaXRlbSIsICJsaXN0IiwgImxpc3RJdGVtIiwgInZhbCIsICJvYmpJdGVtIiwgImdyYXBocWxRdWVyeSIsICJxdWVyeSIsICJib2R5IiwgIm11dGF0aW9uIiwgInN1YnNjcmliZVNTRSIsICJjYWxsYmFja3MiLCAicmV0cnlJbnRlcnZhbCIsICJtYXhSZXRyaWVzIiwgInJldHJ5Q291bnQiLCAiZXZlbnRTb3VyY2UiLCAidGltZW91dElkIiwgImNvbm5lY3QiLCAiZXZlbnQiLCAic3NlRXZlbnQiXQp9Cg==
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nlabs/rip-hunter",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "JS utilities for AJAX and GraphQL",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"main": "./lib/index.js",
|
|
7
8
|
"module": "./lib/index.js",
|
|
8
9
|
"types": "./lib/index.d.ts",
|
|
@@ -31,9 +32,9 @@
|
|
|
31
32
|
"url": "https://github.com/nitrogenlabs/rip-hunter/issues"
|
|
32
33
|
},
|
|
33
34
|
"scripts": {
|
|
34
|
-
"build": "lex compile
|
|
35
|
+
"build": "lex compile --remove",
|
|
35
36
|
"clean": "lex clean",
|
|
36
|
-
"lint": "
|
|
37
|
+
"lint": "lex lint --fix",
|
|
37
38
|
"prepublishOnly": "npm run lint && npm run test && npm run build",
|
|
38
39
|
"pretest": "stage=test npm run lint",
|
|
39
40
|
"publish:major": "npm version major && npm run publish:tags && npm publish",
|
|
@@ -41,19 +42,19 @@
|
|
|
41
42
|
"publish:patch": "npm version patch && npm run publish:tags && npm publish",
|
|
42
43
|
"publish:tags": "git push --tags && git push origin HEAD",
|
|
43
44
|
"test": "lex test",
|
|
44
|
-
"update": "lex update
|
|
45
|
-
"watch": "lex compile
|
|
45
|
+
"update": "lex update --interactive",
|
|
46
|
+
"watch": "lex compile --remove -watch",
|
|
47
|
+
"benchmark": "node --experimental-modules ./benchmark.js"
|
|
46
48
|
},
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"lodash": "4.17.21"
|
|
49
|
+
"optionalDependencies": {
|
|
50
|
+
"eventsource": "^2.0.2"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
53
|
+
"@jest/globals": "30.0.4",
|
|
54
|
+
"@nlabs/lex": "1.47.2",
|
|
52
55
|
"@nlabs/fetch-mock": "1.0.2",
|
|
53
|
-
"@types/jest": "
|
|
54
|
-
"@types/node": "
|
|
55
|
-
"
|
|
56
|
-
"eslint-config-styleguidejs": "3.2.1",
|
|
57
|
-
"typescript": "5.0.2"
|
|
56
|
+
"@types/jest": "30.0.0",
|
|
57
|
+
"@types/node": "24.0.12",
|
|
58
|
+
"typescript": "5.8.3"
|
|
58
59
|
}
|
|
59
60
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"skipLibCheck": true
|
|
5
|
+
},
|
|
6
|
+
"include": [
|
|
7
|
+
"./src/**/*.ts",
|
|
8
|
+
"./src/**/*.tsx"
|
|
9
|
+
],
|
|
10
|
+
"exclude": [
|
|
11
|
+
"lib",
|
|
12
|
+
"./node_modules",
|
|
13
|
+
"./src/**/*.test.ts",
|
|
14
|
+
"./src/**/*.test.tsx"
|
|
15
|
+
]
|
|
16
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -5,40 +5,51 @@
|
|
|
5
5
|
"declaration": true,
|
|
6
6
|
"emitDeclarationOnly": true,
|
|
7
7
|
"esModuleInterop": true,
|
|
8
|
+
"exactOptionalPropertyTypes": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
8
10
|
"inlineSourceMap": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"jsx": "react-jsx",
|
|
9
13
|
"lib": [
|
|
14
|
+
"esnext",
|
|
10
15
|
"dom",
|
|
11
|
-
"
|
|
12
|
-
"es5",
|
|
13
|
-
"es6",
|
|
14
|
-
"es7",
|
|
15
|
-
"esnext"
|
|
16
|
+
"dom.iterable"
|
|
16
17
|
],
|
|
17
|
-
"module": "
|
|
18
|
+
"module": "esnext",
|
|
18
19
|
"moduleResolution": "node",
|
|
20
|
+
"noImplicitAny": false,
|
|
21
|
+
"noImplicitOverride": false,
|
|
19
22
|
"noImplicitReturns": true,
|
|
20
23
|
"noImplicitThis": true,
|
|
24
|
+
"noUncheckedIndexedAccess": false,
|
|
21
25
|
"noUnusedLocals": true,
|
|
22
|
-
"outDir": "
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
+
"outDir": "lib",
|
|
27
|
+
"pretty": true,
|
|
28
|
+
"resolveJsonModule": true,
|
|
29
|
+
"skipLibCheck": false,
|
|
30
|
+
"strict": false,
|
|
31
|
+
"strictFunctionTypes": true,
|
|
32
|
+
"strictNullChecks": true,
|
|
33
|
+
"target": "ES2022",
|
|
26
34
|
"typeRoots": [
|
|
35
|
+
"../../node_modules/@types",
|
|
27
36
|
"node_modules/@types",
|
|
28
37
|
"node_modules/json-d-ts"
|
|
29
38
|
],
|
|
30
39
|
"types": [
|
|
31
40
|
"jest",
|
|
32
41
|
"node"
|
|
33
|
-
]
|
|
42
|
+
],
|
|
43
|
+
"useDefineForClassFields": true,
|
|
44
|
+
"verbatimModuleSyntax": true
|
|
34
45
|
},
|
|
35
|
-
"include": [
|
|
36
|
-
"./src/**/*"
|
|
37
|
-
],
|
|
38
46
|
"exclude": [
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
47
|
+
"node_modules",
|
|
48
|
+
"lib",
|
|
49
|
+
"benchmark.js",
|
|
50
|
+
"index.js"
|
|
51
|
+
],
|
|
52
|
+
"include": [
|
|
53
|
+
"src/**/*"
|
|
43
54
|
]
|
|
44
55
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"noImplicitAny": false,
|
|
5
|
+
"noImplicitThis": false,
|
|
6
|
+
"noUncheckedIndexedAccess": false,
|
|
7
|
+
"noUnusedLocals": false,
|
|
8
|
+
"skipLibCheck": false,
|
|
9
|
+
"strict": false,
|
|
10
|
+
"types": [
|
|
11
|
+
"jest",
|
|
12
|
+
"node"
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
"include": [
|
|
16
|
+
"./src/**/*.ts",
|
|
17
|
+
"./src/**/*.tsx",
|
|
18
|
+
"./src/**/*.test.ts",
|
|
19
|
+
"./src/**/*.test.tsx"
|
|
20
|
+
],
|
|
21
|
+
"exclude": [
|
|
22
|
+
"lib",
|
|
23
|
+
"./node_modules"
|
|
24
|
+
]
|
|
25
|
+
}
|