murlock 4.3.1 → 4.4.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
CHANGED
|
@@ -69,7 +69,15 @@ import { MurLock } from 'murlock';
|
|
|
69
69
|
@Injectable()
|
|
70
70
|
export class AppService {
|
|
71
71
|
@MurLock(5000, 'userId')
|
|
72
|
-
async someFunction({
|
|
72
|
+
async someFunction({
|
|
73
|
+
userId,
|
|
74
|
+
firstName,
|
|
75
|
+
lastName,
|
|
76
|
+
}: {
|
|
77
|
+
userId: string;
|
|
78
|
+
firstName: string;
|
|
79
|
+
lastName: string;
|
|
80
|
+
}): Promise<void> {
|
|
73
81
|
// Some critical section that only one request should be able to execute at a time
|
|
74
82
|
}
|
|
75
83
|
}
|
|
@@ -83,7 +91,10 @@ import { MurLock } from 'murlock';
|
|
|
83
91
|
@Injectable()
|
|
84
92
|
export class AppService {
|
|
85
93
|
@MurLock(5000, '0.userId', '1.transactionId')
|
|
86
|
-
async someFunction(
|
|
94
|
+
async someFunction(
|
|
95
|
+
{ userId, firstName, lastName }: UserDTO,
|
|
96
|
+
{ balance, transactionId }: TransactionDTO
|
|
97
|
+
): Promise<void> {
|
|
87
98
|
// Some critical section that only one request should be able to execute at a time
|
|
88
99
|
}
|
|
89
100
|
}
|
|
@@ -130,7 +141,7 @@ You can override the global wait parameter per decorator, allowing fine-grained
|
|
|
130
141
|
|
|
131
142
|
```typescript
|
|
132
143
|
@MurLock(
|
|
133
|
-
5000,
|
|
144
|
+
5000,
|
|
134
145
|
(retries) => (Math.floor(Math.random() * 50) + 50) * retries,
|
|
135
146
|
'user.id',
|
|
136
147
|
)
|
|
@@ -151,6 +162,113 @@ async anotherFunction(user: User): Promise<void> {
|
|
|
151
162
|
- If no wait is provided in decorator, MurLock will fallback to global wait from forRoot().
|
|
152
163
|
- Allows dynamic retry logic per critical section.
|
|
153
164
|
|
|
165
|
+
## Decorator Composition
|
|
166
|
+
|
|
167
|
+
When using `@MurLock` with other decorators (such as `@Transactional` from typeorm-transactional), you may encounter issues with parameter name extraction if the other decorator wraps the method before `@MurLock` is applied.
|
|
168
|
+
|
|
169
|
+
### Problem
|
|
170
|
+
|
|
171
|
+
TypeScript decorators execute in bottom-up order. If another decorator wraps the method before `@MurLock`, the parameter names cannot be extracted from the wrapped function:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// This may fail if @Transactional wraps the method before @MurLock executes
|
|
175
|
+
@MurLock(5000, 'userData.id')
|
|
176
|
+
@Transactional()
|
|
177
|
+
async process(userData: { id: string }, options: string[] = []): Promise<any> {
|
|
178
|
+
// Error: Parameter userData not found in method arguments
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Solution: Using SetParamNames
|
|
183
|
+
|
|
184
|
+
Use the `SetParamNames` decorator to explicitly specify parameter names. **Important**: `SetParamNames` must be placed **below** `@MurLock` in the code (it will execute before `@MurLock` due to TypeScript's bottom-up decorator execution order).
|
|
185
|
+
|
|
186
|
+
#### Option 1: Object Format (Recommended)
|
|
187
|
+
|
|
188
|
+
The object format allows you to specify only the parameters you need, with explicit index mapping. This provides O(1) lookup performance and doesn't require specifying all parameters:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { MurLock, SetParamNames } from 'murlock';
|
|
192
|
+
|
|
193
|
+
class MyService {
|
|
194
|
+
@MurLock(5000, 'userData.id')
|
|
195
|
+
@SetParamNames({ userData: 0 }) // Only specify needed params with their indices
|
|
196
|
+
@Transactional()
|
|
197
|
+
async process(
|
|
198
|
+
userData: { id: string },
|
|
199
|
+
options: string[],
|
|
200
|
+
context: any
|
|
201
|
+
): Promise<any> {
|
|
202
|
+
// This will work correctly - only userData is needed for the lock key
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Benefits of Object Format:**
|
|
208
|
+
|
|
209
|
+
- **Partial specification**: Only specify the parameters you actually use in the lock key
|
|
210
|
+
- **Order independent**: Parameter indices are explicit, so declaration order doesn't matter
|
|
211
|
+
- **O(1) lookup**: Direct property access instead of array indexOf search
|
|
212
|
+
- **Self-documenting**: The index mapping clearly shows which argument position each name refers to
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// Example: Only need the third parameter for the lock key
|
|
216
|
+
@MurLock(5000, 'context.tenantId')
|
|
217
|
+
@SetParamNames({ context: 2 }) // context is at index 2
|
|
218
|
+
@Transactional()
|
|
219
|
+
async process(userData: any, options: any, context: { tenantId: string }): Promise<any> {
|
|
220
|
+
// ...
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### Option 2: Array Format (Legacy)
|
|
225
|
+
|
|
226
|
+
The array format requires specifying ALL parameters in order:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { MurLock, SetParamNames } from 'murlock';
|
|
230
|
+
|
|
231
|
+
class MyService {
|
|
232
|
+
@MurLock(5000, 'userData.id')
|
|
233
|
+
@SetParamNames('userData', 'options') // Must specify ALL params in order
|
|
234
|
+
@Transactional()
|
|
235
|
+
async process(
|
|
236
|
+
userData: { id: string },
|
|
237
|
+
options: string[] = []
|
|
238
|
+
): Promise<any> {
|
|
239
|
+
// This will work correctly
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
> **Note**: The array format uses `indexOf` to find parameters, so all parameters must be specified in the correct order. If you only need one parameter, the object format is recommended.
|
|
245
|
+
|
|
246
|
+
**Decorator Execution Order** (bottom-up):
|
|
247
|
+
|
|
248
|
+
1. `@Transactional()` executes first and wraps the method
|
|
249
|
+
2. `@SetParamNames` executes second and stores parameter names in metadata
|
|
250
|
+
3. `@MurLock` executes last and reads parameter names from metadata
|
|
251
|
+
|
|
252
|
+
If you place `@SetParamNames` above `@MurLock`, it will execute after `@MurLock`, and the metadata won't be available when `@MurLock` needs it.
|
|
253
|
+
|
|
254
|
+
### Alternative: Using Parameter Indices
|
|
255
|
+
|
|
256
|
+
As a workaround, you can use parameter indices instead of names:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
@MurLock(5000, '0.id') // Uses index 0 for userData
|
|
260
|
+
@Transactional()
|
|
261
|
+
async process(userData: { id: string }, options: string[] = []): Promise<any> {
|
|
262
|
+
// This works, but name-based keys are more readable
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### How It Works
|
|
267
|
+
|
|
268
|
+
- `SetParamNames` stores parameter names in metadata before the method is wrapped
|
|
269
|
+
- `@MurLock` reads the parameter names from metadata when the function is already wrapped
|
|
270
|
+
- This allows decorator composition to work correctly regardless of execution order
|
|
271
|
+
|
|
154
272
|
## Blocking Mode
|
|
155
273
|
|
|
156
274
|
MurLock supports a blocking mode where it will continuously retry to acquire the lock until successful. This is useful for critical operations that must eventually succeed.
|
|
@@ -189,7 +307,7 @@ MurLock includes robust Redis connection handling:
|
|
|
189
307
|
@Module({
|
|
190
308
|
imports: [
|
|
191
309
|
MurLockModule.forRoot({
|
|
192
|
-
redisOptions: {
|
|
310
|
+
redisOptions: {
|
|
193
311
|
url: 'redis://localhost:6379',
|
|
194
312
|
socket: {
|
|
195
313
|
keepAlive: false,
|
|
@@ -222,7 +340,7 @@ import { MurLockModule } from 'murlock';
|
|
|
222
340
|
wait: configService.get('MURLOCK_WAIT'),
|
|
223
341
|
maxAttempts: configService.get('MURLOCK_MAX_ATTEMPTS'),
|
|
224
342
|
logLevel: configService.get('LOG_LEVEL'),
|
|
225
|
-
lockKeyPrefix: 'custom'
|
|
343
|
+
lockKeyPrefix: 'custom',
|
|
226
344
|
}),
|
|
227
345
|
inject: [ConfigService],
|
|
228
346
|
}),
|
|
@@ -277,7 +395,7 @@ import { MurLockService } from 'murlock';
|
|
|
277
395
|
@Injectable()
|
|
278
396
|
export class YourService {
|
|
279
397
|
constructor(private murLockService: MurLockService) {}
|
|
280
|
-
|
|
398
|
+
|
|
281
399
|
// Your methods where you want to use the lock
|
|
282
400
|
}
|
|
283
401
|
```
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
+
export declare const PARAM_NAMES_KEY: unique symbol;
|
|
3
|
+
export declare const PARAM_INDEX_MAP_KEY: unique symbol;
|
|
4
|
+
export type ParamIndexMap = Record<string, number>;
|
|
5
|
+
export declare function SetParamNames(mappingOrFirstParam: ParamIndexMap | string, ...restParamNames: string[]): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
2
6
|
export declare function MurLock(releaseTime: number, wait: number | ((retries: number) => number), ...keyParams: string[]): any;
|
|
3
7
|
export declare function MurLock(releaseTime: number, ...keyParams: string[]): any;
|
|
@@ -9,19 +9,83 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.MurLock = void 0;
|
|
13
|
-
require("reflect-metadata");
|
|
12
|
+
exports.MurLock = exports.SetParamNames = exports.PARAM_INDEX_MAP_KEY = exports.PARAM_NAMES_KEY = void 0;
|
|
14
13
|
const common_1 = require("@nestjs/common");
|
|
14
|
+
require("reflect-metadata");
|
|
15
15
|
const exceptions_1 = require("../exceptions");
|
|
16
16
|
const murlock_service_1 = require("../murlock.service");
|
|
17
|
+
exports.PARAM_NAMES_KEY = Symbol('murlock:param-names');
|
|
18
|
+
exports.PARAM_INDEX_MAP_KEY = Symbol('murlock:param-index-map');
|
|
19
|
+
function SetParamNames(mappingOrFirstParam, ...restParamNames) {
|
|
20
|
+
return function (target, propertyKey, descriptor) {
|
|
21
|
+
if (typeof mappingOrFirstParam === 'object') {
|
|
22
|
+
Reflect.defineMetadata(exports.PARAM_INDEX_MAP_KEY, mappingOrFirstParam, target, propertyKey);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const paramNames = [mappingOrFirstParam, ...restParamNames];
|
|
26
|
+
Reflect.defineMetadata(exports.PARAM_NAMES_KEY, paramNames, target, propertyKey);
|
|
27
|
+
}
|
|
28
|
+
return descriptor;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
exports.SetParamNames = SetParamNames;
|
|
17
32
|
function getParameterNames(func) {
|
|
18
33
|
const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
|
|
19
|
-
const ARGUMENT_NAMES = /([^\s,]+)/g;
|
|
20
34
|
const fnStr = func.toString().replace(STRIP_COMMENTS, '');
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
const paramsStr = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')'));
|
|
36
|
+
if (!paramsStr.trim()) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
const params = [];
|
|
40
|
+
let current = '';
|
|
41
|
+
let depth = 0;
|
|
42
|
+
let inString = false;
|
|
43
|
+
let stringChar = '';
|
|
44
|
+
for (let i = 0; i < paramsStr.length; i++) {
|
|
45
|
+
const char = paramsStr[i];
|
|
46
|
+
if (!inString && (char === '"' || char === "'" || char === '`')) {
|
|
47
|
+
inString = true;
|
|
48
|
+
stringChar = char;
|
|
49
|
+
}
|
|
50
|
+
else if (inString && char === stringChar && paramsStr[i - 1] !== '\\') {
|
|
51
|
+
inString = false;
|
|
52
|
+
}
|
|
53
|
+
else if (!inString) {
|
|
54
|
+
if (char === '(' || char === '[' || char === '{') {
|
|
55
|
+
depth++;
|
|
56
|
+
}
|
|
57
|
+
else if (char === ')' || char === ']' || char === '}') {
|
|
58
|
+
depth--;
|
|
59
|
+
}
|
|
60
|
+
else if (char === ',' && depth === 0) {
|
|
61
|
+
const paramName = current.split('=')[0].trim().split(':')[0].trim();
|
|
62
|
+
if (paramName) {
|
|
63
|
+
params.push(paramName);
|
|
64
|
+
}
|
|
65
|
+
current = '';
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
current += char;
|
|
70
|
+
}
|
|
71
|
+
if (current.trim()) {
|
|
72
|
+
const paramName = current.split('=')[0].trim().split(':')[0].trim();
|
|
73
|
+
if (paramName) {
|
|
74
|
+
params.push(paramName);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return params;
|
|
78
|
+
}
|
|
79
|
+
function getParameterNamesWithFallback(func, target, propertyKey) {
|
|
80
|
+
const paramNames = getParameterNames(func);
|
|
81
|
+
if (paramNames.length > 0 && !paramNames.includes('...args')) {
|
|
82
|
+
return paramNames;
|
|
83
|
+
}
|
|
84
|
+
const metadataParamNames = Reflect.getMetadata(exports.PARAM_NAMES_KEY, target, propertyKey);
|
|
85
|
+
if (metadataParamNames && metadataParamNames.length > 0) {
|
|
86
|
+
return metadataParamNames;
|
|
87
|
+
}
|
|
88
|
+
return paramNames;
|
|
25
89
|
}
|
|
26
90
|
function MurLock(releaseTime, waitOrKeyParam, ...keyParams) {
|
|
27
91
|
let wait;
|
|
@@ -39,18 +103,33 @@ function MurLock(releaseTime, waitOrKeyParam, ...keyParams) {
|
|
|
39
103
|
return (target, propertyKey, descriptor) => {
|
|
40
104
|
injectMurlockService(target, 'murlockServiceDecorator');
|
|
41
105
|
const originalMethod = descriptor.value;
|
|
42
|
-
const methodParameterNames =
|
|
106
|
+
const methodParameterNames = getParameterNamesWithFallback(originalMethod, target, propertyKey);
|
|
107
|
+
const paramIndexMap = Reflect.getMetadata(exports.PARAM_INDEX_MAP_KEY, target, propertyKey);
|
|
108
|
+
if (methodParameterNames.length > 0 &&
|
|
109
|
+
!methodParameterNames.includes('...args')) {
|
|
110
|
+
const existingMetadata = Reflect.getMetadata(exports.PARAM_NAMES_KEY, target, propertyKey);
|
|
111
|
+
if (!existingMetadata) {
|
|
112
|
+
Reflect.defineMetadata(exports.PARAM_NAMES_KEY, methodParameterNames, target, propertyKey);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function resolveParameterIndex(source) {
|
|
116
|
+
if (isNumber(source)) {
|
|
117
|
+
return Number(source);
|
|
118
|
+
}
|
|
119
|
+
if (paramIndexMap && source in paramIndexMap) {
|
|
120
|
+
return paramIndexMap[source];
|
|
121
|
+
}
|
|
122
|
+
return methodParameterNames.indexOf(source);
|
|
123
|
+
}
|
|
43
124
|
function constructLockKey(args, lockKeyPrefix = 'default') {
|
|
44
|
-
|
|
125
|
+
const lockKeyElements = [];
|
|
45
126
|
if (lockKeyPrefix != 'custom') {
|
|
46
127
|
lockKeyElements.push(target.constructor.name);
|
|
47
128
|
lockKeyElements.push(propertyKey);
|
|
48
129
|
}
|
|
49
130
|
lockKeyElements.push(...keyParams.map((keyParam) => {
|
|
50
131
|
const [source, path] = keyParam.split('.');
|
|
51
|
-
const parameterIndex =
|
|
52
|
-
? Number(source)
|
|
53
|
-
: methodParameterNames.indexOf(source);
|
|
132
|
+
const parameterIndex = resolveParameterIndex(source);
|
|
54
133
|
if (parameterIndex >= 0) {
|
|
55
134
|
const parameterValue = findParameterValue({
|
|
56
135
|
args,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"murlock.decorator.js","sourceRoot":"","sources":["../../lib/decorators/murlock.decorator.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4BAA0B;AAC1B,
|
|
1
|
+
{"version":3,"file":"murlock.decorator.js","sourceRoot":"","sources":["../../lib/decorators/murlock.decorator.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAwC;AACxC,4BAA0B;AAC1B,8CAAiD;AACjD,wDAAoD;AAMvC,QAAA,eAAe,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAMhD,QAAA,mBAAmB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AA8CrE,SAAgB,aAAa,CAC3B,mBAA2C,EAC3C,GAAG,cAAwB;IAE3B,OAAO,UACL,MAAW,EACX,WAAmB,EACnB,UAA8B;QAE9B,IAAI,OAAO,mBAAmB,KAAK,QAAQ,EAAE;YAE3C,OAAO,CAAC,cAAc,CACpB,2BAAmB,EACnB,mBAAmB,EACnB,MAAM,EACN,WAAW,CACZ,CAAC;SACH;aAAM;YAEL,MAAM,UAAU,GAAG,CAAC,mBAAmB,EAAE,GAAG,cAAc,CAAC,CAAC;YAC5D,OAAO,CAAC,cAAc,CAAC,uBAAe,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;SAC1E;QACD,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC;AAxBD,sCAwBC;AAOD,SAAS,iBAAiB,CAAC,IAAc;IACvC,MAAM,cAAc,GAAG,kCAAkC,CAAC;IAE1D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAE1E,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE;QACrB,OAAO,EAAE,CAAC;KACX;IAGD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,UAAU,GAAG,EAAE,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACzC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE;YAC/D,QAAQ,GAAG,IAAI,CAAC;YAChB,UAAU,GAAG,IAAI,CAAC;SACnB;aAAM,IAAI,QAAQ,IAAI,IAAI,KAAK,UAAU,IAAI,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;YACvE,QAAQ,GAAG,KAAK,CAAC;SAClB;aAAM,IAAI,CAAC,QAAQ,EAAE;YACpB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE;gBAChD,KAAK,EAAE,CAAC;aACT;iBAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE;gBACvD,KAAK,EAAE,CAAC;aACT;iBAAM,IAAI,IAAI,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,EAAE;gBAEtC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACpE,IAAI,SAAS,EAAE;oBACb,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;iBACxB;gBACD,OAAO,GAAG,EAAE,CAAC;gBACb,SAAS;aACV;SACF;QAED,OAAO,IAAI,IAAI,CAAC;KACjB;IAGD,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE;QAClB,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpE,IAAI,SAAS,EAAE;YACb,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;SACxB;KACF;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAUD,SAAS,6BAA6B,CACpC,IAAc,EACd,MAAW,EACX,WAAmB;IAGnB,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAG3C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;QAC5D,OAAO,UAAU,CAAC;KACnB;IAID,MAAM,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAC5C,uBAAe,EACf,MAAM,EACN,WAAW,CACY,CAAC;IAE1B,IAAI,kBAAkB,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE;QACvD,OAAO,kBAAkB,CAAC;KAC3B;IAGD,OAAO,UAAU,CAAC;AACpB,CAAC;AAwBD,SAAgB,OAAO,CACrB,WAAmB,EACnB,cAAgE,EAChE,GAAG,SAAmB;IAEtB,IAAI,IAAwD,CAAC;IAC7D,IACE,OAAO,cAAc,KAAK,QAAQ;QAClC,OAAO,cAAc,KAAK,UAAU,EACpC;QACA,IAAI,GAAG,cAAc,CAAC;KACvB;SAAM;QACL,SAAS,GAAG;YACV,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;YACzD,GAAG,SAAS;SACb,CAAC;KACH;IAED,MAAM,oBAAoB,GAAG,IAAA,eAAM,EAAC,gCAAc,CAAC,CAAC;IAEpD,OAAO,CAAC,MAAW,EAAE,WAAmB,EAAE,UAA8B,EAAE,EAAE;QAC1E,oBAAoB,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;QAExD,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAIxC,MAAM,oBAAoB,GAAG,6BAA6B,CACxD,cAAc,EACd,MAAM,EACN,WAAW,CACZ,CAAC;QAGF,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,CACvC,2BAAmB,EACnB,MAAM,EACN,WAAW,CACiB,CAAC;QAI/B,IACE,oBAAoB,CAAC,MAAM,GAAG,CAAC;YAC/B,CAAC,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,EACzC;YACA,MAAM,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAC1C,uBAAe,EACf,MAAM,EACN,WAAW,CACZ,CAAC;YACF,IAAI,CAAC,gBAAgB,EAAE;gBACrB,OAAO,CAAC,cAAc,CACpB,uBAAe,EACf,oBAAoB,EACpB,MAAM,EACN,WAAW,CACZ,CAAC;aACH;SACF;QAMD,SAAS,qBAAqB,CAAC,MAAc;YAE3C,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE;gBACpB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;aACvB;YAGD,IAAI,aAAa,IAAI,MAAM,IAAI,aAAa,EAAE;gBAC5C,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;aAC9B;YAGD,OAAO,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QAED,SAAS,gBAAgB,CAAC,IAAW,EAAE,aAAa,GAAG,SAAS;YAC9D,MAAM,eAAe,GAAa,EAAE,CAAC;YACrC,IAAI,aAAa,IAAI,QAAQ,EAAE;gBAC7B,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBAC9C,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aACnC;YAED,eAAe,CAAC,IAAI,CAClB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAC5B,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC3C,MAAM,cAAc,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;gBAErD,IAAI,cAAc,IAAI,CAAC,EAAE;oBACvB,MAAM,cAAc,GAAG,kBAAkB,CAAC;wBACxC,IAAI;wBACJ,MAAM;wBACN,cAAc;wBACd,IAAI;qBACL,CAAC,CAAC;oBACH,IACE,OAAO,cAAc,KAAK,WAAW;wBACrC,cAAc,KAAK,IAAI,EACvB;wBACA,MAAM,IAAI,6BAAgB,CACxB,aAAa,MAAM,wBAAwB,CAC5C,CAAC;qBACH;oBACD,IACE,IAAI;wBACJ,OAAO,cAAc,KAAK,QAAQ;wBAClC,cAAc,KAAK,IAAI;wBACvB,IAAI,IAAI,cAAc,EACtB;wBACA,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;qBAC7B;oBACD,OAAO,cAAc,YAAY,MAAM;wBACrC,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE;wBAC3B,CAAC,CAAC,cAAc,CAAC;iBACpB;gBAED,IAAI,aAAa,IAAI,QAAQ,EAAE;oBAC7B,OAAO,MAAM,CAAC;iBACf;gBAED,MAAM,IAAI,6BAAgB,CACxB,aAAa,MAAM,iCAAiC,CACrD,CAAC;YACJ,CAAC,CAAC,CACH,CAAC;YACF,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,MAAM,OAAO,GAAG,UAAgB,GAAG,IAAW;;gBAC5C,MAAM,cAAc,GAAmB,IAAI,CAAC,uBAAuB,CAAC;gBAEpE,MAAM,OAAO,GAAG,gBAAgB,CAC9B,IAAI,EACJ,cAAc,CAAC,OAAO,CAAC,aAAa,CACrC,CAAC;gBAEF,IAAI,CAAC,cAAc,EAAE;oBACnB,MAAM,IAAI,6BAAgB,CAAC,kCAAkC,CAAC,CAAC;iBAChE;gBAED,OAAO,cAAc,CAAC,WAAW,CAC/B,OAAO,EACP,WAAW,EACX,IAAI,EACJ,GAAS,EAAE;oBACT,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC1C,CAAC,CAAA,CACF,CAAC;YACJ,CAAC;SAAA,CAAC;QAEF,MAAM,YAAY,GAChB,OAAQ,OAAe,CAAC,eAAe,KAAK,UAAU;YACpD,CAAC,CAAE,OAAe,CAAC,eAAe,CAAC,cAAc,CAAC;YAClD,CAAC,CAAC,EAAE,CAAC;QACT,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE;YAC9B,MAAM,KAAK,GAAI,OAAe,CAAC,WAAW,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAC/D,OAAe,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;SACtD;QAED,UAAU,CAAC,KAAK,GAAG,OAAO,CAAC;QAE3B,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC;AAvKD,0BAuKC;AAED,SAAS,QAAQ,CAAC,KAAK;IACrB,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;QACvB,OAAO,IAAI,CAAC;KACb;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,KAAU;IAC1B,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,kBAAkB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE;IAChE,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;KAC3B;IACD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE;QAClD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;KACxB;IACD,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC;AAC9B,CAAC"}
|