typescript-retry-decorator 2.0.6 → 2.2.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/.github/workflows/ci.yml +28 -9
- package/.github/workflows/npm-publish.yml +27 -7
- package/README.md +2 -0
- package/dist/retry.decorator.d.ts +4 -2
- package/dist/retry.decorator.d.ts.map +1 -1
- package/dist/retry.decorator.js +4 -3
- package/dist/retry.decorator.js.map +1 -1
- package/dist/retry.decorator.test.js +47 -1
- package/dist/retry.decorator.test.js.map +1 -1
- package/package.json +1 -1
- package/src/retry.decorator.test.ts +38 -2
- package/src/retry.decorator.ts +7 -5
- package/tsconfig.json +1 -0
package/.github/workflows/ci.yml
CHANGED
|
@@ -11,16 +11,35 @@ jobs:
|
|
|
11
11
|
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
|
|
14
|
-
strategy:
|
|
15
|
-
matrix:
|
|
16
|
-
node-version: [14.x, 16.x]
|
|
17
|
-
|
|
18
14
|
steps:
|
|
19
|
-
- uses: actions/checkout@
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
- uses: actions/checkout@v3
|
|
16
|
+
|
|
17
|
+
- name: Install Node.js
|
|
18
|
+
uses: actions/setup-node@v3
|
|
19
|
+
with:
|
|
20
|
+
node-version: 18
|
|
21
|
+
|
|
22
|
+
- uses: pnpm/action-setup@v2
|
|
23
|
+
name: Install pnpm
|
|
24
|
+
id: pnpm-install
|
|
22
25
|
with:
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
version: 7
|
|
27
|
+
run_install: false
|
|
28
|
+
|
|
29
|
+
- name: Get pnpm store directory
|
|
30
|
+
id: pnpm-cache
|
|
31
|
+
shell: bash
|
|
32
|
+
run: |
|
|
33
|
+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
|
34
|
+
|
|
35
|
+
- uses: actions/cache@v3
|
|
36
|
+
name: Setup pnpm cache
|
|
37
|
+
with:
|
|
38
|
+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
39
|
+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
40
|
+
restore-keys: |
|
|
41
|
+
${{ runner.os }}-pnpm-store-
|
|
42
|
+
|
|
43
|
+
- run: pnpm install
|
|
25
44
|
- run: npm run build
|
|
26
45
|
- run: npm test
|
|
@@ -10,16 +10,36 @@ on:
|
|
|
10
10
|
jobs:
|
|
11
11
|
publish-npm:
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
|
-
strategy:
|
|
14
|
-
matrix:
|
|
15
|
-
node-version: [14.x]
|
|
16
13
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
18
|
-
-
|
|
14
|
+
- uses: actions/checkout@v3
|
|
15
|
+
- name: Install Node.js
|
|
16
|
+
uses: actions/setup-node@v3
|
|
19
17
|
with:
|
|
20
|
-
node-version:
|
|
18
|
+
node-version: 18
|
|
21
19
|
registry-url: https://registry.npmjs.org/
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
- uses: pnpm/action-setup@v2
|
|
22
|
+
name: Install pnpm
|
|
23
|
+
id: pnpm-install
|
|
24
|
+
with:
|
|
25
|
+
version: 7
|
|
26
|
+
run_install: false
|
|
27
|
+
|
|
28
|
+
- name: Get pnpm store directory
|
|
29
|
+
id: pnpm-cache
|
|
30
|
+
shell: bash
|
|
31
|
+
run: |
|
|
32
|
+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
|
33
|
+
|
|
34
|
+
- uses: actions/cache@v3
|
|
35
|
+
name: Setup pnpm cache
|
|
36
|
+
with:
|
|
37
|
+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
38
|
+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
39
|
+
restore-keys: |
|
|
40
|
+
${{ runner.os }}-pnpm-store-
|
|
41
|
+
|
|
42
|
+
- run: pnpm install
|
|
23
43
|
- run: npm run build
|
|
24
44
|
- run: npm test
|
|
25
45
|
- run: npm publish
|
package/README.md
CHANGED
|
@@ -16,6 +16,8 @@ Import and use it. Retry for `Promise` is supported as long as the `runtime` has
|
|
|
16
16
|
| exponentialOption | object | No | { maxInterval: 2000, multiplier: 2 } | This is for the `ExponentialBackOffPolicy` <br/> The max interval each wait and the multiplier for the `backOff`. |
|
|
17
17
|
| doRetry | (e: any) => boolean | No | - | Function with error parameter to decide if repetition is necessary. |
|
|
18
18
|
| value | Error/Exception class | No | [ ] | An array of Exception types that are retryable. |
|
|
19
|
+
| useConsoleLogger | boolean | No | true | Print errors on console. |
|
|
20
|
+
| useOriginalError | throw original exception| No | false | `MaxAttemptsError` by default. if this is set to *true*, the `original` exception would be thrown instead. |
|
|
19
21
|
|
|
20
22
|
### Example
|
|
21
23
|
```typescript
|
|
@@ -8,15 +8,17 @@ export declare class MaxAttemptsError extends Error {
|
|
|
8
8
|
code: string;
|
|
9
9
|
}
|
|
10
10
|
export interface RetryOptions {
|
|
11
|
-
maxAttempts: number;
|
|
12
11
|
backOffPolicy?: BackOffPolicy;
|
|
13
12
|
backOff?: number;
|
|
14
13
|
doRetry?: (e: any) => boolean;
|
|
15
|
-
value?: ErrorConstructor[];
|
|
16
14
|
exponentialOption?: {
|
|
17
15
|
maxInterval: number;
|
|
18
16
|
multiplier: number;
|
|
19
17
|
};
|
|
18
|
+
maxAttempts: number;
|
|
19
|
+
value?: ErrorConstructor[];
|
|
20
|
+
useConsoleLogger?: boolean;
|
|
21
|
+
useOriginalError?: boolean;
|
|
20
22
|
}
|
|
21
23
|
export declare enum BackOffPolicy {
|
|
22
24
|
FixedBackOffPolicy = "FixedBackOffPolicy",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.decorator.d.ts","sourceRoot":"","sources":["../src/retry.decorator.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,iBAAiB,CAyElE;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,SAAS;CAMd;AAED,MAAM,WAAW,YAAY;IAC3B,
|
|
1
|
+
{"version":3,"file":"retry.decorator.d.ts","sourceRoot":"","sources":["../src/retry.decorator.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,iBAAiB,CAyElE;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,SAAS;CAMd;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,oBAAY,aAAa;IACvB,kBAAkB,uBAAuB;IACzC,wBAAwB,6BAA6B;CACtD;AAED,oBAAY,iBAAiB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,uBAAuB,CAAC,GAAG,CAAC,KAAK,uBAAuB,CAAC,GAAG,CAAC,CAAC"}
|
package/dist/retry.decorator.js
CHANGED
|
@@ -55,7 +55,9 @@ function Retryable(options) {
|
|
|
55
55
|
}
|
|
56
56
|
catch (e) {
|
|
57
57
|
if (--maxAttempts < 0) {
|
|
58
|
-
(e === null || e === void 0 ? void 0 : e.message) && console.error(e.message);
|
|
58
|
+
(typeof options.useConsoleLogger !== 'boolean' || options.useConsoleLogger) && (e === null || e === void 0 ? void 0 : e.message) && console.error(e.message);
|
|
59
|
+
if (options.useOriginalError)
|
|
60
|
+
throw e;
|
|
59
61
|
const maxAttemptsErrorInstance = new MaxAttemptsError(e === null || e === void 0 ? void 0 : e.message);
|
|
60
62
|
// Add the existing error stack if present
|
|
61
63
|
if (e === null || e === void 0 ? void 0 : e.stack) {
|
|
@@ -68,8 +70,7 @@ function Retryable(options) {
|
|
|
68
70
|
}
|
|
69
71
|
backOff && (yield (0, utils_1.sleep)(backOff));
|
|
70
72
|
if (options.backOffPolicy === BackOffPolicy.ExponentialBackOffPolicy) {
|
|
71
|
-
|
|
72
|
-
backOff = newBackOff > options.exponentialOption.maxInterval ? options.exponentialOption.maxInterval : newBackOff;
|
|
73
|
+
backOff = Math.min(backOff * options.exponentialOption.multiplier, options.exponentialOption.maxInterval);
|
|
73
74
|
}
|
|
74
75
|
return retryAsync.apply(this, [fn, args, maxAttempts, backOff]);
|
|
75
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.decorator.js","sourceRoot":"","sources":["../src/retry.decorator.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,mCAAgC;AAEhC;;;;GAIG;AACH,SAAgB,SAAS,CAAC,OAAqB;IAC7C;;;;;;;;OAQG;IACH,OAAO,UAAS,MAA2B,EAAE,WAAmB,EAAE,UAAwC;QACxG,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC;QACpC,iDAAiD;QACjD,IAAI,OAAO,CAAC,aAAa,KAAK,aAAa,CAAC,wBAAwB,EAAE;YACpE,kCAAkC,EAAE,CAAC;SACtC;QACD,UAAU,CAAC,KAAK,GAAG,UAAe,GAAG,IAAW;;gBAC9C,IAAI;oBACF,OAAO,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;iBAC/F;gBAAC,OAAO,CAAC,EAAE;oBACV,IAAI,CAAC,YAAY,gBAAgB,EAAE;wBACjC,MAAM,SAAS,GAAG,eAAe,WAAW,SAAS,OAAO,CAAC,WAAW,SAAS,CAAC;wBAClF,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,oBAAoB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;qBACjF;oBACD,MAAM,CAAC,CAAC;iBACT;YACH,CAAC;SAAA,CAAC;QACF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IAEF,SAAe,UAAU,CAAC,EAAa,EAAE,IAAW,EAAE,WAAmB,EAAE,OAAgB;;YACzF,IAAI;gBACF,OAAO,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;aACnC;YAAC,OAAO,CAAC,EAAE;gBACV,IAAI,EAAE,WAAW,GAAG,CAAC,EAAE;oBACrB,
|
|
1
|
+
{"version":3,"file":"retry.decorator.js","sourceRoot":"","sources":["../src/retry.decorator.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,6 +53,17 @@ class TestClass {
|
|
|
53
53
|
yield this.called();
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
+
noLog() {
|
|
57
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
console.log(`test method is called for ${++this.count} time`);
|
|
59
|
+
yield this.called();
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
useOriginalError() {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
yield this.called();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
56
67
|
called() {
|
|
57
68
|
return __awaiter(this, void 0, void 0, function* () {
|
|
58
69
|
return 'from real implementation';
|
|
@@ -102,6 +113,18 @@ __decorate([
|
|
|
102
113
|
__metadata("design:paramtypes", []),
|
|
103
114
|
__metadata("design:returntype", Promise)
|
|
104
115
|
], TestClass.prototype, "exponentialBackOffRetry", null);
|
|
116
|
+
__decorate([
|
|
117
|
+
(0, retry_decorator_1.Retryable)({ maxAttempts: 2, useConsoleLogger: false }),
|
|
118
|
+
__metadata("design:type", Function),
|
|
119
|
+
__metadata("design:paramtypes", []),
|
|
120
|
+
__metadata("design:returntype", Promise)
|
|
121
|
+
], TestClass.prototype, "noLog", null);
|
|
122
|
+
__decorate([
|
|
123
|
+
(0, retry_decorator_1.Retryable)({ maxAttempts: 2, useOriginalError: true }),
|
|
124
|
+
__metadata("design:type", Function),
|
|
125
|
+
__metadata("design:paramtypes", []),
|
|
126
|
+
__metadata("design:returntype", Promise)
|
|
127
|
+
], TestClass.prototype, "useOriginalError", null);
|
|
105
128
|
describe('Capture original error data Test', () => {
|
|
106
129
|
test('exceed max retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
107
130
|
const testClass = new TestClass();
|
|
@@ -139,7 +162,7 @@ describe('Retry Test', () => {
|
|
|
139
162
|
yield testClass.testMethod();
|
|
140
163
|
}
|
|
141
164
|
catch (e) {
|
|
142
|
-
expect(e).
|
|
165
|
+
expect(e).toBeInstanceOf(retry_decorator_1.MaxAttemptsError);
|
|
143
166
|
expect(e.message.includes(errorMsg));
|
|
144
167
|
}
|
|
145
168
|
expect(calledSpy).toHaveBeenCalledTimes(3);
|
|
@@ -193,5 +216,28 @@ describe('Retry Test', () => {
|
|
|
193
216
|
catch (e) { }
|
|
194
217
|
expect(calledSpy).toHaveBeenCalledTimes(4);
|
|
195
218
|
}));
|
|
219
|
+
test('no log', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
220
|
+
const calledSpy = jest.spyOn(testClass, 'called');
|
|
221
|
+
const errorSpy = jest.spyOn(console, 'error');
|
|
222
|
+
calledSpy.mockRejectedValueOnce(new Error('rejected'));
|
|
223
|
+
calledSpy.mockResolvedValueOnce('fulfilled');
|
|
224
|
+
yield testClass.testMethod();
|
|
225
|
+
expect(calledSpy).toHaveBeenCalledTimes(2);
|
|
226
|
+
expect(errorSpy).not.toHaveBeenCalled();
|
|
227
|
+
}));
|
|
228
|
+
// CustomError for testing.
|
|
229
|
+
class CustomError extends Error {
|
|
230
|
+
}
|
|
231
|
+
test('throw original error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
232
|
+
jest.setTimeout(60000);
|
|
233
|
+
const calledSpy = jest.spyOn(testClass, 'called');
|
|
234
|
+
calledSpy.mockImplementation(() => { throw new CustomError(); });
|
|
235
|
+
try {
|
|
236
|
+
yield testClass.useOriginalError();
|
|
237
|
+
}
|
|
238
|
+
catch (e) {
|
|
239
|
+
expect(e).toBeInstanceOf(CustomError);
|
|
240
|
+
}
|
|
241
|
+
}));
|
|
196
242
|
});
|
|
197
243
|
//# sourceMappingURL=retry.decorator.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.decorator.test.js","sourceRoot":"","sources":["../src/retry.decorator.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"retry.decorator.test.js","sourceRoot":"","sources":["../src/retry.decorator.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import exp = require('constants');
|
|
2
|
+
import { BackOffPolicy, MaxAttemptsError, Retryable } from './retry.decorator';
|
|
2
3
|
|
|
3
4
|
class TestClass {
|
|
4
5
|
count: number;
|
|
@@ -48,6 +49,17 @@ class TestClass {
|
|
|
48
49
|
await this.called();
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
@Retryable({ maxAttempts: 2, useConsoleLogger: false })
|
|
53
|
+
async noLog(): Promise<void> {
|
|
54
|
+
console.log(`test method is called for ${++this.count} time`);
|
|
55
|
+
await this.called();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@Retryable({ maxAttempts: 2, useOriginalError: true })
|
|
59
|
+
async useOriginalError(): Promise<void> {
|
|
60
|
+
await this.called();
|
|
61
|
+
}
|
|
62
|
+
|
|
51
63
|
async called(): Promise<string> {
|
|
52
64
|
return 'from real implementation';
|
|
53
65
|
}
|
|
@@ -96,7 +108,7 @@ describe('Retry Test', () => {
|
|
|
96
108
|
try {
|
|
97
109
|
await testClass.testMethod();
|
|
98
110
|
} catch (e) {
|
|
99
|
-
expect(e).
|
|
111
|
+
expect(e).toBeInstanceOf(MaxAttemptsError);
|
|
100
112
|
expect(e.message.includes(errorMsg));
|
|
101
113
|
}
|
|
102
114
|
expect(calledSpy).toHaveBeenCalledTimes(3);
|
|
@@ -153,5 +165,29 @@ describe('Retry Test', () => {
|
|
|
153
165
|
} catch (e) {}
|
|
154
166
|
expect(calledSpy).toHaveBeenCalledTimes(4);
|
|
155
167
|
});
|
|
168
|
+
|
|
169
|
+
test('no log', async () => {
|
|
170
|
+
const calledSpy = jest.spyOn(testClass, 'called');
|
|
171
|
+
const errorSpy = jest.spyOn(console, 'error');
|
|
172
|
+
calledSpy.mockRejectedValueOnce(new Error('rejected'));
|
|
173
|
+
calledSpy.mockResolvedValueOnce('fulfilled');
|
|
174
|
+
await testClass.testMethod();
|
|
175
|
+
expect(calledSpy).toHaveBeenCalledTimes(2);
|
|
176
|
+
expect(errorSpy).not.toHaveBeenCalled();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// CustomError for testing.
|
|
180
|
+
class CustomError extends Error { }
|
|
181
|
+
|
|
182
|
+
test('throw original error', async () => {
|
|
183
|
+
jest.setTimeout(60000);
|
|
184
|
+
const calledSpy = jest.spyOn(testClass, 'called');
|
|
185
|
+
calledSpy.mockImplementation(() => { throw new CustomError(); });
|
|
186
|
+
try {
|
|
187
|
+
await testClass.useOriginalError();
|
|
188
|
+
} catch (e) {
|
|
189
|
+
expect(e).toBeInstanceOf(CustomError);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
156
192
|
});
|
|
157
193
|
|
package/src/retry.decorator.ts
CHANGED
|
@@ -40,7 +40,8 @@ export function Retryable(options: RetryOptions): DecoratorFunction {
|
|
|
40
40
|
return await fn.apply(this, args);
|
|
41
41
|
} catch (e) {
|
|
42
42
|
if (--maxAttempts < 0) {
|
|
43
|
-
e?.message && console.error(e.message);
|
|
43
|
+
(typeof options.useConsoleLogger !== 'boolean' || options.useConsoleLogger) && e?.message && console.error(e.message);
|
|
44
|
+
if(options.useOriginalError) throw e;
|
|
44
45
|
const maxAttemptsErrorInstance = new MaxAttemptsError(e?.message);
|
|
45
46
|
// Add the existing error stack if present
|
|
46
47
|
if(e?.stack) {
|
|
@@ -54,8 +55,7 @@ export function Retryable(options: RetryOptions): DecoratorFunction {
|
|
|
54
55
|
}
|
|
55
56
|
backOff && (await sleep(backOff));
|
|
56
57
|
if (options.backOffPolicy === BackOffPolicy.ExponentialBackOffPolicy) {
|
|
57
|
-
|
|
58
|
-
backOff = newBackOff > options.exponentialOption.maxInterval ? options.exponentialOption.maxInterval : newBackOff;
|
|
58
|
+
backOff = Math.min(backOff * options.exponentialOption.multiplier, options.exponentialOption.maxInterval);
|
|
59
59
|
}
|
|
60
60
|
return retryAsync.apply(this, [fn, args, maxAttempts, backOff]);
|
|
61
61
|
}
|
|
@@ -90,12 +90,14 @@ export class MaxAttemptsError extends Error {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
export interface RetryOptions {
|
|
93
|
-
maxAttempts: number;
|
|
94
93
|
backOffPolicy?: BackOffPolicy;
|
|
95
94
|
backOff?: number;
|
|
96
95
|
doRetry?: (e: any) => boolean;
|
|
97
|
-
value?: ErrorConstructor[];
|
|
98
96
|
exponentialOption?: { maxInterval: number; multiplier: number };
|
|
97
|
+
maxAttempts: number;
|
|
98
|
+
value?: ErrorConstructor[];
|
|
99
|
+
useConsoleLogger?: boolean;
|
|
100
|
+
useOriginalError?: boolean;
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
export enum BackOffPolicy {
|