@aurios/mizzle 1.1.1 → 1.1.3

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.
Files changed (116) hide show
  1. package/.turbo/turbo-build.log +37 -0
  2. package/LICENSE +21 -0
  3. package/README.md +57 -0
  4. package/dist/chunk-AQVECMXP.js +1 -0
  5. package/dist/chunk-DU7UPWBW.js +1 -0
  6. package/dist/chunk-GPYZK4WY.js +1 -0
  7. package/dist/chunk-NPPZW6VT.js +1 -0
  8. package/dist/chunk-TOYV2M4M.js +1 -0
  9. package/dist/chunk-UM3YF5EC.js +1 -0
  10. package/dist/columns.d.ts +1 -0
  11. package/dist/columns.js +1 -0
  12. package/dist/db-zHIHBm1E.d.ts +815 -0
  13. package/dist/db.d.ts +3 -0
  14. package/dist/db.js +1 -0
  15. package/dist/diff.d.ts +18 -0
  16. package/dist/diff.js +1 -0
  17. package/dist/index.d.ts +42 -0
  18. package/dist/index.js +1 -0
  19. package/dist/introspection.d.ts +7 -0
  20. package/dist/introspection.js +1 -0
  21. package/dist/operators-BVreW0ky.d.ts +719 -0
  22. package/dist/snapshot.d.ts +24 -0
  23. package/dist/snapshot.js +1 -0
  24. package/dist/table.d.ts +1 -0
  25. package/dist/table.js +1 -0
  26. package/dist/transaction-RE7LXTGV.js +1 -0
  27. package/package.json +73 -24
  28. package/src/builders/base.ts +53 -56
  29. package/src/builders/batch-get.ts +63 -58
  30. package/src/builders/batch-write.ts +81 -78
  31. package/src/builders/delete.ts +46 -53
  32. package/src/builders/insert.ts +158 -150
  33. package/src/builders/query-promise.ts +26 -35
  34. package/src/builders/relational-builder.ts +214 -191
  35. package/src/builders/select.ts +250 -238
  36. package/src/builders/transaction.ts +170 -151
  37. package/src/builders/update.ts +198 -191
  38. package/src/columns/binary-set.ts +29 -38
  39. package/src/columns/binary.ts +25 -35
  40. package/src/columns/boolean.ts +25 -30
  41. package/src/columns/date.ts +57 -64
  42. package/src/columns/index.ts +15 -15
  43. package/src/columns/json.ts +39 -48
  44. package/src/columns/list.ts +26 -36
  45. package/src/columns/map.ts +26 -34
  46. package/src/columns/number-set.ts +29 -38
  47. package/src/columns/number.ts +33 -40
  48. package/src/columns/string-set.ts +38 -47
  49. package/src/columns/string.ts +37 -49
  50. package/src/columns/uuid.ts +26 -33
  51. package/src/core/client.ts +9 -9
  52. package/src/core/column-builder.ts +194 -220
  53. package/src/core/column.ts +127 -135
  54. package/src/core/diff.ts +40 -34
  55. package/src/core/errors.ts +20 -17
  56. package/src/core/introspection.ts +62 -58
  57. package/src/core/operations.ts +17 -23
  58. package/src/core/parser.ts +82 -88
  59. package/src/core/relations.ts +165 -152
  60. package/src/core/retry.ts +52 -52
  61. package/src/core/snapshot.ts +131 -130
  62. package/src/core/strategies.ts +222 -214
  63. package/src/core/table.ts +189 -202
  64. package/src/core/validation.ts +52 -52
  65. package/src/db.ts +216 -213
  66. package/src/expressions/actions.ts +26 -26
  67. package/src/expressions/builder.ts +62 -54
  68. package/src/expressions/operators.ts +48 -48
  69. package/src/expressions/update-builder.ts +79 -75
  70. package/src/index.ts +2 -1
  71. package/src/indexes.ts +8 -8
  72. package/test/batch-resilience.test.ts +138 -0
  73. package/test/builders/delete.test.ts +100 -0
  74. package/test/builders/insert.test.ts +216 -0
  75. package/test/builders/relational-types.test.ts +55 -0
  76. package/test/builders/relational.integration.test.ts +291 -0
  77. package/test/builders/relational.test.ts +66 -0
  78. package/test/builders/select.test.ts +411 -0
  79. package/test/builders/transaction-errors.test.ts +46 -0
  80. package/test/builders/transaction-execution.test.ts +99 -0
  81. package/test/builders/transaction-proxy.test.ts +41 -0
  82. package/test/builders/update-expression.test.ts +106 -0
  83. package/test/builders/update.test.ts +179 -0
  84. package/test/core/diff.test.ts +152 -0
  85. package/test/core/expressions.test.ts +64 -0
  86. package/test/core/introspection.test.ts +47 -0
  87. package/test/core/parser.test.ts +69 -0
  88. package/test/core/snapshot-gen.test.ts +155 -0
  89. package/test/core/snapshot.test.ts +52 -0
  90. package/test/date-column.test.ts +159 -0
  91. package/test/fluent-writes.integration.test.ts +148 -0
  92. package/test/integration-retry.test.ts +77 -0
  93. package/test/integration.test.ts +105 -0
  94. package/test/item-size-error.test.ts +16 -0
  95. package/test/item-size-validation.test.ts +82 -0
  96. package/test/item-size.test.ts +47 -0
  97. package/test/iterator-pagination.integration.test.ts +132 -0
  98. package/test/jsdoc-builders.test.ts +55 -0
  99. package/test/jsdoc-schema.test.ts +107 -0
  100. package/test/json-column.test.ts +51 -0
  101. package/test/metadata.test.ts +54 -0
  102. package/test/mizzle-package.test.ts +20 -0
  103. package/test/relational-centralized.test.ts +83 -0
  104. package/test/relational-definition.test.ts +75 -0
  105. package/test/relational-init.test.ts +30 -0
  106. package/test/relational-proxy.test.ts +52 -0
  107. package/test/relations.test.ts +45 -0
  108. package/test/resilience-config.test.ts +34 -0
  109. package/test/retry-handler.test.ts +63 -0
  110. package/test/transaction.integration.test.ts +153 -0
  111. package/test/unified-select.integration.test.ts +153 -0
  112. package/test/unified-update.integration.test.ts +139 -0
  113. package/test/update.integration.test.ts +132 -0
  114. package/tsconfig.json +12 -9
  115. package/tsup.config.ts +11 -11
  116. package/vitest.config.ts +8 -0
@@ -0,0 +1,24 @@
1
+ import { P as PhysicalTable, f as Entity } from './operators-BVreW0ky.js';
2
+ import { AttributeDefinition, KeySchemaElement, GlobalSecondaryIndex, LocalSecondaryIndex } from '@aws-sdk/client-dynamodb';
3
+
4
+ interface TableSnapshot {
5
+ TableName: string;
6
+ AttributeDefinitions: AttributeDefinition[];
7
+ KeySchema: KeySchemaElement[];
8
+ GlobalSecondaryIndexes?: GlobalSecondaryIndex[];
9
+ LocalSecondaryIndexes?: LocalSecondaryIndex[];
10
+ }
11
+ interface MizzleSnapshot {
12
+ version: string;
13
+ tables: Record<string, TableSnapshot>;
14
+ }
15
+ interface SchemaCurrent {
16
+ tables: PhysicalTable[];
17
+ entities: Entity[];
18
+ }
19
+ declare function saveSnapshot(dir: string, snapshot: MizzleSnapshot): Promise<void>;
20
+ declare function loadSnapshot(dir: string): Promise<MizzleSnapshot | null>;
21
+ declare function generateSnapshot(schema: SchemaCurrent): MizzleSnapshot;
22
+ declare function getNextMigrationVersion(migrationsDir: string): Promise<string>;
23
+
24
+ export { type MizzleSnapshot, type SchemaCurrent, type TableSnapshot, generateSnapshot, getNextMigrationVersion, loadSnapshot, saveSnapshot };
@@ -0,0 +1 @@
1
+ import{a,b,c,d}from"./chunk-AQVECMXP.js";import"./chunk-GPYZK4WY.js";import"./chunk-DU7UPWBW.js";export{c as generateSnapshot,d as getNextMigrationVersion,b as loadSnapshot,a as saveSnapshot};
@@ -0,0 +1 @@
1
+ export { A as AnyTable, b as AtomicValues, f as Entity, g as EntityConfig, h as EntityWithColumns, k as InferInsertModel, l as InferModelFromColumns, m as InferSelectModel, n as InferSelectedModel, M as MapColumnName, P as PhysicalTable, q as PhysicalTableConfig, r as StrategyCallback, t as TableDefinition, u as UpdateTableConfig, V as dynamoEntity, W as dynamoTable } from './operators-BVreW0ky.js';
package/dist/table.js ADDED
@@ -0,0 +1 @@
1
+ import{a,b,c,d}from"./chunk-GPYZK4WY.js";import"./chunk-DU7UPWBW.js";export{b as Entity,a as PhysicalTable,c as dynamoEntity,d as dynamoTable};
@@ -0,0 +1 @@
1
+ import{R as a,S as b,T as c}from"./chunk-UM3YF5EC.js";import"./chunk-GPYZK4WY.js";import"./chunk-DU7UPWBW.js";export{a as ConditionCheckBuilder,c as TransactionExecutor,b as TransactionProxy};
package/package.json CHANGED
@@ -1,41 +1,90 @@
1
1
  {
2
2
  "name": "@aurios/mizzle",
3
- "version": "1.1.1",
4
- "private": false,
3
+ "version": "1.1.3",
5
4
  "description": "a drizzle-like orm for dynamoDB",
6
- "type": "module",
7
- "main": "./src/index.ts",
8
- "module": "./src/index.ts",
9
- "types": "./src/index.ts",
10
- "exports": {
11
- ".": "./src/index.ts",
12
- "./columns": "./src/columns/index.ts",
13
- "./table": "./src/core/table.ts",
14
- "./snapshot": "./src/core/snapshot.ts",
15
- "./diff": "./src/core/diff.ts",
16
- "./introspection": "./src/core/introspection.ts",
17
- "./db": "./src/db.ts"
5
+ "publishConfig": {
6
+ "access": "public",
7
+ "provenance": true
8
+ },
9
+ "keywords": [
10
+ "aws",
11
+ "database",
12
+ "dynamodb",
13
+ "mizzle",
14
+ "nosql",
15
+ "orm",
16
+ "singletable",
17
+ "ts",
18
+ "typescript"
19
+ ],
20
+ "homepage": "https://mizzle-docs.vercel.app",
21
+ "bugs": {
22
+ "url": "https://github.com/realfakenerd/mizzle/issues"
18
23
  },
24
+ "license": "MIT",
19
25
  "author": {
20
26
  "name": "Lucas",
21
27
  "url": "https://github.com/realfakenerd"
22
28
  },
23
29
  "repository": {
24
- "url": "https://github.com/realfakenerd/mizzle"
30
+ "type": "git",
31
+ "url": "https://github.com/realfakenerd/mizzle.git",
32
+ "directory": "packages/mizzle"
25
33
  },
26
- "scripts": {
27
- "check": "tsc --noEmit",
28
- "build": "tsup",
29
- "lint": "eslint \"src/**/*.ts\""
34
+ "type": "module",
35
+ "main": "./dist/index.js",
36
+ "module": "./dist/index.js",
37
+ "types": "./dist/index.d.ts",
38
+ "exports": {
39
+ ".": {
40
+ "types": "./dist/index.d.ts",
41
+ "import": "./dist/index.js",
42
+ "development": "./src/index.ts"
43
+ },
44
+ "./columns": {
45
+ "types": "./dist/columns.d.ts",
46
+ "import": "./dist/columns.js",
47
+ "development": "./src/columns/index.ts"
48
+ },
49
+ "./table": {
50
+ "types": "./dist/table.d.ts",
51
+ "import": "./dist/table.js",
52
+ "development": "./src/core/table.ts"
53
+ },
54
+ "./snapshot": {
55
+ "types": "./dist/snapshot.d.ts",
56
+ "import": "./dist/snapshot.js",
57
+ "development": "./src/core/snapshot.ts"
58
+ },
59
+ "./diff": {
60
+ "types": "./dist/diff.d.ts",
61
+ "import": "./dist/diff.js",
62
+ "development": "./src/core/diff.ts"
63
+ },
64
+ "./introspection": {
65
+ "types": "./dist/introspection.d.ts",
66
+ "import": "./dist/introspection.js",
67
+ "development": "./src/core/introspection.ts"
68
+ },
69
+ "./db": {
70
+ "types": "./dist/db.d.ts",
71
+ "import": "./dist/db.js",
72
+ "development": "./src/db.ts"
73
+ }
30
74
  },
31
75
  "dependencies": {
32
76
  "@aws-sdk/client-dynamodb": "3.962.0",
33
77
  "@aws-sdk/lib-dynamodb": "3.962.0"
34
78
  },
35
79
  "devDependencies": {
36
- "@mizzle/eslint-config": "workspace:*",
37
- "@mizzle/shared": "workspace:*",
38
- "@mizzle/tsconfig": "workspace:*",
39
- "tsup": "^8.5.1"
80
+ "tsup": "^8.5.1",
81
+ "@repo/shared": "0.0.3",
82
+ "@repo/vitest-config": "0.0.0",
83
+ "@repo/typescript-config": "0.0.0"
84
+ },
85
+ "scripts": {
86
+ "check": "tsc --noEmit",
87
+ "build": "tsup",
88
+ "test": "vitest run"
40
89
  }
41
- }
90
+ }
@@ -1,71 +1,68 @@
1
1
  import { type IMizzleClient } from "../core/client";
2
2
  import { Entity } from "../core/table";
3
3
  import { QueryPromise } from "./query-promise";
4
- import { resolveTableName, mapToLogical } from "@mizzle/shared";
4
+ import { resolveTableName, mapToLogical } from "@repo/shared";
5
5
  import { resolveStrategies, type StrategyResolution } from "../core/strategies";
6
6
  import { type Expression } from "../expressions/operators";
7
- import { ENTITY_SYMBOLS } from "@mizzle/shared";
7
+ import { ENTITY_SYMBOLS } from "@repo/shared";
8
8
 
9
- export abstract class BaseBuilder<
10
- TEntity extends Entity,
11
- TResult,
12
- > extends QueryPromise<TResult> {
13
- constructor(
14
- protected readonly entity: TEntity,
15
- protected readonly client: IMizzleClient,
16
- ) {
17
- super();
18
- }
9
+ export abstract class BaseBuilder<TEntity extends Entity, TResult> extends QueryPromise<TResult> {
10
+ constructor(
11
+ protected readonly entity: TEntity,
12
+ protected readonly client: IMizzleClient,
13
+ ) {
14
+ super();
15
+ }
19
16
 
20
- public get tableName(): string {
21
- return resolveTableName(this.entity as unknown as Entity);
22
- }
17
+ public get tableName(): string {
18
+ return resolveTableName(this.entity as any);
19
+ }
23
20
 
24
- protected get physicalTable() {
25
- return this.entity[ENTITY_SYMBOLS.PHYSICAL_TABLE];
26
- }
21
+ protected get physicalTable() {
22
+ return this.entity[ENTITY_SYMBOLS.PHYSICAL_TABLE];
23
+ }
27
24
 
28
- protected resolveKeys(
29
- whereClause?: Expression,
30
- providedValues?: Record<string, unknown>,
31
- indexName?: string,
32
- ): StrategyResolution {
33
- return resolveStrategies(this.entity, whereClause, providedValues, indexName);
34
- }
25
+ protected resolveKeys(
26
+ whereClause?: Expression,
27
+ providedValues?: Record<string, unknown>,
28
+ indexName?: string,
29
+ ): StrategyResolution {
30
+ return resolveStrategies(this.entity, whereClause, providedValues, indexName);
31
+ }
35
32
 
36
- protected createExpressionContext(prefix = "") {
37
- const expressionAttributeNames: Record<string, string> = {};
38
- const expressionAttributeValues: Record<string, unknown> = {};
39
- let nameCount = 0;
40
- let valueCount = 0;
33
+ protected createExpressionContext(prefix = "") {
34
+ const expressionAttributeNames: Record<string, string> = {};
35
+ const expressionAttributeValues: Record<string, unknown> = {};
36
+ let nameCount = 0;
37
+ let valueCount = 0;
41
38
 
42
- const addName = (name: string) => {
43
- const segments = name.split(".");
44
- const placeholders = segments.map(segment => {
45
- // Check if we already mapped this name segment to avoid redundancy?
46
- // Actually, simple counter is fine for now and safer against collisions.
47
- const placeholder = `#${prefix}n${nameCount++}`;
48
- expressionAttributeNames[placeholder] = segment;
49
- return placeholder;
50
- });
51
- return placeholders.join(".");
52
- };
39
+ const addName = (name: string) => {
40
+ const segments = name.split(".");
41
+ const placeholders = segments.map((segment) => {
42
+ // Check if we already mapped this name segment to avoid redundancy?
43
+ // Actually, simple counter is fine for now and safer against collisions.
44
+ const placeholder = `#${prefix}n${nameCount++}`;
45
+ expressionAttributeNames[placeholder] = segment;
46
+ return placeholder;
47
+ });
48
+ return placeholders.join(".");
49
+ };
53
50
 
54
- const addValue = (value: unknown) => {
55
- const placeholder = `:${prefix}v${valueCount++}`;
56
- expressionAttributeValues[placeholder] = value;
57
- return placeholder;
58
- };
51
+ const addValue = (value: unknown) => {
52
+ const placeholder = `:${prefix}v${valueCount++}`;
53
+ expressionAttributeValues[placeholder] = value;
54
+ return placeholder;
55
+ };
59
56
 
60
- return {
61
- expressionAttributeNames,
62
- expressionAttributeValues,
63
- addName,
64
- addValue,
65
- };
66
- }
57
+ return {
58
+ expressionAttributeNames,
59
+ expressionAttributeValues,
60
+ addName,
61
+ addValue,
62
+ };
63
+ }
67
64
 
68
- protected mapToLogical(item: Record<string, unknown>): Record<string, unknown> {
69
- return mapToLogical(this.entity, item);
70
- }
65
+ protected mapToLogical(item: Record<string, unknown>): Record<string, unknown> {
66
+ return mapToLogical(this.entity as any, item);
67
+ }
71
68
  }
@@ -1,76 +1,81 @@
1
1
  import { BatchGetCommand } from "@aws-sdk/lib-dynamodb";
2
- import { ENTITY_SYMBOLS } from "@mizzle/shared";
2
+ import { ENTITY_SYMBOLS } from "@repo/shared";
3
3
  import { Entity, type InferSelectModel } from "../core/table";
4
4
  import { BaseBuilder } from "./base";
5
5
  import type { IMizzleClient } from "../core/client";
6
6
 
7
7
  export class BatchGetBuilder {
8
- constructor(private client: IMizzleClient) {}
8
+ constructor(private client: IMizzleClient) {}
9
9
 
10
- items<TEntity extends Entity>(entity: TEntity, keys: Partial<InferSelectModel<TEntity>>[]) {
11
- return new BatchGetBase(entity, this.client, keys);
12
- }
10
+ items<TEntity extends Entity>(entity: TEntity, keys: Partial<InferSelectModel<TEntity>>[]) {
11
+ return new BatchGetBase(entity, this.client, keys);
12
+ }
13
13
  }
14
14
 
15
15
  export interface BatchGetResult<T> {
16
- succeeded: T[];
17
- failed: Partial<T>[];
16
+ succeeded: T[];
17
+ failed: Partial<T>[];
18
18
  }
19
19
 
20
20
  export class BatchGetBase<
21
- TEntity extends Entity,
22
- TResult = InferSelectModel<TEntity>,
21
+ TEntity extends Entity,
22
+ TResult = InferSelectModel<TEntity>,
23
23
  > extends BaseBuilder<TEntity, BatchGetResult<TResult>> {
24
- static readonly [ENTITY_SYMBOLS.ENTITY_KIND]: string = "BatchGetBase";
25
-
26
- constructor(
27
- entity: TEntity,
28
- client: IMizzleClient,
29
- private keysData: Partial<InferSelectModel<TEntity>>[],
30
- ) {
31
- super(entity, client);
24
+ static readonly [ENTITY_SYMBOLS.ENTITY_KIND]: string = "BatchGetBase";
25
+
26
+ constructor(
27
+ entity: TEntity,
28
+ client: IMizzleClient,
29
+ private keysData: Partial<InferSelectModel<TEntity>>[],
30
+ ) {
31
+ super(entity, client);
32
+ }
33
+
34
+ public override async execute(): Promise<BatchGetResult<TResult>> {
35
+ const succeeded: TResult[] = [];
36
+ const failed: Partial<TResult>[] = [];
37
+
38
+ // Group keys by resolved DynamoDB keys
39
+ let currentKeys = this.keysData.map(
40
+ (k) => this.resolveKeys(undefined, k as Record<string, unknown>).keys,
41
+ );
42
+
43
+ let attempts = 0;
44
+ const maxBatchAttempts = 5; // Internal limit for unprocessed retries
45
+
46
+ while (currentKeys.length > 0 && attempts < maxBatchAttempts) {
47
+ attempts++;
48
+
49
+ const command = new BatchGetCommand({
50
+ RequestItems: {
51
+ [this.tableName]: {
52
+ Keys: currentKeys,
53
+ },
54
+ },
55
+ });
56
+
57
+ const response = (await this.client.send(command)) as {
58
+ Responses?: Record<string, unknown[]>;
59
+ UnprocessedKeys?: Record<string, { Keys?: Record<string, unknown>[] }>;
60
+ };
61
+
62
+ if (response.Responses?.[this.tableName]) {
63
+ succeeded.push(...(response.Responses[this.tableName] as TResult[]));
64
+ }
65
+
66
+ const unprocessed = response.UnprocessedKeys?.[this.tableName]?.Keys;
67
+
68
+ if (unprocessed && unprocessed.length > 0) {
69
+ currentKeys = unprocessed;
70
+ } else {
71
+ currentKeys = [];
72
+ }
32
73
  }
33
74
 
34
- public override async execute(): Promise<BatchGetResult<TResult>> {
35
- const succeeded: TResult[] = [];
36
- const failed: Partial<TResult>[] = [];
37
-
38
- // Group keys by resolved DynamoDB keys
39
- let currentKeys = this.keysData.map(k => this.resolveKeys(undefined, k as Record<string, unknown>).keys);
40
-
41
- let attempts = 0;
42
- const maxBatchAttempts = 5; // Internal limit for unprocessed retries
43
-
44
- while (currentKeys.length > 0 && attempts < maxBatchAttempts) {
45
- attempts++;
46
-
47
- const command = new BatchGetCommand({
48
- RequestItems: {
49
- [this.tableName]: {
50
- Keys: currentKeys
51
- }
52
- }
53
- });
54
-
55
- const response = await this.client.send(command) as { Responses?: Record<string, unknown[]>, UnprocessedKeys?: Record<string, { Keys?: Record<string, unknown>[] }> };
56
-
57
- if (response.Responses?.[this.tableName]) {
58
- succeeded.push(...(response.Responses[this.tableName] as TResult[]));
59
- }
60
-
61
- const unprocessed = response.UnprocessedKeys?.[this.tableName]?.Keys;
62
-
63
- if (unprocessed && unprocessed.length > 0) {
64
- currentKeys = unprocessed;
65
- } else {
66
- currentKeys = [];
67
- }
68
- }
69
-
70
- if (currentKeys.length > 0) {
71
- failed.push(...(currentKeys as Partial<TResult>[]));
72
- }
73
-
74
- return { succeeded, failed };
75
+ if (currentKeys.length > 0) {
76
+ failed.push(...(currentKeys as Partial<TResult>[]));
75
77
  }
78
+
79
+ return { succeeded, failed };
80
+ }
76
81
  }
@@ -1,99 +1,102 @@
1
1
  import { BatchWriteCommand } from "@aws-sdk/lib-dynamodb";
2
- import { ENTITY_SYMBOLS } from "@mizzle/shared";
2
+ import { ENTITY_SYMBOLS } from "@repo/shared";
3
3
  import { Entity, type InferInsertModel } from "../core/table";
4
4
  import { BaseBuilder } from "./base";
5
5
  import type { IMizzleClient } from "../core/client";
6
6
  import { calculateItemSize } from "../core/validation";
7
7
  import { ItemSizeExceededError } from "../core/errors";
8
8
 
9
- export type BatchWriteOperation<TEntity extends Entity> =
10
- | { type: "put", item: InferInsertModel<TEntity> }
11
- | { type: "delete", keys: Partial<InferInsertModel<TEntity>> };
9
+ export type BatchWriteOperation<TEntity extends Entity> =
10
+ | { type: "put"; item: InferInsertModel<TEntity> }
11
+ | { type: "delete"; keys: Partial<InferInsertModel<TEntity>> };
12
12
 
13
13
  export interface BatchWriteResult<_T> {
14
- succeededCount: number;
15
- failed: unknown[]; // Operations that failed after all retries
14
+ succeededCount: number;
15
+ failed: unknown[]; // Operations that failed after all retries
16
16
  }
17
17
 
18
18
  export class BatchWriteBuilder {
19
- constructor(private client: IMizzleClient) {}
19
+ constructor(private client: IMizzleClient) {}
20
20
 
21
- operations<TEntity extends Entity>(entity: TEntity, ops: BatchWriteOperation<TEntity>[]) {
22
- return new BatchWriteBase(entity, this.client, ops);
23
- }
21
+ operations<TEntity extends Entity>(entity: TEntity, ops: BatchWriteOperation<TEntity>[]) {
22
+ return new BatchWriteBase(entity, this.client, ops);
23
+ }
24
24
  }
25
25
 
26
- export class BatchWriteBase<
27
- TEntity extends Entity,
28
- > extends BaseBuilder<TEntity, BatchWriteResult<InferInsertModel<TEntity>>> {
29
- static readonly [ENTITY_SYMBOLS.ENTITY_KIND]: string = "BatchWriteBase";
30
-
31
- constructor(
32
- entity: TEntity,
33
- client: IMizzleClient,
34
- private ops: BatchWriteOperation<TEntity>[],
35
- ) {
36
- super(entity, client);
37
- }
26
+ export class BatchWriteBase<TEntity extends Entity> extends BaseBuilder<
27
+ TEntity,
28
+ BatchWriteResult<InferInsertModel<TEntity>>
29
+ > {
30
+ static readonly [ENTITY_SYMBOLS.ENTITY_KIND]: string = "BatchWriteBase";
38
31
 
39
- public override async execute(): Promise<BatchWriteResult<InferInsertModel<TEntity>>> {
40
- let succeededCount = 0;
41
- let failed: unknown[] = [];
42
-
43
- const requests = this.ops.map(op => {
44
- if (op.type === "put") {
45
- const item = op.item as Record<string, unknown>;
46
-
47
- // Size validation
48
- const size = calculateItemSize(item);
49
- if (size > 400 * 1024) {
50
- throw new ItemSizeExceededError(`Item in batch exceeds the 400KB limit.`);
51
- }
52
-
53
- return {
54
- PutRequest: {
55
- Item: item
56
- }
57
- };
58
- } else {
59
- return {
60
- DeleteRequest: {
61
- Key: op.keys as Record<string, unknown>
62
- }
63
- };
64
- }
65
- });
66
-
67
- let currentRequests: unknown[] = [...requests];
68
- let attempts = 0;
69
- const maxBatchAttempts = 5;
70
-
71
- while (currentRequests.length > 0 && attempts < maxBatchAttempts) {
72
- attempts++;
73
-
74
- const command = new BatchWriteCommand({
75
- RequestItems: {
76
- [this.tableName]: currentRequests as any[]
77
- }
78
- });
79
-
80
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
- const response = await this.client.send(command) as { UnprocessedItems?: Record<string, any[]> };
82
-
83
- const unprocessed = response.UnprocessedItems?.[this.tableName] || [];
84
- succeededCount += (currentRequests.length - unprocessed.length);
85
-
86
- if (unprocessed.length > 0) {
87
- currentRequests = unprocessed;
88
- } else {
89
- currentRequests = [];
90
- }
91
- }
32
+ constructor(
33
+ entity: TEntity,
34
+ client: IMizzleClient,
35
+ private ops: BatchWriteOperation<TEntity>[],
36
+ ) {
37
+ super(entity, client);
38
+ }
39
+
40
+ public override async execute(): Promise<BatchWriteResult<InferInsertModel<TEntity>>> {
41
+ let succeededCount = 0;
42
+ let failed: unknown[] = [];
92
43
 
93
- if (currentRequests.length > 0) {
94
- failed = currentRequests;
44
+ const requests = this.ops.map((op) => {
45
+ if (op.type === "put") {
46
+ const item = op.item as Record<string, unknown>;
47
+
48
+ // Size validation
49
+ const size = calculateItemSize(item);
50
+ if (size > 400 * 1024) {
51
+ throw new ItemSizeExceededError(`Item in batch exceeds the 400KB limit.`);
95
52
  }
96
53
 
97
- return { succeededCount, failed };
54
+ return {
55
+ PutRequest: {
56
+ Item: item,
57
+ },
58
+ };
59
+ } else {
60
+ return {
61
+ DeleteRequest: {
62
+ Key: op.keys as Record<string, unknown>,
63
+ },
64
+ };
65
+ }
66
+ });
67
+
68
+ let currentRequests: unknown[] = [...requests];
69
+ let attempts = 0;
70
+ const maxBatchAttempts = 5;
71
+
72
+ while (currentRequests.length > 0 && attempts < maxBatchAttempts) {
73
+ attempts++;
74
+
75
+ const command = new BatchWriteCommand({
76
+ RequestItems: {
77
+ [this.tableName]: currentRequests as Record<string, unknown>[],
78
+ },
79
+ });
80
+
81
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
+ const response = (await this.client.send(command)) as {
83
+ UnprocessedItems?: Record<string, any[]>;
84
+ };
85
+
86
+ const unprocessed = response.UnprocessedItems?.[this.tableName] || [];
87
+ succeededCount += currentRequests.length - unprocessed.length;
88
+
89
+ if (unprocessed.length > 0) {
90
+ currentRequests = unprocessed;
91
+ } else {
92
+ currentRequests = [];
93
+ }
98
94
  }
95
+
96
+ if (currentRequests.length > 0) {
97
+ failed = currentRequests;
98
+ }
99
+
100
+ return { succeededCount, failed };
101
+ }
99
102
  }