cabloy 5.1.123 → 5.1.125

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.
@@ -77,7 +77,7 @@ importers:
77
77
  version: 10.5.2(postcss@8.5.15)
78
78
  axios:
79
79
  specifier: ^1.18.1
80
- version: 1.18.1(supports-color@10.2.2)
80
+ version: 1.18.1
81
81
  compression:
82
82
  specifier: ^1.8.1
83
83
  version: 1.8.1
@@ -136,7 +136,7 @@ importers:
136
136
  specifier: workspace:^
137
137
  version: link:packages-zova/zova
138
138
  zova-jsx:
139
- specifier: ^1.1.79
139
+ specifier: ^1.1.81
140
140
  version: link:packages-utils/zova-jsx
141
141
  zova-module-a-api:
142
142
  specifier: workspace:^
@@ -354,7 +354,7 @@ importers:
354
354
  devDependencies:
355
355
  '@cabloy/cli':
356
356
  specifier: ^3.1.28
357
- version: 3.1.28(supports-color@10.2.2)(vue@3.5.38(typescript@5.9.3))
357
+ version: 3.1.28(vue@3.5.38(typescript@5.9.3))
358
358
  '@cabloy/lint':
359
359
  specifier: ^5.1.27
360
360
  version: 5.1.30(@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.6.0(jiti@2.7.0))(typescript@5.9.3))(@typescript-eslint/rule-tester@8.62.1(eslint@10.6.0(jiti@2.7.0))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.62.1(typescript@5.9.3))(@typescript-eslint/utils@8.62.1(eslint@10.6.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.6.0(jiti@2.7.0))(oxfmt@0.45.0)(oxlint@1.72.0)(supports-color@10.2.2)(typescript@5.9.3)(vue-eslint-parser@10.4.1(eslint@10.6.0(jiti@2.7.0)))
@@ -429,7 +429,7 @@ importers:
429
429
  dependencies:
430
430
  '@cabloy/cli':
431
431
  specifier: ^3.1.28
432
- version: 3.1.28(supports-color@10.2.2)(vue@3.5.38(typescript@5.9.3))
432
+ version: 3.1.28(vue@3.5.38(typescript@5.9.3))
433
433
  '@cabloy/process-helper':
434
434
  specifier: ^3.1.8
435
435
  version: 3.1.8
@@ -440,7 +440,7 @@ importers:
440
440
  specifier: ^7.6.2
441
441
  version: 7.8.5
442
442
  zova-cli-set-front:
443
- specifier: ^1.2.98
443
+ specifier: ^1.2.99
444
444
  version: link:../cli-set-front
445
445
  devDependencies:
446
446
  clean-package:
@@ -463,7 +463,7 @@ importers:
463
463
  version: 7.29.7(@babel/core@7.29.7)
464
464
  '@cabloy/cli':
465
465
  specifier: ^3.1.28
466
- version: 3.1.28(supports-color@10.2.2)(vue@3.5.38(typescript@5.9.3))
466
+ version: 3.1.28(vue@3.5.38(typescript@5.9.3))
467
467
  '@cabloy/extend':
468
468
  specifier: ^3.2.8
469
469
  version: 3.2.8
@@ -717,7 +717,7 @@ importers:
717
717
  specifier: ^3.5.38
718
718
  version: 3.5.38(typescript@5.9.3)
719
719
  zova-core:
720
- specifier: ^5.1.79
720
+ specifier: ^5.1.81
721
721
  version: link:../../packages-zova/zova-core
722
722
  devDependencies:
723
723
  clean-package:
@@ -858,10 +858,10 @@ importers:
858
858
  packages-zova/zova:
859
859
  dependencies:
860
860
  zova-core:
861
- specifier: ^5.1.79
861
+ specifier: ^5.1.81
862
862
  version: link:../zova-core
863
863
  zova-suite-a-zova:
864
- specifier: ^5.1.141
864
+ specifier: ^5.1.143
865
865
  version: link:../../src/suite-vendor/a-zova
866
866
  devDependencies:
867
867
  clean-package:
@@ -974,16 +974,16 @@ importers:
974
974
  src/suite-vendor/a-pay:
975
975
  dependencies:
976
976
  zova-module-a-pay:
977
- specifier: ^5.0.0
977
+ specifier: ^5.0.2
978
978
  version: link:modules/a-pay
979
979
  zova-module-pay-mock:
980
- specifier: ^5.0.0
980
+ specifier: ^5.0.2
981
981
  version: link:modules/pay-mock
982
982
  zova-module-pay-paypal:
983
- specifier: ^5.0.0
983
+ specifier: ^5.0.1
984
984
  version: link:modules/pay-paypal
985
985
  zova-module-pay-stripe:
986
- specifier: ^5.0.0
986
+ specifier: ^5.0.1
987
987
  version: link:modules/pay-stripe
988
988
 
989
989
  src/suite-vendor/a-pay/modules/a-pay:
@@ -1097,7 +1097,7 @@ importers:
1097
1097
  specifier: ^5.1.36
1098
1098
  version: link:modules/a-zod
1099
1099
  zova-module-a-zova:
1100
- specifier: ^5.1.94
1100
+ specifier: ^5.1.96
1101
1101
  version: link:modules/a-zova
1102
1102
 
1103
1103
  src/suite-vendor/a-zova/modules/a-api:
@@ -1171,7 +1171,7 @@ importers:
1171
1171
  dependencies:
1172
1172
  axios:
1173
1173
  specifier: ^1.18.1
1174
- version: 1.18.1(supports-color@10.2.2)
1174
+ version: 1.18.1
1175
1175
  devDependencies:
1176
1176
  clean-package:
1177
1177
  specifier: ^2.2.0
@@ -1439,12 +1439,12 @@ importers:
1439
1439
  specifier: ^3.7.2
1440
1440
  version: 3.7.2
1441
1441
  zova-jsx:
1442
- specifier: ^1.1.79
1442
+ specifier: ^1.1.81
1443
1443
  version: link:../../../../../packages-utils/zova-jsx
1444
1444
  devDependencies:
1445
1445
  '@cabloy/cli':
1446
1446
  specifier: ^3.1.28
1447
- version: 3.1.28(supports-color@10.2.2)(vue@3.5.38(typescript@5.9.3))
1447
+ version: 3.1.28(vue@3.5.38(typescript@5.9.3))
1448
1448
  '@types/luxon':
1449
1449
  specifier: ^3.7.1
1450
1450
  version: 3.7.2
@@ -8419,7 +8419,7 @@ snapshots:
8419
8419
 
8420
8420
  '@bufbuild/protobuf@2.12.1': {}
8421
8421
 
8422
- '@cabloy/cli@3.1.28(supports-color@10.2.2)(vue@3.5.38(typescript@5.9.3))':
8422
+ '@cabloy/cli@3.1.28(vue@3.5.38(typescript@5.9.3))':
8423
8423
  dependencies:
8424
8424
  '@babel/parser': 7.29.7
8425
8425
  '@cabloy/module-glob': 5.3.17
@@ -8428,7 +8428,7 @@ snapshots:
8428
8428
  '@cabloy/utils': 2.1.26
8429
8429
  '@cabloy/word-utils': link:packages-utils/word-utils
8430
8430
  '@npmcli/config': 10.11.0
8431
- '@zhennann/common-bin': 4.0.1(supports-color@10.2.2)
8431
+ '@zhennann/common-bin': 4.0.1
8432
8432
  '@zhennann/ejs': 3.0.1
8433
8433
  boxen: 4.2.0
8434
8434
  chalk: 3.0.0
@@ -10454,7 +10454,7 @@ snapshots:
10454
10454
 
10455
10455
  '@vue/shared@3.5.13': {}
10456
10456
 
10457
- '@zhennann/common-bin@4.0.1(supports-color@10.2.2)':
10457
+ '@zhennann/common-bin@4.0.1':
10458
10458
  dependencies:
10459
10459
  chalk: 4.1.2
10460
10460
  change-case: 4.1.2
@@ -10488,7 +10488,7 @@ snapshots:
10488
10488
 
10489
10489
  acorn@8.17.0: {}
10490
10490
 
10491
- agent-base@6.0.2(supports-color@10.2.2):
10491
+ agent-base@6.0.2:
10492
10492
  dependencies:
10493
10493
  debug: 4.4.3(supports-color@10.2.2)
10494
10494
  transitivePeerDependencies:
@@ -10600,11 +10600,11 @@ snapshots:
10600
10600
  dependencies:
10601
10601
  possible-typed-array-names: 1.1.0
10602
10602
 
10603
- axios@1.18.1(supports-color@10.2.2):
10603
+ axios@1.18.1:
10604
10604
  dependencies:
10605
10605
  follow-redirects: 1.16.0
10606
10606
  form-data: 4.0.6
10607
- https-proxy-agent: 5.0.1(supports-color@10.2.2)
10607
+ https-proxy-agent: 5.0.1
10608
10608
  proxy-from-env: 2.1.0
10609
10609
  transitivePeerDependencies:
10610
10610
  - debug
@@ -12015,9 +12015,9 @@ snapshots:
12015
12015
  statuses: 2.0.2
12016
12016
  toidentifier: 1.0.1
12017
12017
 
12018
- https-proxy-agent@5.0.1(supports-color@10.2.2):
12018
+ https-proxy-agent@5.0.1:
12019
12019
  dependencies:
12020
- agent-base: 6.0.2(supports-color@10.2.2)
12020
+ agent-base: 6.0.2
12021
12021
  debug: 4.4.3(supports-color@10.2.2)
12022
12022
  transitivePeerDependencies:
12023
12023
  - supports-color
@@ -1,209 +0,0 @@
1
- import assert from 'node:assert';
2
- import { randomUUID } from 'node:crypto';
3
- import { describe, it } from 'node:test';
4
- import { app } from 'vona-mock';
5
-
6
- import type { IPaymentOutcomeEvent } from '../src/types/payment.ts';
7
-
8
- interface IFixture {
9
- userId?: number;
10
- paymentSessionId?: number;
11
- outboxEventIds: number[];
12
- }
13
-
14
- async function createFixture(suffix: string): Promise<IFixture> {
15
- const scope = app.scope('a-pay');
16
- const user = await app.bean.user.register({ name: `pay-outbox-${suffix}` }, true);
17
- const session = await scope.service.paymentSession.create({
18
- userId: user.id,
19
- payScene: 'commerce-payment:commerceOrder',
20
- businessReference: `business-${suffix}`,
21
- amountMinor: 1299,
22
- currency: 'USD',
23
- correlationId: `payment-${suffix}`,
24
- });
25
- return { userId: user.id as number, paymentSessionId: session.id as number, outboxEventIds: [] };
26
- }
27
-
28
- function createOutcomePayload(fixture: IFixture): IPaymentOutcomeEvent {
29
- return {
30
- eventId: randomUUID(),
31
- paymentSessionId: fixture.paymentSessionId!,
32
- businessReference: 'outbox-test',
33
- providerName: 'test-provider',
34
- state: 'succeeded',
35
- amountMinor: 1299,
36
- currency: 'USD',
37
- };
38
- }
39
-
40
- async function insertOutbox(
41
- fixture: IFixture,
42
- overrides?: Partial<{
43
- eventType: 'payment.outcome.v1';
44
- state: 'pending' | 'claimed';
45
- attemptCount: number;
46
- nextAttemptAt: Date;
47
- claimToken: string;
48
- claimedAt: Date;
49
- claimExpiresAt: Date;
50
- }>,
51
- ) {
52
- const event = await app.scope('a-pay').model.outboxEvent.insert({
53
- eventType: overrides?.eventType ?? 'payment.outcome.v1',
54
- paymentSessionId: fixture.paymentSessionId!,
55
- payload: createOutcomePayload(fixture),
56
- state: overrides?.state ?? 'pending',
57
- attemptCount: overrides?.attemptCount ?? 0,
58
- nextAttemptAt: overrides?.nextAttemptAt ?? new Date(Date.now() - 1_000),
59
- claimToken: overrides?.claimToken,
60
- claimedAt: overrides?.claimedAt,
61
- claimExpiresAt: overrides?.claimExpiresAt,
62
- });
63
- fixture.outboxEventIds.push(event.id as number);
64
- return event;
65
- }
66
-
67
- async function cleanup(fixture: IFixture) {
68
- const scope = app.scope('a-pay');
69
- for (const id of fixture.outboxEventIds) await scope.model.outboxEvent.delete({ id });
70
- if (fixture.paymentSessionId !== undefined) {
71
- await scope.model.paymentAudit.delete({ paymentSessionId: fixture.paymentSessionId });
72
- await scope.model.webhookInbox.delete({ paymentSessionId: fixture.paymentSessionId });
73
- await scope.model.paymentSession.delete({ id: fixture.paymentSessionId });
74
- }
75
- if (fixture.userId !== undefined) {
76
- await app.scope('home-user').model.roleUser.delete({ userId: fixture.userId });
77
- await app.bean.user.removeById(fixture.userId);
78
- }
79
- }
80
-
81
- describe('outbox.test.ts', { concurrency: false }, () => {
82
- it('claims, backs off, and exhausts durable delivery attempts', async () => {
83
- await app.bean.executor.mockCtx(async () => {
84
- const fixture = await createFixture(randomUUID().slice(0, 12));
85
- try {
86
- const event = await insertOutbox(fixture);
87
- const scope = app.scope('a-pay');
88
- const first = await scope.service.outbox.claim(event.id);
89
- assert.equal(first?.attemptCount, 1);
90
- assert.ok(first?.claimToken);
91
- const releaseStart = Date.now();
92
- await scope.service.outbox.release(
93
- event.id,
94
- first!.claimToken!,
95
- new Error('first failure'),
96
- );
97
- let persisted = await scope.model.outboxEvent.getById(event.id);
98
- assert.equal(persisted?.state, 'pending');
99
- assert.equal(persisted?.errorSummary, 'first failure');
100
- assert.ok((persisted?.nextAttemptAt?.getTime() ?? 0) >= releaseStart + 900);
101
- assert.equal(await scope.service.outbox.claim(event.id), undefined);
102
- await scope.model.outboxEvent.updateById(event.id, {
103
- nextAttemptAt: new Date(Date.now() - 1),
104
- });
105
- const second = await scope.service.outbox.claim(event.id);
106
- assert.equal(second?.attemptCount, 2);
107
- const secondReleaseStart = Date.now();
108
- await scope.service.outbox.release(
109
- event.id,
110
- second!.claimToken!,
111
- new Error('second failure'),
112
- );
113
- persisted = await scope.model.outboxEvent.getById(event.id);
114
- assert.ok((persisted?.nextAttemptAt?.getTime() ?? 0) >= secondReleaseStart + 1_900);
115
-
116
- const exhausted = await insertOutbox(fixture, { attemptCount: 10 });
117
- assert.equal(await scope.service.outbox.claim(exhausted.id), undefined);
118
- assert.equal((await scope.model.outboxEvent.getById(exhausted.id))?.state, 'failed');
119
- } finally {
120
- await cleanup(fixture);
121
- }
122
- });
123
- });
124
-
125
- it('retries a dispatch when the persisted payment scene is unavailable', async () => {
126
- await app.bean.executor.mockCtx(async () => {
127
- const fixture = await createFixture(randomUUID().slice(0, 12));
128
- try {
129
- const scope = app.scope('a-pay');
130
- await scope.model.paymentSession.updateById(fixture.paymentSessionId!, {
131
- payScene: 'test-payment',
132
- });
133
- const event = await insertOutbox(fixture);
134
- await scope.queue.outboxDispatch.pushAsync({ outboxEventId: event.id });
135
- const persisted = await scope.model.outboxEvent.getById(event.id);
136
- assert.equal(persisted?.state, 'pending');
137
- assert.equal(persisted?.attemptCount, 1);
138
- assert.match(persisted?.errorSummary ?? '', /payment scene not found/);
139
- } finally {
140
- await cleanup(fixture);
141
- }
142
- });
143
- });
144
-
145
- it('reclaims expired leases and fences stale claim tokens', async () => {
146
- await app.bean.executor.mockCtx(async () => {
147
- const fixture = await createFixture(randomUUID().slice(0, 12));
148
- try {
149
- const event = await insertOutbox(fixture);
150
- const scope = app.scope('a-pay');
151
- const first = await scope.service.outbox.claim(event.id);
152
- await scope.model.outboxEvent.updateById(event.id, {
153
- claimExpiresAt: new Date(Date.now() - 1),
154
- });
155
- const second = await scope.service.outbox.claim(event.id);
156
- assert.ok(second?.claimToken);
157
- assert.notEqual(second?.claimToken, first?.claimToken);
158
- assert.equal(second?.attemptCount, 2);
159
- assert.equal(
160
- await scope.service.outbox.markDispatched(event.id, first!.claimToken!),
161
- undefined,
162
- );
163
- assert.equal(
164
- await scope.service.outbox.release(event.id, first!.claimToken!, new Error('stale')),
165
- undefined,
166
- );
167
- assert.equal(
168
- (await scope.model.outboxEvent.getById(event.id))?.claimToken,
169
- second?.claimToken,
170
- );
171
- await scope.service.outbox.markDispatched(event.id, second!.claimToken!);
172
- const persisted = await scope.model.outboxEvent.getById(event.id);
173
- assert.equal(persisted?.state, 'dispatched');
174
- assert.equal(persisted?.claimToken, undefined);
175
- } finally {
176
- await cleanup(fixture);
177
- }
178
- });
179
- });
180
-
181
- it('rolls back enqueued durable rows with the enclosing transaction', async () => {
182
- await app.bean.executor.mockCtx(async () => {
183
- const fixture = await createFixture(randomUUID().slice(0, 12));
184
- try {
185
- const scope = app.scope('a-pay');
186
- const eventId = await assert.rejects(
187
- app.ctx.db.transaction.begin(async () => {
188
- const event = await scope.service.outbox.enqueue(
189
- fixture.paymentSessionId!,
190
- 'payment.outcome.v1',
191
- createOutcomePayload(fixture),
192
- );
193
- fixture.outboxEventIds.push(event.id as number);
194
- throw new Error(String(event.id));
195
- }),
196
- /\d+/,
197
- );
198
- assert.equal(eventId, undefined);
199
- const events = await scope.model.outboxEvent.select({
200
- where: { paymentSessionId: fixture.paymentSessionId },
201
- });
202
- assert.deepEqual(events, []);
203
- fixture.outboxEventIds = [];
204
- } finally {
205
- await cleanup(fixture);
206
- }
207
- });
208
- });
209
- });
@@ -1,153 +0,0 @@
1
- import assert from 'node:assert';
2
- import { randomUUID } from 'node:crypto';
3
- import { describe, it } from 'node:test';
4
- import { app } from 'vona-mock';
5
-
6
- interface IFixture {
7
- userId?: number;
8
- paymentSessionId?: number;
9
- }
10
-
11
- async function createFixture(expiresAt: Date): Promise<IFixture> {
12
- const scope = app.scope('a-pay');
13
- const suffix = randomUUID().slice(0, 12);
14
- const user = await app.bean.user.register({ name: `payment-session-${suffix}` }, true);
15
- const session = await scope.service.paymentSession.create({
16
- userId: user.id,
17
- payScene: 'commerce-payment:commerceOrder',
18
- businessReference: `business-${suffix}`,
19
- amountMinor: 1299,
20
- currency: 'USD',
21
- correlationId: `payment-${suffix}`,
22
- });
23
- await scope.model.paymentSession.updateById(session.id, { expiresAt });
24
- return { userId: user.id as number, paymentSessionId: session.id as number };
25
- }
26
-
27
- async function cleanup(fixture: IFixture) {
28
- const scope = app.scope('a-pay');
29
- if (fixture.paymentSessionId !== undefined) {
30
- await scope.model.paymentAudit.delete({ paymentSessionId: fixture.paymentSessionId });
31
- await scope.model.paymentSession.delete({ id: fixture.paymentSessionId });
32
- }
33
- if (fixture.userId !== undefined) {
34
- await app.scope('home-user').model.roleUser.delete({ userId: fixture.userId });
35
- await app.bean.user.removeById(fixture.userId);
36
- }
37
- }
38
-
39
- describe('paymentSession.test.ts', { concurrency: false }, () => {
40
- it('derives provider facts and expiry from the payment scene', async () => {
41
- await app.bean.executor.mockCtx(async () => {
42
- const scope = app.scope('a-pay');
43
- const suffix = randomUUID().slice(0, 12);
44
- const user = await app.bean.user.register({ name: `payment-session-${suffix}` }, true);
45
- const fixture: IFixture = { userId: user.id as number };
46
- try {
47
- const createdAt = Date.now();
48
- const session = await scope.service.paymentSession.create({
49
- userId: user.id,
50
- payScene: 'commerce-payment:commerceOrder',
51
- businessReference: `business-${suffix}`,
52
- amountMinor: 1299,
53
- currency: 'USD',
54
- correlationId: `payment-${suffix}`,
55
- });
56
- fixture.paymentSessionId = session.id as number;
57
- assert.equal(session.providerName, 'pay-mock:mock');
58
- assert.equal(session.clientName, 'default');
59
- assert.equal(session.environment, 'sandbox');
60
- assert.ok(session.expiresAt.getTime() >= createdAt + 30 * 60 * 1000);
61
- assert.ok(session.expiresAt.getTime() <= Date.now() + 30 * 60 * 1000);
62
- } finally {
63
- await cleanup(fixture);
64
- }
65
- });
66
- });
67
-
68
- it('rejects a currency outside the payment scene policy', async () => {
69
- await app.bean.executor.mockCtx(async () => {
70
- const scope = app.scope('a-pay');
71
- const suffix = randomUUID().slice(0, 12);
72
- const user = await app.bean.user.register({ name: `payment-session-${suffix}` }, true);
73
- const fixture: IFixture = { userId: user.id as number };
74
- try {
75
- await assert.rejects(
76
- scope.service.paymentSession.create({
77
- userId: user.id,
78
- payScene: 'commerce-payment:commerceOrder',
79
- businessReference: `business-${suffix}`,
80
- amountMinor: 1299,
81
- currency: 'EUR',
82
- correlationId: `payment-${suffix}`,
83
- }),
84
- { status: 422 },
85
- );
86
- assert.deepEqual(
87
- await scope.model.paymentSession.select({
88
- where: { correlationId: `payment-${suffix}` },
89
- }),
90
- [],
91
- );
92
- } finally {
93
- await cleanup(fixture);
94
- }
95
- });
96
- });
97
-
98
- it('starts only an unexpired created payment session', async () => {
99
- await app.bean.executor.mockCtx(async () => {
100
- const fixture = await createFixture(new Date(Date.now() + 60_000));
101
- try {
102
- const scope = app.scope('a-pay');
103
- const session = await scope.service.paymentSession.start(fixture.paymentSessionId!);
104
- assert.equal(session.state, 'requires_action');
105
- await assert.rejects(scope.service.paymentSession.start(fixture.paymentSessionId!), {
106
- status: 409,
107
- });
108
- } finally {
109
- await cleanup(fixture);
110
- }
111
- });
112
- });
113
-
114
- it('does not start an expired payment session', async () => {
115
- await app.bean.executor.mockCtx(async () => {
116
- const fixture = await createFixture(new Date(Date.now() - 1));
117
- try {
118
- const scope = app.scope('a-pay');
119
- await assert.rejects(scope.service.paymentSession.start(fixture.paymentSessionId!), {
120
- status: 409,
121
- });
122
- assert.equal(
123
- (await scope.model.paymentSession.getById(fixture.paymentSessionId!))?.state,
124
- 'created',
125
- );
126
- } finally {
127
- await cleanup(fixture);
128
- }
129
- });
130
- });
131
-
132
- it('allows only one competing start to call the provider', async () => {
133
- const fixture = await app.bean.executor.mockCtx(async () => {
134
- return await createFixture(new Date(Date.now() + 60_000));
135
- });
136
- try {
137
- const results = await Promise.allSettled([
138
- app.bean.executor.mockCtx(async () => {
139
- return await app.scope('a-pay').service.paymentSession.start(fixture.paymentSessionId!);
140
- }),
141
- app.bean.executor.mockCtx(async () => {
142
- return await app.scope('a-pay').service.paymentSession.start(fixture.paymentSessionId!);
143
- }),
144
- ]);
145
- assert.equal(results.filter(result => result.status === 'fulfilled').length, 1);
146
- assert.equal(results.filter(result => result.status === 'rejected').length, 1);
147
- } finally {
148
- await app.bean.executor.mockCtx(async () => {
149
- await cleanup(fixture);
150
- });
151
- }
152
- });
153
- });