dyno-table 1.0.0-alpha.1 → 1.0.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 +751 -172
- package/dist/builder-types-C_PDZhnP.d.ts +118 -0
- package/dist/builder-types-DtwbqMeF.d.cts +118 -0
- package/dist/builders/condition-check-builder.cjs +394 -0
- package/dist/builders/condition-check-builder.cjs.map +1 -0
- package/dist/builders/condition-check-builder.d.cts +157 -0
- package/dist/builders/condition-check-builder.d.ts +157 -0
- package/dist/builders/condition-check-builder.js +392 -0
- package/dist/builders/condition-check-builder.js.map +1 -0
- package/dist/builders/delete-builder.cjs +405 -0
- package/dist/builders/delete-builder.cjs.map +1 -0
- package/dist/builders/delete-builder.d.cts +166 -0
- package/dist/builders/delete-builder.d.ts +166 -0
- package/dist/builders/delete-builder.js +403 -0
- package/dist/builders/delete-builder.js.map +1 -0
- package/dist/builders/paginator.cjs +199 -0
- package/dist/builders/paginator.cjs.map +1 -0
- package/dist/builders/paginator.d.cts +179 -0
- package/dist/builders/paginator.d.ts +179 -0
- package/dist/builders/paginator.js +197 -0
- package/dist/builders/paginator.js.map +1 -0
- package/dist/builders/put-builder.cjs +476 -0
- package/dist/builders/put-builder.cjs.map +1 -0
- package/dist/builders/put-builder.d.cts +274 -0
- package/dist/builders/put-builder.d.ts +274 -0
- package/dist/builders/put-builder.js +474 -0
- package/dist/builders/put-builder.js.map +1 -0
- package/dist/builders/query-builder.cjs +674 -0
- package/dist/builders/query-builder.cjs.map +1 -0
- package/dist/builders/query-builder.d.cts +6 -0
- package/dist/builders/query-builder.d.ts +6 -0
- package/dist/builders/query-builder.js +672 -0
- package/dist/builders/query-builder.js.map +1 -0
- package/dist/builders/transaction-builder.cjs +894 -0
- package/dist/builders/transaction-builder.cjs.map +1 -0
- package/dist/builders/transaction-builder.d.cts +511 -0
- package/dist/builders/transaction-builder.d.ts +511 -0
- package/dist/builders/transaction-builder.js +892 -0
- package/dist/builders/transaction-builder.js.map +1 -0
- package/dist/builders/update-builder.cjs +627 -0
- package/dist/builders/update-builder.cjs.map +1 -0
- package/dist/builders/update-builder.d.cts +365 -0
- package/dist/builders/update-builder.d.ts +365 -0
- package/dist/builders/update-builder.js +625 -0
- package/dist/builders/update-builder.js.map +1 -0
- package/dist/conditions--ld9a78i.d.ts +331 -0
- package/dist/conditions-ChhQWd6z.d.cts +331 -0
- package/dist/conditions.cjs +59 -0
- package/dist/conditions.cjs.map +1 -0
- package/dist/conditions.d.cts +3 -0
- package/dist/conditions.d.ts +3 -0
- package/dist/conditions.js +43 -0
- package/dist/conditions.js.map +1 -0
- package/dist/entity.cjs +228 -0
- package/dist/entity.cjs.map +1 -0
- package/dist/entity.d.cts +149 -0
- package/dist/entity.d.ts +149 -0
- package/dist/entity.js +224 -0
- package/dist/entity.js.map +1 -0
- package/dist/query-builder-Csror9Iu.d.ts +507 -0
- package/dist/query-builder-D2FM9rsu.d.cts +507 -0
- package/dist/standard-schema.cjs +4 -0
- package/dist/standard-schema.cjs.map +1 -0
- package/dist/standard-schema.d.cts +57 -0
- package/dist/standard-schema.d.ts +57 -0
- package/dist/standard-schema.js +3 -0
- package/dist/standard-schema.js.map +1 -0
- package/dist/table-BEhBPy2G.d.cts +364 -0
- package/dist/table-BW3cmUqr.d.ts +364 -0
- package/dist/{index.js → table.cjs} +88 -127
- package/dist/table.cjs.map +1 -0
- package/dist/table.d.cts +12 -0
- package/dist/table.d.ts +12 -0
- package/dist/{index.cjs → table.js} +86 -176
- package/dist/table.js.map +1 -0
- package/dist/types.cjs +4 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +22 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/partition-key-template.cjs +19 -0
- package/dist/utils/partition-key-template.cjs.map +1 -0
- package/dist/utils/partition-key-template.d.cts +32 -0
- package/dist/utils/partition-key-template.d.ts +32 -0
- package/dist/utils/partition-key-template.js +17 -0
- package/dist/utils/partition-key-template.js.map +1 -0
- package/dist/utils/sort-key-template.cjs +19 -0
- package/dist/utils/sort-key-template.cjs.map +1 -0
- package/dist/utils/sort-key-template.d.cts +35 -0
- package/dist/utils/sort-key-template.d.ts +35 -0
- package/dist/utils/sort-key-template.js +17 -0
- package/dist/utils/sort-key-template.js.map +1 -0
- package/package.json +77 -7
- package/dist/index.d.cts +0 -2971
- package/dist/index.d.ts +0 -2971
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// src/builders/paginator.ts
|
|
2
|
+
var Paginator = class {
|
|
3
|
+
queryBuilder;
|
|
4
|
+
pageSize;
|
|
5
|
+
currentPage = 0;
|
|
6
|
+
lastEvaluatedKey;
|
|
7
|
+
hasMorePages = true;
|
|
8
|
+
totalItemsRetrieved = 0;
|
|
9
|
+
overallLimit;
|
|
10
|
+
constructor(queryBuilder, pageSize) {
|
|
11
|
+
this.queryBuilder = queryBuilder;
|
|
12
|
+
this.pageSize = pageSize;
|
|
13
|
+
this.overallLimit = queryBuilder.getLimit();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Gets the current page number (1-indexed).
|
|
17
|
+
* Use this method when you need to:
|
|
18
|
+
* - Track progress through dinosaur lists
|
|
19
|
+
* - Display habitat inspection status
|
|
20
|
+
* - Monitor security sweep progress
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const paginator = new QueryBuilder(executor, eq('species', 'Tyrannosaurus'))
|
|
25
|
+
* .paginate(5);
|
|
26
|
+
*
|
|
27
|
+
* await paginator.getNextPage();
|
|
28
|
+
* console.log(`Reviewing T-Rex group ${paginator.getCurrentPage()}`);
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @returns The current page number, starting from 1
|
|
32
|
+
*/
|
|
33
|
+
getCurrentPage() {
|
|
34
|
+
return this.currentPage;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Checks if there are more pages of dinosaurs or habitats to process.
|
|
38
|
+
* Use this method when you need to:
|
|
39
|
+
* - Check for more dinosaurs to review
|
|
40
|
+
* - Continue habitat inspections
|
|
41
|
+
* - Process security incidents
|
|
42
|
+
* - Complete feeding schedules
|
|
43
|
+
*
|
|
44
|
+
* This method takes into account both:
|
|
45
|
+
* - DynamoDB's lastEvaluatedKey mechanism
|
|
46
|
+
* - Any overall limit set on the query
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* // Process all security incidents
|
|
51
|
+
* const paginator = new QueryBuilder(executor, eq('type', 'SECURITY_BREACH'))
|
|
52
|
+
* .sortDescending()
|
|
53
|
+
* .paginate(10);
|
|
54
|
+
*
|
|
55
|
+
* while (paginator.hasNextPage()) {
|
|
56
|
+
* const page = await paginator.getNextPage();
|
|
57
|
+
* for (const incident of page.items) {
|
|
58
|
+
* await processSecurityBreach(incident);
|
|
59
|
+
* }
|
|
60
|
+
* console.log(`Processed incidents page ${page.page}`);
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @returns true if there are more pages available, false otherwise
|
|
65
|
+
*/
|
|
66
|
+
hasNextPage() {
|
|
67
|
+
if (this.overallLimit !== void 0 && this.totalItemsRetrieved >= this.overallLimit) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return this.hasMorePages;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Retrieves the next page of dinosaurs or habitats from DynamoDB.
|
|
74
|
+
* Use this method when you need to:
|
|
75
|
+
* - Process dinosaur groups systematically
|
|
76
|
+
* - Review habitat inspections in batches
|
|
77
|
+
* - Monitor security incidents in sequence
|
|
78
|
+
* - Schedule feeding rotations
|
|
79
|
+
*
|
|
80
|
+
* This method handles:
|
|
81
|
+
* - Automatic continuation between groups
|
|
82
|
+
* - Respect for park capacity limits
|
|
83
|
+
* - Group size adjustments for safety
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* const paginator = new QueryBuilder(executor, eq('species', 'Velociraptor'))
|
|
88
|
+
* .filter(op => op.eq('status', 'ACTIVE'))
|
|
89
|
+
* .paginate(5);
|
|
90
|
+
*
|
|
91
|
+
* // Check first raptor group
|
|
92
|
+
* const page1 = await paginator.getNextPage();
|
|
93
|
+
* console.log(`Found ${page1.items.length} active raptors`);
|
|
94
|
+
*
|
|
95
|
+
* // Continue inspection if more groups exist
|
|
96
|
+
* if (page1.hasNextPage) {
|
|
97
|
+
* const page2 = await paginator.getNextPage();
|
|
98
|
+
* console.log(`Inspecting raptor group ${page2.page}`);
|
|
99
|
+
*
|
|
100
|
+
* for (const raptor of page2.items) {
|
|
101
|
+
* await performHealthCheck(raptor);
|
|
102
|
+
* }
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @returns A promise that resolves to a PaginationResult containing:
|
|
107
|
+
* - items: The dinosaurs/habitats for this page
|
|
108
|
+
* - hasNextPage: Whether more groups exist
|
|
109
|
+
* - page: The current group number
|
|
110
|
+
* - lastEvaluatedKey: DynamoDB's continuation token
|
|
111
|
+
*/
|
|
112
|
+
async getNextPage() {
|
|
113
|
+
if (!this.hasNextPage()) {
|
|
114
|
+
return {
|
|
115
|
+
items: [],
|
|
116
|
+
hasNextPage: false,
|
|
117
|
+
page: this.currentPage
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
let effectivePageSize = this.pageSize;
|
|
121
|
+
if (this.overallLimit !== void 0) {
|
|
122
|
+
const remainingItems = this.overallLimit - this.totalItemsRetrieved;
|
|
123
|
+
if (remainingItems <= 0) {
|
|
124
|
+
return {
|
|
125
|
+
items: [],
|
|
126
|
+
hasNextPage: false,
|
|
127
|
+
page: this.currentPage
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
effectivePageSize = Math.min(effectivePageSize, remainingItems);
|
|
131
|
+
}
|
|
132
|
+
const query = this.queryBuilder.clone().limit(effectivePageSize);
|
|
133
|
+
if (this.lastEvaluatedKey) {
|
|
134
|
+
query.startFrom(this.lastEvaluatedKey);
|
|
135
|
+
}
|
|
136
|
+
const result = await query.execute();
|
|
137
|
+
this.currentPage += 1;
|
|
138
|
+
this.lastEvaluatedKey = result.lastEvaluatedKey;
|
|
139
|
+
this.totalItemsRetrieved += result.items.length;
|
|
140
|
+
this.hasMorePages = !!result.lastEvaluatedKey && (this.overallLimit === void 0 || this.totalItemsRetrieved < this.overallLimit);
|
|
141
|
+
return {
|
|
142
|
+
items: result.items,
|
|
143
|
+
lastEvaluatedKey: result.lastEvaluatedKey,
|
|
144
|
+
hasNextPage: this.hasNextPage(),
|
|
145
|
+
page: this.currentPage
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Gets all remaining dinosaurs or habitats and combines them into a single array.
|
|
150
|
+
* Use this method when you need to:
|
|
151
|
+
* - Generate complete park inventory
|
|
152
|
+
* - Perform full security audit
|
|
153
|
+
* - Create comprehensive feeding schedule
|
|
154
|
+
* - Run park-wide health checks
|
|
155
|
+
*
|
|
156
|
+
* Note: Use with caution! This method:
|
|
157
|
+
* - Could overwhelm systems with large dinosaur populations
|
|
158
|
+
* - Makes multiple database requests
|
|
159
|
+
* - May cause system strain during peak hours
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* // Get complete carnivore inventory
|
|
164
|
+
* const paginator = new QueryBuilder(executor, eq('diet', 'CARNIVORE'))
|
|
165
|
+
* .filter(op => op.eq('status', 'ACTIVE'))
|
|
166
|
+
* .paginate(10);
|
|
167
|
+
*
|
|
168
|
+
* try {
|
|
169
|
+
* const allCarnivores = await paginator.getAllPages();
|
|
170
|
+
* console.log(`Park contains ${allCarnivores.length} active carnivores`);
|
|
171
|
+
*
|
|
172
|
+
* // Calculate total threat level
|
|
173
|
+
* const totalThreat = allCarnivores.reduce(
|
|
174
|
+
* (sum, dino) => sum + dino.stats.threatLevel,
|
|
175
|
+
* 0
|
|
176
|
+
* );
|
|
177
|
+
* console.log(`Total threat level: ${totalThreat}`);
|
|
178
|
+
* } catch (error) {
|
|
179
|
+
* console.error('Failed to complete carnivore census:', error);
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @returns A promise that resolves to an array containing all remaining items
|
|
184
|
+
*/
|
|
185
|
+
async getAllPages() {
|
|
186
|
+
const allItems = [];
|
|
187
|
+
while (this.hasNextPage()) {
|
|
188
|
+
const result = await this.getNextPage();
|
|
189
|
+
allItems.push(...result.items);
|
|
190
|
+
}
|
|
191
|
+
return allItems;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export { Paginator };
|
|
196
|
+
//# sourceMappingURL=paginator.js.map
|
|
197
|
+
//# sourceMappingURL=paginator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/builders/paginator.ts"],"names":[],"mappings":"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","file":"paginator.js","sourcesContent":["import type { DynamoItem, TableConfig } from \"../types\";\nimport type { PaginationResult, QueryBuilderInterface } from \"./builder-types\";\n\n/**\n * A utility class for handling DynamoDB pagination.\n * Use this class when you need to:\n * - Browse large collections of dinosaurs\n * - Review extensive security logs\n * - Analyze habitat inspection history\n * - Process feeding schedules\n *\n * The paginator maintains internal state and automatically handles:\n * - Page boundaries\n * - Result set limits\n * - Continuation tokens\n *\n * @example\n * ```typescript\n * // List all velociraptors with pagination\n * const paginator = new QueryBuilder(executor, eq('species', 'Velociraptor'))\n * .filter(op => op.eq('status', 'ACTIVE'))\n * .paginate(10);\n *\n * // Process each page of dinosaurs\n * while (paginator.hasNextPage()) {\n * const page = await paginator.getNextPage();\n * console.log(`Processing page ${page.page} of velociraptors`);\n *\n * for (const raptor of page.items) {\n * console.log(`- ${raptor.id}: Health=${raptor.stats.health}`);\n * }\n * }\n * ```\n *\n * @typeParam T - The type of items being paginated\n * @typeParam TConfig - The table configuration type\n */\nexport class Paginator<T extends DynamoItem, TConfig extends TableConfig = TableConfig> {\n private queryBuilder: QueryBuilderInterface<T, TConfig>;\n private readonly pageSize: number;\n private currentPage = 0;\n private lastEvaluatedKey?: DynamoItem;\n private hasMorePages = true;\n private totalItemsRetrieved = 0;\n private readonly overallLimit?: number;\n\n constructor(queryBuilder: QueryBuilderInterface<T, TConfig>, pageSize: number) {\n this.queryBuilder = queryBuilder;\n this.pageSize = pageSize;\n // Store the overall limit from the query builder if it exists\n this.overallLimit = queryBuilder.getLimit();\n }\n\n /**\n * Gets the current page number (1-indexed).\n * Use this method when you need to:\n * - Track progress through dinosaur lists\n * - Display habitat inspection status\n * - Monitor security sweep progress\n *\n * @example\n * ```ts\n * const paginator = new QueryBuilder(executor, eq('species', 'Tyrannosaurus'))\n * .paginate(5);\n *\n * await paginator.getNextPage();\n * console.log(`Reviewing T-Rex group ${paginator.getCurrentPage()}`);\n * ```\n *\n * @returns The current page number, starting from 1\n */\n public getCurrentPage(): number {\n return this.currentPage;\n }\n\n /**\n * Checks if there are more pages of dinosaurs or habitats to process.\n * Use this method when you need to:\n * - Check for more dinosaurs to review\n * - Continue habitat inspections\n * - Process security incidents\n * - Complete feeding schedules\n *\n * This method takes into account both:\n * - DynamoDB's lastEvaluatedKey mechanism\n * - Any overall limit set on the query\n *\n * @example\n * ```ts\n * // Process all security incidents\n * const paginator = new QueryBuilder(executor, eq('type', 'SECURITY_BREACH'))\n * .sortDescending()\n * .paginate(10);\n *\n * while (paginator.hasNextPage()) {\n * const page = await paginator.getNextPage();\n * for (const incident of page.items) {\n * await processSecurityBreach(incident);\n * }\n * console.log(`Processed incidents page ${page.page}`);\n * }\n * ```\n *\n * @returns true if there are more pages available, false otherwise\n */\n public hasNextPage(): boolean {\n // If we have an overall limit and we've already retrieved that many items, there are no more pages\n if (this.overallLimit !== undefined && this.totalItemsRetrieved >= this.overallLimit) {\n return false;\n }\n return this.hasMorePages;\n }\n\n /**\n * Retrieves the next page of dinosaurs or habitats from DynamoDB.\n * Use this method when you need to:\n * - Process dinosaur groups systematically\n * - Review habitat inspections in batches\n * - Monitor security incidents in sequence\n * - Schedule feeding rotations\n *\n * This method handles:\n * - Automatic continuation between groups\n * - Respect for park capacity limits\n * - Group size adjustments for safety\n *\n * @example\n * ```ts\n * const paginator = new QueryBuilder(executor, eq('species', 'Velociraptor'))\n * .filter(op => op.eq('status', 'ACTIVE'))\n * .paginate(5);\n *\n * // Check first raptor group\n * const page1 = await paginator.getNextPage();\n * console.log(`Found ${page1.items.length} active raptors`);\n *\n * // Continue inspection if more groups exist\n * if (page1.hasNextPage) {\n * const page2 = await paginator.getNextPage();\n * console.log(`Inspecting raptor group ${page2.page}`);\n *\n * for (const raptor of page2.items) {\n * await performHealthCheck(raptor);\n * }\n * }\n * ```\n *\n * @returns A promise that resolves to a PaginationResult containing:\n * - items: The dinosaurs/habitats for this page\n * - hasNextPage: Whether more groups exist\n * - page: The current group number\n * - lastEvaluatedKey: DynamoDB's continuation token\n */\n public async getNextPage(): Promise<PaginationResult<T>> {\n if (!this.hasNextPage()) {\n return {\n items: [],\n hasNextPage: false,\n page: this.currentPage,\n };\n }\n\n // Calculate how many items to fetch for this page\n let effectivePageSize = this.pageSize;\n\n // If we have an overall limit, make sure we don't fetch more than what's left\n if (this.overallLimit !== undefined) {\n const remainingItems = this.overallLimit - this.totalItemsRetrieved;\n if (remainingItems <= 0) {\n return {\n items: [],\n hasNextPage: false,\n page: this.currentPage,\n };\n }\n effectivePageSize = Math.min(effectivePageSize, remainingItems);\n }\n\n // Clone the query builder to avoid modifying the original\n const query = this.queryBuilder.clone().limit(effectivePageSize);\n\n // Apply the last evaluated key if we have one\n if (this.lastEvaluatedKey) {\n query.startFrom(this.lastEvaluatedKey);\n }\n\n // Execute the query\n const result = await query.execute();\n\n // Update pagination state\n this.currentPage += 1;\n this.lastEvaluatedKey = result.lastEvaluatedKey;\n this.totalItemsRetrieved += result.items.length;\n\n // Determine if there are more pages\n // We have more pages if:\n // 1. DynamoDB returned a lastEvaluatedKey AND\n // 2. We haven't hit our overall limit (if one exists)\n this.hasMorePages =\n !!result.lastEvaluatedKey && (this.overallLimit === undefined || this.totalItemsRetrieved < this.overallLimit);\n\n return {\n items: result.items,\n lastEvaluatedKey: result.lastEvaluatedKey,\n hasNextPage: this.hasNextPage(),\n page: this.currentPage,\n };\n }\n\n /**\n * Gets all remaining dinosaurs or habitats and combines them into a single array.\n * Use this method when you need to:\n * - Generate complete park inventory\n * - Perform full security audit\n * - Create comprehensive feeding schedule\n * - Run park-wide health checks\n *\n * Note: Use with caution! This method:\n * - Could overwhelm systems with large dinosaur populations\n * - Makes multiple database requests\n * - May cause system strain during peak hours\n *\n * @example\n * ```ts\n * // Get complete carnivore inventory\n * const paginator = new QueryBuilder(executor, eq('diet', 'CARNIVORE'))\n * .filter(op => op.eq('status', 'ACTIVE'))\n * .paginate(10);\n *\n * try {\n * const allCarnivores = await paginator.getAllPages();\n * console.log(`Park contains ${allCarnivores.length} active carnivores`);\n *\n * // Calculate total threat level\n * const totalThreat = allCarnivores.reduce(\n * (sum, dino) => sum + dino.stats.threatLevel,\n * 0\n * );\n * console.log(`Total threat level: ${totalThreat}`);\n * } catch (error) {\n * console.error('Failed to complete carnivore census:', error);\n * }\n * ```\n *\n * @returns A promise that resolves to an array containing all remaining items\n */\n public async getAllPages(): Promise<T[]> {\n const allItems: T[] = [];\n\n while (this.hasNextPage()) {\n const result = await this.getNextPage();\n allItems.push(...result.items);\n }\n\n return allItems;\n }\n}\n"]}
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/conditions.ts
|
|
4
|
+
var createComparisonCondition = (type) => (attr, value) => ({
|
|
5
|
+
type,
|
|
6
|
+
attr,
|
|
7
|
+
value
|
|
8
|
+
});
|
|
9
|
+
var eq = createComparisonCondition("eq");
|
|
10
|
+
var ne = createComparisonCondition("ne");
|
|
11
|
+
var lt = createComparisonCondition("lt");
|
|
12
|
+
var lte = createComparisonCondition("lte");
|
|
13
|
+
var gt = createComparisonCondition("gt");
|
|
14
|
+
var gte = createComparisonCondition("gte");
|
|
15
|
+
var between = (attr, lower, upper) => ({
|
|
16
|
+
type: "between",
|
|
17
|
+
attr,
|
|
18
|
+
value: [lower, upper]
|
|
19
|
+
});
|
|
20
|
+
var beginsWith = createComparisonCondition("beginsWith");
|
|
21
|
+
var contains = createComparisonCondition("contains");
|
|
22
|
+
var attributeExists = (attr) => ({
|
|
23
|
+
type: "attributeExists",
|
|
24
|
+
attr
|
|
25
|
+
});
|
|
26
|
+
var attributeNotExists = (attr) => ({
|
|
27
|
+
type: "attributeNotExists",
|
|
28
|
+
attr
|
|
29
|
+
});
|
|
30
|
+
var and = (...conditions) => ({
|
|
31
|
+
type: "and",
|
|
32
|
+
conditions
|
|
33
|
+
});
|
|
34
|
+
var or = (...conditions) => ({
|
|
35
|
+
type: "or",
|
|
36
|
+
conditions
|
|
37
|
+
});
|
|
38
|
+
var not = (condition) => ({
|
|
39
|
+
type: "not",
|
|
40
|
+
condition
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// src/expression.ts
|
|
44
|
+
var generateAttributeName = (params, attr) => {
|
|
45
|
+
for (const [existingName, existingAttr] of Object.entries(params.expressionAttributeNames)) {
|
|
46
|
+
if (existingAttr === attr) {
|
|
47
|
+
return existingName;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const attrName = `#${Object.keys(params.expressionAttributeNames).length}`;
|
|
51
|
+
params.expressionAttributeNames[attrName] = attr;
|
|
52
|
+
return attrName;
|
|
53
|
+
};
|
|
54
|
+
var generateValueName = (params, value) => {
|
|
55
|
+
const valueName = `:${params.valueCounter.count++}`;
|
|
56
|
+
params.expressionAttributeValues[valueName] = value;
|
|
57
|
+
return valueName;
|
|
58
|
+
};
|
|
59
|
+
var validateCondition = (condition, requiresAttr = true, requiresValue = true) => {
|
|
60
|
+
if (requiresAttr && !condition.attr) {
|
|
61
|
+
throw new Error(`Attribute is required for ${condition.type} condition`);
|
|
62
|
+
}
|
|
63
|
+
if (requiresValue && condition.value === void 0) {
|
|
64
|
+
throw new Error(`Value is required for ${condition.type} condition`);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var buildComparisonExpression = (condition, operator, params) => {
|
|
68
|
+
validateCondition(condition);
|
|
69
|
+
if (!condition.attr) {
|
|
70
|
+
throw new Error(`Attribute is required for ${condition.type} condition`);
|
|
71
|
+
}
|
|
72
|
+
const attrName = generateAttributeName(params, condition.attr);
|
|
73
|
+
const valueName = generateValueName(params, condition.value);
|
|
74
|
+
return `${attrName} ${operator} ${valueName}`;
|
|
75
|
+
};
|
|
76
|
+
var buildBetweenExpression = (condition, params) => {
|
|
77
|
+
validateCondition(condition);
|
|
78
|
+
if (!condition.attr) {
|
|
79
|
+
throw new Error(`Attribute is required for ${condition.type} condition`);
|
|
80
|
+
}
|
|
81
|
+
if (!Array.isArray(condition.value) || condition.value.length !== 2) {
|
|
82
|
+
throw new Error("Between condition requires an array of two values");
|
|
83
|
+
}
|
|
84
|
+
const attrName = generateAttributeName(params, condition.attr);
|
|
85
|
+
const lowerName = generateValueName(params, condition.value[0]);
|
|
86
|
+
const upperName = generateValueName(params, condition.value[1]);
|
|
87
|
+
return `${attrName} BETWEEN ${lowerName} AND ${upperName}`;
|
|
88
|
+
};
|
|
89
|
+
var buildFunctionExpression = (functionName, condition, params) => {
|
|
90
|
+
validateCondition(condition);
|
|
91
|
+
if (!condition.attr) {
|
|
92
|
+
throw new Error(`Attribute is required for ${condition.type} condition`);
|
|
93
|
+
}
|
|
94
|
+
const attrName = generateAttributeName(params, condition.attr);
|
|
95
|
+
const valueName = generateValueName(params, condition.value);
|
|
96
|
+
return `${functionName}(${attrName}, ${valueName})`;
|
|
97
|
+
};
|
|
98
|
+
var buildAttributeFunction = (functionName, condition, params) => {
|
|
99
|
+
validateCondition(condition, true, false);
|
|
100
|
+
if (!condition.attr) {
|
|
101
|
+
throw new Error(`Attribute is required for ${condition.type} condition`);
|
|
102
|
+
}
|
|
103
|
+
const attrName = generateAttributeName(params, condition.attr);
|
|
104
|
+
return `${functionName}(${attrName})`;
|
|
105
|
+
};
|
|
106
|
+
var buildLogicalExpression = (operator, conditions, params) => {
|
|
107
|
+
if (!conditions || conditions.length === 0) {
|
|
108
|
+
throw new Error(`At least one condition is required for ${operator} expression`);
|
|
109
|
+
}
|
|
110
|
+
const expressions = conditions.map((c) => buildExpression(c, params));
|
|
111
|
+
return `(${expressions.join(` ${operator} `)})`;
|
|
112
|
+
};
|
|
113
|
+
var buildExpression = (condition, params) => {
|
|
114
|
+
if (!condition) return "";
|
|
115
|
+
try {
|
|
116
|
+
const expressionBuilders = {
|
|
117
|
+
eq: () => buildComparisonExpression(condition, "=", params),
|
|
118
|
+
ne: () => buildComparisonExpression(condition, "<>", params),
|
|
119
|
+
lt: () => buildComparisonExpression(condition, "<", params),
|
|
120
|
+
lte: () => buildComparisonExpression(condition, "<=", params),
|
|
121
|
+
gt: () => buildComparisonExpression(condition, ">", params),
|
|
122
|
+
gte: () => buildComparisonExpression(condition, ">=", params),
|
|
123
|
+
between: () => buildBetweenExpression(condition, params),
|
|
124
|
+
beginsWith: () => buildFunctionExpression("begins_with", condition, params),
|
|
125
|
+
contains: () => buildFunctionExpression("contains", condition, params),
|
|
126
|
+
attributeExists: () => buildAttributeFunction("attribute_exists", condition, params),
|
|
127
|
+
attributeNotExists: () => buildAttributeFunction("attribute_not_exists", condition, params),
|
|
128
|
+
and: () => {
|
|
129
|
+
if (!condition.conditions) {
|
|
130
|
+
throw new Error("Conditions array is required for AND operator");
|
|
131
|
+
}
|
|
132
|
+
return buildLogicalExpression("AND", condition.conditions, params);
|
|
133
|
+
},
|
|
134
|
+
or: () => {
|
|
135
|
+
if (!condition.conditions) {
|
|
136
|
+
throw new Error("Conditions array is required for OR operator");
|
|
137
|
+
}
|
|
138
|
+
return buildLogicalExpression("OR", condition.conditions, params);
|
|
139
|
+
},
|
|
140
|
+
not: () => {
|
|
141
|
+
if (!condition.condition) {
|
|
142
|
+
throw new Error("Condition is required for NOT operator");
|
|
143
|
+
}
|
|
144
|
+
return `NOT (${buildExpression(condition.condition, params)})`;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const builder = expressionBuilders[condition.type];
|
|
148
|
+
if (!builder) {
|
|
149
|
+
throw new Error(`Unknown condition type: ${condition.type}`);
|
|
150
|
+
}
|
|
151
|
+
return builder();
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error instanceof Error) {
|
|
154
|
+
console.error(`Error building expression for condition type ${condition.type}:`, error.message);
|
|
155
|
+
} else {
|
|
156
|
+
console.error(`Error building expression for condition type ${condition.type}:`, error);
|
|
157
|
+
}
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var prepareExpressionParams = (condition) => {
|
|
162
|
+
if (!condition) return {};
|
|
163
|
+
const params = {
|
|
164
|
+
expressionAttributeNames: {},
|
|
165
|
+
expressionAttributeValues: {},
|
|
166
|
+
valueCounter: { count: 0 }
|
|
167
|
+
};
|
|
168
|
+
const expression = buildExpression(condition, params);
|
|
169
|
+
return {
|
|
170
|
+
expression,
|
|
171
|
+
names: Object.keys(params.expressionAttributeNames).length > 0 ? params.expressionAttributeNames : void 0,
|
|
172
|
+
values: Object.keys(params.expressionAttributeValues).length > 0 ? params.expressionAttributeValues : void 0
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// src/utils/debug-expression.ts
|
|
177
|
+
function debugCommand(command) {
|
|
178
|
+
const result = {};
|
|
179
|
+
function replaceAliases(expressionString) {
|
|
180
|
+
if (!expressionString) {
|
|
181
|
+
return expressionString;
|
|
182
|
+
}
|
|
183
|
+
let replacedString = expressionString;
|
|
184
|
+
for (const alias in command.expressionAttributeNames) {
|
|
185
|
+
const attributeName = command.expressionAttributeNames[alias];
|
|
186
|
+
const regex = new RegExp(alias, "g");
|
|
187
|
+
replacedString = replacedString.replace(regex, attributeName);
|
|
188
|
+
}
|
|
189
|
+
for (const alias in command.expressionAttributeValues) {
|
|
190
|
+
let attributeValue = command.expressionAttributeValues[alias];
|
|
191
|
+
if (attributeValue instanceof Set) {
|
|
192
|
+
const array = Array.from(attributeValue);
|
|
193
|
+
attributeValue = `Set(${array.length}){${array.map((v) => JSON.stringify(v)).join(", ")}}`;
|
|
194
|
+
} else {
|
|
195
|
+
attributeValue = JSON.stringify(attributeValue);
|
|
196
|
+
}
|
|
197
|
+
const regex = new RegExp(alias, "g");
|
|
198
|
+
replacedString = replacedString.replace(regex, attributeValue);
|
|
199
|
+
}
|
|
200
|
+
return replacedString;
|
|
201
|
+
}
|
|
202
|
+
if (command.updateExpression) {
|
|
203
|
+
result.updateExpression = replaceAliases(command.updateExpression);
|
|
204
|
+
}
|
|
205
|
+
if (command.conditionExpression) {
|
|
206
|
+
result.conditionExpression = replaceAliases(command.conditionExpression);
|
|
207
|
+
}
|
|
208
|
+
if (command.filterExpression) {
|
|
209
|
+
result.filterExpression = replaceAliases(command.filterExpression);
|
|
210
|
+
}
|
|
211
|
+
if (command.keyConditionExpression) {
|
|
212
|
+
result.keyConditionExpression = replaceAliases(command.keyConditionExpression);
|
|
213
|
+
}
|
|
214
|
+
if (command.projectionExpression) {
|
|
215
|
+
result.projectionExpression = replaceAliases(command.projectionExpression);
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
raw: command,
|
|
219
|
+
readable: result
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/builders/put-builder.ts
|
|
224
|
+
var PutBuilder = class {
|
|
225
|
+
item;
|
|
226
|
+
options;
|
|
227
|
+
executor;
|
|
228
|
+
tableName;
|
|
229
|
+
constructor(executor, item, tableName) {
|
|
230
|
+
this.executor = executor;
|
|
231
|
+
this.item = item;
|
|
232
|
+
this.tableName = tableName;
|
|
233
|
+
this.options = {
|
|
234
|
+
returnValues: "NONE"
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
set(valuesOrPath, value) {
|
|
238
|
+
if (typeof valuesOrPath === "object") {
|
|
239
|
+
Object.assign(this.item, valuesOrPath);
|
|
240
|
+
} else {
|
|
241
|
+
this.item[valuesOrPath] = value;
|
|
242
|
+
}
|
|
243
|
+
return this;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Adds a condition that must be satisfied for the put operation to succeed.
|
|
247
|
+
* Use this method when you need to:
|
|
248
|
+
* - Prevent overwriting existing items (optimistic locking)
|
|
249
|
+
* - Ensure items meet certain criteria before replacement
|
|
250
|
+
* - Implement complex business rules for item updates
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```ts
|
|
254
|
+
* // Ensure item doesn't exist (insert only)
|
|
255
|
+
* builder.condition(op => op.attributeNotExists('id'))
|
|
256
|
+
*
|
|
257
|
+
* // Complex condition with version check
|
|
258
|
+
* builder.condition(op =>
|
|
259
|
+
* op.and([
|
|
260
|
+
* op.attributeExists('id'),
|
|
261
|
+
* op.eq('version', currentVersion),
|
|
262
|
+
* op.eq('status', 'ACTIVE')
|
|
263
|
+
* ])
|
|
264
|
+
* )
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* @param condition - Either a Condition object or a callback function that builds the condition
|
|
268
|
+
* @returns The builder instance for method chaining
|
|
269
|
+
*/
|
|
270
|
+
/**
|
|
271
|
+
* Adds a condition that must be satisfied for the put operation to succeed.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* // Ensure unique dinosaur ID
|
|
276
|
+
* builder.condition(op =>
|
|
277
|
+
* op.attributeNotExists('id')
|
|
278
|
+
* );
|
|
279
|
+
*
|
|
280
|
+
* // Verify habitat requirements
|
|
281
|
+
* builder.condition(op =>
|
|
282
|
+
* op.and([
|
|
283
|
+
* op.eq('securityStatus', 'READY'),
|
|
284
|
+
* op.attributeExists('lastInspection'),
|
|
285
|
+
* op.gt('securityLevel', 5)
|
|
286
|
+
* ])
|
|
287
|
+
* );
|
|
288
|
+
*
|
|
289
|
+
* // Check breeding facility conditions
|
|
290
|
+
* builder.condition(op =>
|
|
291
|
+
* op.and([
|
|
292
|
+
* op.between('temperature', 25, 30),
|
|
293
|
+
* op.between('humidity', 60, 80),
|
|
294
|
+
* op.eq('quarantineStatus', 'CLEAR')
|
|
295
|
+
* ])
|
|
296
|
+
* );
|
|
297
|
+
* ```
|
|
298
|
+
*
|
|
299
|
+
* @param condition - Either a Condition object or a callback function that builds the condition
|
|
300
|
+
* @returns The builder instance for method chaining
|
|
301
|
+
*/
|
|
302
|
+
condition(condition) {
|
|
303
|
+
if (typeof condition === "function") {
|
|
304
|
+
const conditionOperator = {
|
|
305
|
+
eq,
|
|
306
|
+
ne,
|
|
307
|
+
lt,
|
|
308
|
+
lte,
|
|
309
|
+
gt,
|
|
310
|
+
gte,
|
|
311
|
+
between,
|
|
312
|
+
beginsWith,
|
|
313
|
+
contains,
|
|
314
|
+
attributeExists,
|
|
315
|
+
attributeNotExists,
|
|
316
|
+
and,
|
|
317
|
+
or,
|
|
318
|
+
not
|
|
319
|
+
};
|
|
320
|
+
this.options.condition = condition(conditionOperator);
|
|
321
|
+
} else {
|
|
322
|
+
this.options.condition = condition;
|
|
323
|
+
}
|
|
324
|
+
return this;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Sets whether to return the item's previous values (if it existed).
|
|
328
|
+
*
|
|
329
|
+
* @options
|
|
330
|
+
* - NONE: No return value
|
|
331
|
+
* - ALL_OLD: Returns the item's previous state if it existed, no read capacity units are consumed
|
|
332
|
+
* - CONSISTENT: (default) Performs a GET operation after the put to retrieve the item's new state
|
|
333
|
+
*
|
|
334
|
+
* @example
|
|
335
|
+
* ```ts
|
|
336
|
+
* // Get previous dinosaur state
|
|
337
|
+
* const result = await builder
|
|
338
|
+
* .returnValues('ALL_OLD')
|
|
339
|
+
* .execute();
|
|
340
|
+
*
|
|
341
|
+
* if (result) {
|
|
342
|
+
* console.log('Previous profile:', {
|
|
343
|
+
* species: result.species,
|
|
344
|
+
* status: result.status,
|
|
345
|
+
* stats: {
|
|
346
|
+
* health: result.stats.health,
|
|
347
|
+
* threatLevel: result.stats.threatLevel
|
|
348
|
+
* }
|
|
349
|
+
* });
|
|
350
|
+
* }
|
|
351
|
+
* ```
|
|
352
|
+
*
|
|
353
|
+
* @param returnValues - Use 'ALL_OLD' to return previous values if the item was overwritten, or 'NONE' (default).
|
|
354
|
+
* @returns The builder instance for method chaining
|
|
355
|
+
*/
|
|
356
|
+
returnValues(returnValues) {
|
|
357
|
+
this.options.returnValues = returnValues;
|
|
358
|
+
return this;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Generate the DynamoDB command parameters
|
|
362
|
+
*/
|
|
363
|
+
toDynamoCommand() {
|
|
364
|
+
const { expression, names, values } = prepareExpressionParams(this.options.condition);
|
|
365
|
+
return {
|
|
366
|
+
tableName: this.tableName,
|
|
367
|
+
item: this.item,
|
|
368
|
+
conditionExpression: expression,
|
|
369
|
+
expressionAttributeNames: names,
|
|
370
|
+
expressionAttributeValues: values,
|
|
371
|
+
returnValues: this.options.returnValues
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Adds this put operation to a transaction.
|
|
376
|
+
* Use this method when you need to:
|
|
377
|
+
* - Transfer dinosaurs between habitats
|
|
378
|
+
* - Initialize new breeding programs
|
|
379
|
+
* - Update multiple facility records
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```ts
|
|
383
|
+
* const transaction = new TransactionBuilder();
|
|
384
|
+
*
|
|
385
|
+
* // Add dinosaur to new habitat
|
|
386
|
+
* new PutBuilder(executor, {
|
|
387
|
+
* id: 'TREX-002',
|
|
388
|
+
* location: 'PADDOCK-B',
|
|
389
|
+
* status: 'ACTIVE',
|
|
390
|
+
* transferDate: new Date().toISOString()
|
|
391
|
+
* }, 'dinosaurs')
|
|
392
|
+
* .withTransaction(transaction);
|
|
393
|
+
*
|
|
394
|
+
* // Update habitat records
|
|
395
|
+
* new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-B' })
|
|
396
|
+
* .add('occupants', 1)
|
|
397
|
+
* .set('lastTransfer', new Date().toISOString())
|
|
398
|
+
* .withTransaction(transaction);
|
|
399
|
+
*
|
|
400
|
+
* // Execute transfer atomically
|
|
401
|
+
* await transaction.execute();
|
|
402
|
+
* ```
|
|
403
|
+
*
|
|
404
|
+
* @param transaction - The transaction builder to add this operation to
|
|
405
|
+
* @returns The builder instance for method chaining
|
|
406
|
+
*/
|
|
407
|
+
withTransaction(transaction) {
|
|
408
|
+
const command = this.toDynamoCommand();
|
|
409
|
+
transaction.putWithCommand(command);
|
|
410
|
+
return this;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Executes the put operation against DynamoDB.
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* ```ts
|
|
417
|
+
* try {
|
|
418
|
+
* // Put with condition and return old values
|
|
419
|
+
* const result = await new PutBuilder(executor, newItem, 'myTable')
|
|
420
|
+
* .condition(op => op.eq('version', 1))
|
|
421
|
+
* .returnValues('ALL_OLD')
|
|
422
|
+
* .execute();
|
|
423
|
+
*
|
|
424
|
+
* console.log('Put successful, old item:', result);
|
|
425
|
+
* } catch (error) {
|
|
426
|
+
* // Handle condition check failure or other errors
|
|
427
|
+
* console.error('Put failed:', error);
|
|
428
|
+
* }
|
|
429
|
+
* ```
|
|
430
|
+
*
|
|
431
|
+
* @returns A promise that resolves to the operation result (type depends on returnValues setting)
|
|
432
|
+
* @throws Will throw an error if the condition check fails or other DynamoDB errors occur
|
|
433
|
+
*/
|
|
434
|
+
async execute() {
|
|
435
|
+
const params = this.toDynamoCommand();
|
|
436
|
+
return this.executor(params);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Gets a human-readable representation of the put command
|
|
440
|
+
* with all expression placeholders replaced by their actual values.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```ts
|
|
444
|
+
* const debugInfo = new PutBuilder(executor, {
|
|
445
|
+
* id: 'RAPTOR-003',
|
|
446
|
+
* species: 'Velociraptor',
|
|
447
|
+
* status: 'QUARANTINE',
|
|
448
|
+
* stats: {
|
|
449
|
+
* health: 100,
|
|
450
|
+
* aggressionLevel: 7,
|
|
451
|
+
* age: 2
|
|
452
|
+
* }
|
|
453
|
+
* }, 'dinosaurs')
|
|
454
|
+
* .condition(op =>
|
|
455
|
+
* op.and([
|
|
456
|
+
* op.attributeNotExists('id'),
|
|
457
|
+
* op.eq('quarantineStatus', 'READY'),
|
|
458
|
+
* op.gt('securityLevel', 8)
|
|
459
|
+
* ])
|
|
460
|
+
* )
|
|
461
|
+
* .debug();
|
|
462
|
+
*
|
|
463
|
+
* console.log('Dinosaur transfer command:', debugInfo);
|
|
464
|
+
* ```
|
|
465
|
+
*
|
|
466
|
+
* @returns A readable representation of the put command with resolved expressions
|
|
467
|
+
*/
|
|
468
|
+
debug() {
|
|
469
|
+
const command = this.toDynamoCommand();
|
|
470
|
+
return debugCommand(command);
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
exports.PutBuilder = PutBuilder;
|
|
475
|
+
//# sourceMappingURL=put-builder.cjs.map
|
|
476
|
+
//# sourceMappingURL=put-builder.cjs.map
|