@mastra/dynamodb 0.11.1-alpha.0 → 0.11.1-alpha.1

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.
@@ -2,6 +2,7 @@ import { DynamoDBClient, DescribeTableCommand } from '@aws-sdk/client-dynamodb';
2
2
  import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
3
3
  import type { MastraMessageContentV2 } from '@mastra/core/agent';
4
4
  import { MessageList } from '@mastra/core/agent';
5
+ import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
5
6
  import type { StorageThreadType, MastraMessageV2, MastraMessageV1 } from '@mastra/core/memory';
6
7
 
7
8
  import {
@@ -63,25 +64,36 @@ export class DynamoDBStore extends MastraStorage {
63
64
  super({ name });
64
65
 
65
66
  // Validate required config
66
- if (!config.tableName || typeof config.tableName !== 'string' || config.tableName.trim() === '') {
67
- throw new Error('DynamoDBStore: config.tableName must be provided and cannot be empty.');
68
- }
69
- // Validate tableName characters (basic check)
70
- if (!/^[a-zA-Z0-9_.-]{3,255}$/.test(config.tableName)) {
71
- throw new Error(
72
- `DynamoDBStore: config.tableName "${config.tableName}" contains invalid characters or is not between 3 and 255 characters long.`,
73
- );
74
- }
67
+ try {
68
+ if (!config.tableName || typeof config.tableName !== 'string' || config.tableName.trim() === '') {
69
+ throw new Error('DynamoDBStore: config.tableName must be provided and cannot be empty.');
70
+ }
71
+ // Validate tableName characters (basic check)
72
+ if (!/^[a-zA-Z0-9_.-]{3,255}$/.test(config.tableName)) {
73
+ throw new Error(
74
+ `DynamoDBStore: config.tableName "${config.tableName}" contains invalid characters or is not between 3 and 255 characters long.`,
75
+ );
76
+ }
75
77
 
76
- const dynamoClient = new DynamoDBClient({
77
- region: config.region || 'us-east-1',
78
- endpoint: config.endpoint,
79
- credentials: config.credentials,
80
- });
78
+ const dynamoClient = new DynamoDBClient({
79
+ region: config.region || 'us-east-1',
80
+ endpoint: config.endpoint,
81
+ credentials: config.credentials,
82
+ });
81
83
 
82
- this.tableName = config.tableName;
83
- this.client = DynamoDBDocumentClient.from(dynamoClient);
84
- this.service = getElectroDbService(this.client, this.tableName) as MastraService;
84
+ this.tableName = config.tableName;
85
+ this.client = DynamoDBDocumentClient.from(dynamoClient);
86
+ this.service = getElectroDbService(this.client, this.tableName) as MastraService;
87
+ } catch (error) {
88
+ throw new MastraError(
89
+ {
90
+ id: 'STORAGE_DYNAMODB_STORE_CONSTRUCTOR_FAILED',
91
+ domain: ErrorDomain.STORAGE,
92
+ category: ErrorCategory.USER,
93
+ },
94
+ error,
95
+ );
96
+ }
85
97
 
86
98
  // We're using a single table design with ElectroDB,
87
99
  // so we don't need to create multiple tables
@@ -113,7 +125,15 @@ export class DynamoDBStore extends MastraStorage {
113
125
  this.logger.debug(`Table ${this.tableName} exists and is accessible`);
114
126
  } catch (error) {
115
127
  this.logger.error('Error validating table access', { tableName: this.tableName, error });
116
- throw error;
128
+ throw new MastraError(
129
+ {
130
+ id: 'STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_ACCESS_FAILED',
131
+ domain: ErrorDomain.STORAGE,
132
+ category: ErrorCategory.THIRD_PARTY,
133
+ details: { tableName: this.tableName },
134
+ },
135
+ error,
136
+ );
117
137
  }
118
138
  }
119
139
 
@@ -139,7 +159,15 @@ export class DynamoDBStore extends MastraStorage {
139
159
  }
140
160
 
141
161
  // For other errors (like permissions issues), we should throw
142
- throw error;
162
+ throw new MastraError(
163
+ {
164
+ id: 'STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_EXISTS_FAILED',
165
+ domain: ErrorDomain.STORAGE,
166
+ category: ErrorCategory.THIRD_PARTY,
167
+ details: { tableName: this.tableName },
168
+ },
169
+ error,
170
+ );
143
171
  }
144
172
  }
145
173
 
@@ -166,7 +194,15 @@ export class DynamoDBStore extends MastraStorage {
166
194
  // The error has already been handled by _performInitializationAndStore
167
195
  // (i.e., this.hasInitialized was reset). Re-throwing here ensures
168
196
  // the caller of init() is aware of the failure.
169
- throw error;
197
+ throw new MastraError(
198
+ {
199
+ id: 'STORAGE_DYNAMODB_STORE_INIT_FAILED',
200
+ domain: ErrorDomain.STORAGE,
201
+ category: ErrorCategory.THIRD_PARTY,
202
+ details: { tableName: this.tableName },
203
+ },
204
+ error,
205
+ );
170
206
  }
171
207
  }
172
208
 
@@ -232,7 +268,13 @@ export class DynamoDBStore extends MastraStorage {
232
268
 
233
269
  const entityName = this.getEntityNameForTable(tableName);
234
270
  if (!entityName || !this.service.entities[entityName]) {
235
- throw new Error(`No entity defined for ${tableName}`);
271
+ throw new MastraError({
272
+ id: 'STORAGE_DYNAMODB_STORE_CLEAR_TABLE_INVALID_ARGS',
273
+ domain: ErrorDomain.STORAGE,
274
+ category: ErrorCategory.USER,
275
+ text: 'No entity defined for tableName',
276
+ details: { tableName },
277
+ });
236
278
  }
237
279
 
238
280
  try {
@@ -302,8 +344,15 @@ export class DynamoDBStore extends MastraStorage {
302
344
 
303
345
  this.logger.debug(`Successfully cleared all records for ${tableName}`);
304
346
  } catch (error) {
305
- this.logger.error('Failed to clear table', { tableName, error });
306
- throw error;
347
+ throw new MastraError(
348
+ {
349
+ id: 'STORAGE_DYNAMODB_STORE_CLEAR_TABLE_FAILED',
350
+ domain: ErrorDomain.STORAGE,
351
+ category: ErrorCategory.THIRD_PARTY,
352
+ details: { tableName },
353
+ },
354
+ error,
355
+ );
307
356
  }
308
357
  }
309
358
 
@@ -315,7 +364,13 @@ export class DynamoDBStore extends MastraStorage {
315
364
 
316
365
  const entityName = this.getEntityNameForTable(tableName);
317
366
  if (!entityName || !this.service.entities[entityName]) {
318
- throw new Error(`No entity defined for ${tableName}`);
367
+ throw new MastraError({
368
+ id: 'STORAGE_DYNAMODB_STORE_INSERT_INVALID_ARGS',
369
+ domain: ErrorDomain.STORAGE,
370
+ category: ErrorCategory.USER,
371
+ text: 'No entity defined for tableName',
372
+ details: { tableName },
373
+ });
319
374
  }
320
375
 
321
376
  try {
@@ -323,8 +378,15 @@ export class DynamoDBStore extends MastraStorage {
323
378
  const dataToSave = { entity: entityName, ...this.preprocessRecord(record) };
324
379
  await this.service.entities[entityName].create(dataToSave).go();
325
380
  } catch (error) {
326
- this.logger.error('Failed to insert record', { tableName, error });
327
- throw error;
381
+ throw new MastraError(
382
+ {
383
+ id: 'STORAGE_DYNAMODB_STORE_INSERT_FAILED',
384
+ domain: ErrorDomain.STORAGE,
385
+ category: ErrorCategory.THIRD_PARTY,
386
+ details: { tableName },
387
+ },
388
+ error,
389
+ );
328
390
  }
329
391
  }
330
392
 
@@ -336,7 +398,13 @@ export class DynamoDBStore extends MastraStorage {
336
398
 
337
399
  const entityName = this.getEntityNameForTable(tableName);
338
400
  if (!entityName || !this.service.entities[entityName]) {
339
- throw new Error(`No entity defined for ${tableName}`);
401
+ throw new MastraError({
402
+ id: 'STORAGE_DYNAMODB_STORE_BATCH_INSERT_INVALID_ARGS',
403
+ domain: ErrorDomain.STORAGE,
404
+ category: ErrorCategory.USER,
405
+ text: 'No entity defined for tableName',
406
+ details: { tableName },
407
+ });
340
408
  }
341
409
 
342
410
  // Add entity type and preprocess each record
@@ -366,8 +434,15 @@ export class DynamoDBStore extends MastraStorage {
366
434
  // Original batch call: await this.service.entities[entityName].create(batch).go();
367
435
  }
368
436
  } catch (error) {
369
- this.logger.error('Failed to batch insert records', { tableName, error });
370
- throw error;
437
+ throw new MastraError(
438
+ {
439
+ id: 'STORAGE_DYNAMODB_STORE_BATCH_INSERT_FAILED',
440
+ domain: ErrorDomain.STORAGE,
441
+ category: ErrorCategory.THIRD_PARTY,
442
+ details: { tableName },
443
+ },
444
+ error,
445
+ );
371
446
  }
372
447
  }
373
448
 
@@ -379,7 +454,13 @@ export class DynamoDBStore extends MastraStorage {
379
454
 
380
455
  const entityName = this.getEntityNameForTable(tableName);
381
456
  if (!entityName || !this.service.entities[entityName]) {
382
- throw new Error(`No entity defined for ${tableName}`);
457
+ throw new MastraError({
458
+ id: 'STORAGE_DYNAMODB_STORE_LOAD_INVALID_ARGS',
459
+ domain: ErrorDomain.STORAGE,
460
+ category: ErrorCategory.USER,
461
+ text: 'No entity defined for tableName',
462
+ details: { tableName },
463
+ });
383
464
  }
384
465
 
385
466
  try {
@@ -404,8 +485,15 @@ export class DynamoDBStore extends MastraStorage {
404
485
 
405
486
  return data as R;
406
487
  } catch (error) {
407
- this.logger.error('Failed to load record', { tableName, keys, error });
408
- throw error;
488
+ throw new MastraError(
489
+ {
490
+ id: 'STORAGE_DYNAMODB_STORE_LOAD_FAILED',
491
+ domain: ErrorDomain.STORAGE,
492
+ category: ErrorCategory.THIRD_PARTY,
493
+ details: { tableName },
494
+ },
495
+ error,
496
+ );
409
497
  }
410
498
  }
411
499
 
@@ -430,8 +518,15 @@ export class DynamoDBStore extends MastraStorage {
430
518
  // metadata is already transformed by the entity's getter
431
519
  } as StorageThreadType;
432
520
  } catch (error) {
433
- this.logger.error('Failed to get thread by ID', { threadId, error });
434
- throw error;
521
+ throw new MastraError(
522
+ {
523
+ id: 'STORAGE_DYNAMODB_STORE_GET_THREAD_BY_ID_FAILED',
524
+ domain: ErrorDomain.STORAGE,
525
+ category: ErrorCategory.THIRD_PARTY,
526
+ details: { threadId },
527
+ },
528
+ error,
529
+ );
435
530
  }
436
531
  }
437
532
 
@@ -454,8 +549,15 @@ export class DynamoDBStore extends MastraStorage {
454
549
  // metadata is already transformed by the entity's getter
455
550
  })) as StorageThreadType[];
456
551
  } catch (error) {
457
- this.logger.error('Failed to get threads by resource ID', { resourceId, error });
458
- throw error;
552
+ throw new MastraError(
553
+ {
554
+ id: 'STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED',
555
+ domain: ErrorDomain.STORAGE,
556
+ category: ErrorCategory.THIRD_PARTY,
557
+ details: { resourceId },
558
+ },
559
+ error,
560
+ );
459
561
  }
460
562
  }
461
563
 
@@ -486,8 +588,15 @@ export class DynamoDBStore extends MastraStorage {
486
588
  metadata: thread.metadata,
487
589
  };
488
590
  } catch (error) {
489
- this.logger.error('Failed to save thread', { threadId: thread.id, error });
490
- throw error;
591
+ throw new MastraError(
592
+ {
593
+ id: 'STORAGE_DYNAMODB_STORE_SAVE_THREAD_FAILED',
594
+ domain: ErrorDomain.STORAGE,
595
+ category: ErrorCategory.THIRD_PARTY,
596
+ details: { threadId: thread.id },
597
+ },
598
+ error,
599
+ );
491
600
  }
492
601
  }
493
602
 
@@ -542,8 +651,15 @@ export class DynamoDBStore extends MastraStorage {
542
651
  updatedAt: now,
543
652
  };
544
653
  } catch (error) {
545
- this.logger.error('Failed to update thread', { threadId: id, error });
546
- throw error;
654
+ throw new MastraError(
655
+ {
656
+ id: 'STORAGE_DYNAMODB_STORE_UPDATE_THREAD_FAILED',
657
+ domain: ErrorDomain.STORAGE,
658
+ category: ErrorCategory.THIRD_PARTY,
659
+ details: { threadId: id },
660
+ },
661
+ error,
662
+ );
547
663
  }
548
664
  }
549
665
 
@@ -559,8 +675,15 @@ export class DynamoDBStore extends MastraStorage {
559
675
  // 2. Delete any vector embeddings related to this thread
560
676
  // These would be additional operations
561
677
  } catch (error) {
562
- this.logger.error('Failed to delete thread', { threadId, error });
563
- throw error;
678
+ throw new MastraError(
679
+ {
680
+ id: 'STORAGE_DYNAMODB_STORE_DELETE_THREAD_FAILED',
681
+ domain: ErrorDomain.STORAGE,
682
+ category: ErrorCategory.THIRD_PARTY,
683
+ details: { threadId },
684
+ },
685
+ error,
686
+ );
564
687
  }
565
688
  }
566
689
 
@@ -580,12 +703,13 @@ export class DynamoDBStore extends MastraStorage {
580
703
  // Provide *all* composite key components for the 'byThread' index ('entity', 'threadId')
581
704
  const query = this.service.entities.message.query.byThread({ entity: 'message', threadId });
582
705
 
706
+ const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
583
707
  // Apply the 'last' limit if provided
584
- if (selectBy?.last && typeof selectBy.last === 'number') {
708
+ if (limit !== Number.MAX_SAFE_INTEGER) {
585
709
  // Use ElectroDB's limit parameter
586
710
  // DDB GSIs are sorted in ascending order
587
711
  // Use ElectroDB's order parameter to sort in descending order to retrieve 'latest' messages
588
- const results = await query.go({ limit: selectBy.last, order: 'desc' });
712
+ const results = await query.go({ limit, order: 'desc' });
589
713
  // Use arrow function in map to preserve 'this' context for parseMessageData
590
714
  const list = new MessageList({ threadId, resourceId }).add(
591
715
  results.data.map((data: any) => this.parseMessageData(data)),
@@ -605,8 +729,15 @@ export class DynamoDBStore extends MastraStorage {
605
729
  if (format === `v2`) return list.get.all.v2();
606
730
  return list.get.all.v1();
607
731
  } catch (error) {
608
- this.logger.error('Failed to get messages', { threadId, error });
609
- throw error;
732
+ throw new MastraError(
733
+ {
734
+ id: 'STORAGE_DYNAMODB_STORE_GET_MESSAGES_FAILED',
735
+ domain: ErrorDomain.STORAGE,
736
+ category: ErrorCategory.THIRD_PARTY,
737
+ details: { threadId },
738
+ },
739
+ error,
740
+ );
610
741
  }
611
742
  }
612
743
  async saveMessages(args: { messages: MastraMessageV1[]; format?: undefined | 'v1' }): Promise<MastraMessageV1[]>;
@@ -682,8 +813,15 @@ export class DynamoDBStore extends MastraStorage {
682
813
  if (format === `v1`) return list.get.all.v1();
683
814
  return list.get.all.v2();
684
815
  } catch (error) {
685
- this.logger.error('Failed to save messages', { error });
686
- throw error;
816
+ throw new MastraError(
817
+ {
818
+ id: 'STORAGE_DYNAMODB_STORE_SAVE_MESSAGES_FAILED',
819
+ domain: ErrorDomain.STORAGE,
820
+ category: ErrorCategory.THIRD_PARTY,
821
+ details: { count: messages.length },
822
+ },
823
+ error,
824
+ );
687
825
  }
688
826
  }
689
827
 
@@ -747,8 +885,14 @@ export class DynamoDBStore extends MastraStorage {
747
885
 
748
886
  return items;
749
887
  } catch (error) {
750
- this.logger.error('Failed to get traces', { error });
751
- throw error;
888
+ throw new MastraError(
889
+ {
890
+ id: 'STORAGE_DYNAMODB_STORE_GET_TRACES_FAILED',
891
+ domain: ErrorDomain.STORAGE,
892
+ category: ErrorCategory.THIRD_PARTY,
893
+ },
894
+ error,
895
+ );
752
896
  }
753
897
  }
754
898
 
@@ -767,8 +911,15 @@ export class DynamoDBStore extends MastraStorage {
767
911
  records: recordsToSave, // Pass records with 'entity' included
768
912
  });
769
913
  } catch (error) {
770
- this.logger.error('Failed to batch insert traces', { error });
771
- throw error;
914
+ throw new MastraError(
915
+ {
916
+ id: 'STORAGE_DYNAMODB_STORE_BATCH_TRACE_INSERT_FAILED',
917
+ domain: ErrorDomain.STORAGE,
918
+ category: ErrorCategory.THIRD_PARTY,
919
+ details: { count: records.length },
920
+ },
921
+ error,
922
+ );
772
923
  }
773
924
  }
774
925
 
@@ -800,8 +951,15 @@ export class DynamoDBStore extends MastraStorage {
800
951
  // Use upsert instead of create to handle both create and update cases
801
952
  await this.service.entities.workflowSnapshot.upsert(data).go();
802
953
  } catch (error) {
803
- this.logger.error('Failed to persist workflow snapshot', { workflowName, runId, error });
804
- throw error;
954
+ throw new MastraError(
955
+ {
956
+ id: 'STORAGE_DYNAMODB_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED',
957
+ domain: ErrorDomain.STORAGE,
958
+ category: ErrorCategory.THIRD_PARTY,
959
+ details: { workflowName, runId },
960
+ },
961
+ error,
962
+ );
805
963
  }
806
964
  }
807
965
 
@@ -832,8 +990,15 @@ export class DynamoDBStore extends MastraStorage {
832
990
  // Parse the snapshot string
833
991
  return result.data.snapshot as WorkflowRunState;
834
992
  } catch (error) {
835
- this.logger.error('Failed to load workflow snapshot', { workflowName, runId, error });
836
- throw error;
993
+ throw new MastraError(
994
+ {
995
+ id: 'STORAGE_DYNAMODB_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED',
996
+ domain: ErrorDomain.STORAGE,
997
+ category: ErrorCategory.THIRD_PARTY,
998
+ details: { workflowName, runId },
999
+ },
1000
+ error,
1001
+ );
837
1002
  }
838
1003
  }
839
1004
 
@@ -923,8 +1088,15 @@ export class DynamoDBStore extends MastraStorage {
923
1088
  total,
924
1089
  };
925
1090
  } catch (error) {
926
- this.logger.error('Failed to get workflow runs', { error });
927
- throw error;
1091
+ throw new MastraError(
1092
+ {
1093
+ id: 'STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUNS_FAILED',
1094
+ domain: ErrorDomain.STORAGE,
1095
+ category: ErrorCategory.THIRD_PARTY,
1096
+ details: { workflowName: args?.workflowName || '', resourceId: args?.resourceId || '' },
1097
+ },
1098
+ error,
1099
+ );
928
1100
  }
929
1101
  }
930
1102
 
@@ -995,8 +1167,15 @@ export class DynamoDBStore extends MastraStorage {
995
1167
  resourceId: matchingRunDbItem.resourceId,
996
1168
  };
997
1169
  } catch (error) {
998
- this.logger.error('Failed to get workflow run by ID', { runId, workflowName, error });
999
- throw error;
1170
+ throw new MastraError(
1171
+ {
1172
+ id: 'STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED',
1173
+ domain: ErrorDomain.STORAGE,
1174
+ category: ErrorCategory.THIRD_PARTY,
1175
+ details: { runId, workflowName: args?.workflowName || '' },
1176
+ },
1177
+ error,
1178
+ );
1000
1179
  }
1001
1180
  }
1002
1181
 
@@ -1098,13 +1277,27 @@ export class DynamoDBStore extends MastraStorage {
1098
1277
  }
1099
1278
  });
1100
1279
  } catch (error) {
1101
- this.logger.error('Failed to get evals by agent name', { agentName, type, error });
1102
- throw error;
1280
+ throw new MastraError(
1281
+ {
1282
+ id: 'STORAGE_DYNAMODB_STORE_GET_EVALS_BY_AGENT_NAME_FAILED',
1283
+ domain: ErrorDomain.STORAGE,
1284
+ category: ErrorCategory.THIRD_PARTY,
1285
+ details: { agentName },
1286
+ },
1287
+ error,
1288
+ );
1103
1289
  }
1104
1290
  }
1105
1291
 
1106
1292
  async getTracesPaginated(_args: StorageGetTracesArg): Promise<PaginationInfo & { traces: Trace[] }> {
1107
- throw new Error('Method not implemented.');
1293
+ throw new MastraError(
1294
+ {
1295
+ id: 'STORAGE_DYNAMODB_STORE_GET_TRACES_PAGINATED_FAILED',
1296
+ domain: ErrorDomain.STORAGE,
1297
+ category: ErrorCategory.THIRD_PARTY,
1298
+ },
1299
+ new Error('Method not implemented.'),
1300
+ );
1108
1301
  }
1109
1302
 
1110
1303
  async getThreadsByResourceIdPaginated(_args: {
@@ -1112,13 +1305,27 @@ export class DynamoDBStore extends MastraStorage {
1112
1305
  page?: number;
1113
1306
  perPage?: number;
1114
1307
  }): Promise<PaginationInfo & { threads: StorageThreadType[] }> {
1115
- throw new Error('Method not implemented.');
1308
+ throw new MastraError(
1309
+ {
1310
+ id: 'STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED',
1311
+ domain: ErrorDomain.STORAGE,
1312
+ category: ErrorCategory.THIRD_PARTY,
1313
+ },
1314
+ new Error('Method not implemented.'),
1315
+ );
1116
1316
  }
1117
1317
 
1118
1318
  async getMessagesPaginated(
1119
1319
  _args: StorageGetMessagesArg,
1120
1320
  ): Promise<PaginationInfo & { messages: MastraMessageV1[] | MastraMessageV2[] }> {
1121
- throw new Error('Method not implemented.');
1321
+ throw new MastraError(
1322
+ {
1323
+ id: 'STORAGE_DYNAMODB_STORE_GET_MESSAGES_PAGINATED_FAILED',
1324
+ domain: ErrorDomain.STORAGE,
1325
+ category: ErrorCategory.THIRD_PARTY,
1326
+ },
1327
+ new Error('Method not implemented.'),
1328
+ );
1122
1329
  }
1123
1330
 
1124
1331
  /**
@@ -1131,9 +1338,14 @@ export class DynamoDBStore extends MastraStorage {
1131
1338
  this.client.destroy();
1132
1339
  this.logger.debug('DynamoDB client closed successfully for store:', { name: this.name });
1133
1340
  } catch (error) {
1134
- this.logger.error('Error closing DynamoDB client for store:', { name: this.name, error });
1135
- // Optionally re-throw or handle as appropriate for your application's error handling strategy
1136
- throw error;
1341
+ throw new MastraError(
1342
+ {
1343
+ id: 'STORAGE_DYNAMODB_STORE_CLOSE_FAILED',
1344
+ domain: ErrorDomain.STORAGE,
1345
+ category: ErrorCategory.THIRD_PARTY,
1346
+ },
1347
+ error,
1348
+ );
1137
1349
  }
1138
1350
  }
1139
1351