dyno-table 0.1.6 → 0.1.8

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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -17
  3. package/dist/builders/condition-check-builder.cjs +394 -0
  4. package/dist/builders/condition-check-builder.cjs.map +1 -0
  5. package/dist/builders/condition-check-builder.js +392 -0
  6. package/dist/builders/condition-check-builder.js.map +1 -0
  7. package/dist/builders/delete-builder.cjs +422 -0
  8. package/dist/builders/delete-builder.cjs.map +1 -0
  9. package/dist/builders/delete-builder.js +420 -0
  10. package/dist/builders/delete-builder.js.map +1 -0
  11. package/dist/builders/paginator.cjs +199 -0
  12. package/dist/builders/paginator.cjs.map +1 -0
  13. package/dist/builders/paginator.js +197 -0
  14. package/dist/builders/paginator.js.map +1 -0
  15. package/dist/builders/put-builder.cjs +468 -0
  16. package/dist/builders/put-builder.cjs.map +1 -0
  17. package/dist/builders/put-builder.js +466 -0
  18. package/dist/builders/put-builder.js.map +1 -0
  19. package/dist/builders/query-builder.cjs +674 -0
  20. package/dist/builders/query-builder.cjs.map +1 -0
  21. package/dist/builders/query-builder.js +672 -0
  22. package/dist/builders/query-builder.js.map +1 -0
  23. package/dist/builders/transaction-builder.cjs +876 -0
  24. package/dist/builders/transaction-builder.cjs.map +1 -0
  25. package/dist/builders/transaction-builder.js +874 -0
  26. package/dist/builders/transaction-builder.js.map +1 -0
  27. package/dist/builders/update-builder.cjs +662 -0
  28. package/dist/builders/update-builder.cjs.map +1 -0
  29. package/dist/builders/update-builder.js +660 -0
  30. package/dist/builders/update-builder.js.map +1 -0
  31. package/dist/conditions.cjs +59 -0
  32. package/dist/conditions.cjs.map +1 -0
  33. package/dist/conditions.js +43 -0
  34. package/dist/conditions.js.map +1 -0
  35. package/dist/entity.cjs +169 -0
  36. package/dist/entity.cjs.map +1 -0
  37. package/dist/entity.js +165 -0
  38. package/dist/entity.js.map +1 -0
  39. package/dist/index.cjs +3333 -0
  40. package/dist/index.d.cts +2971 -0
  41. package/dist/index.d.ts +1504 -1383
  42. package/dist/index.js +391 -375
  43. package/dist/standard-schema.cjs +4 -0
  44. package/dist/standard-schema.cjs.map +1 -0
  45. package/dist/standard-schema.js +3 -0
  46. package/dist/standard-schema.js.map +1 -0
  47. package/dist/table.cjs +3265 -0
  48. package/dist/table.cjs.map +1 -0
  49. package/dist/table.js +3263 -0
  50. package/dist/table.js.map +1 -0
  51. package/dist/types.cjs +4 -0
  52. package/dist/types.cjs.map +1 -0
  53. package/dist/types.js +3 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/utils/key-template.cjs +19 -0
  56. package/dist/utils/key-template.cjs.map +1 -0
  57. package/dist/utils/key-template.js +17 -0
  58. package/dist/utils/key-template.js.map +1 -0
  59. package/dist/utils/sort-key-template.cjs +19 -0
  60. package/dist/utils/sort-key-template.cjs.map +1 -0
  61. package/dist/utils/sort-key-template.js +17 -0
  62. package/dist/utils/sort-key-template.js.map +1 -0
  63. package/package.json +12 -7
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/conditions.ts","../../src/builders/paginator.ts","../../src/builders/filter-builder.ts","../../src/builders/query-builder.ts"],"names":[],"mappings":"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","file":"query-builder.js","sourcesContent":["import type { Path, PathType } from \"./builders/types\";\n\n/**\n * Supported comparison operators for DynamoDB conditions.\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html AWS DynamoDB - Comparison Operator Reference}\n *\n * - eq: Equals (=)\n * - ne: Not equals (≠ / <>)\n * - lt: Less than (<)\n * - lte: Less than or equal to (≤)\n * - gt: Greater than (>)\n * - gte: Greater than or equal to (≥)\n * - between: Between two values (inclusive)\n * - beginsWith: Checks if string attribute begins with specified substring\n * - contains: Checks if string/set attribute contains specified value\n * - attributeExists: Checks if attribute exists\n * - attributeNotExists: Checks if attribute does not exist\n */\nexport type ComparisonOperator =\n | \"eq\"\n | \"ne\"\n | \"lt\"\n | \"lte\"\n | \"gt\"\n | \"gte\"\n | \"between\"\n | \"beginsWith\"\n | \"contains\"\n | \"attributeExists\"\n | \"attributeNotExists\";\n\n/**\n * Logical operators for combining multiple conditions.\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Logical AWS DynamoDB - Logical Operator Reference}\n *\n * - and: Evaluates to true if all conditions are true\n * - or: Evaluates to true if any condition is true\n * - not: Negate the result of a condition\n */\nexport type LogicalOperator = \"and\" | \"or\" | \"not\";\n\n/**\n * Represents a DynamoDB condition expression.\n * Can be either a comparison condition or a logical combination of conditions.\n *\n * @example\n * // Simple comparison condition\n * const condition: Condition = {\n * type: \"eq\",\n * attr: \"status\",\n * value: \"ACTIVE\"\n * };\n *\n * @example\n * // Logical combination of conditions\n * const condition: Condition = {\n * type: \"and\",\n * conditions: [\n * { type: \"eq\", attr: \"status\", value: \"ACTIVE\" },\n * { type: \"gt\", attr: \"age\", value: 5 }\n * ]\n * };\n */\nexport interface Condition {\n /** The type of condition (comparison or logical operator) */\n type: ComparisonOperator | LogicalOperator;\n /** The attribute name for comparison conditions */\n attr?: string;\n /** The value to compare against for comparison conditions */\n value?: unknown;\n /** Array of conditions for logical operators (and/or) */\n conditions?: Condition[];\n /** Single condition for the 'not' operator */\n condition?: Condition;\n}\n\n/**\n * Parameters used to build DynamoDB expression strings.\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html Expression Attribute Names}\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeValues.html Expression Attribute Values}\n */\nexport interface ExpressionParams {\n /** Map of attribute name placeholders to actual attribute names */\n expressionAttributeNames: Record<string, string>;\n /** Map of value placeholders to actual values */\n expressionAttributeValues: Record<string, unknown>;\n /** Counter for generating unique value placeholders */\n valueCounter: { count: number };\n}\n\n/**\n * Creates a comparison condition builder function for the specified operator.\n * @internal\n */\nexport const createComparisonCondition =\n (type: ComparisonOperator) =>\n (attr: string, value: unknown): Condition => ({\n type,\n attr,\n value,\n });\n\n/**\n * Creates an equals (=) condition\n * @example\n * eq(\"status\", \"ACTIVE\") // status = \"ACTIVE\"\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}\n */\nexport const eq = createComparisonCondition(\"eq\");\n\n/**\n * Creates a not equals (≠) condition\n * @example\n * ne(\"status\", \"DELETED\") // status <> \"DELETED\"\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}\n */\nexport const ne = createComparisonCondition(\"ne\");\n\n/**\n * Creates a less than (<) condition\n * @example\n * lt(\"age\", 18) // age < 18\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}\n */\nexport const lt = createComparisonCondition(\"lt\");\n\n/**\n * Creates a less than or equal to (≤) condition\n * @example\n * lte(\"age\", 18) // age <= 18\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}\n */\nexport const lte = createComparisonCondition(\"lte\");\n\n/**\n * Creates a greater than (>) condition\n * @example\n * gt(\"price\", 100) // price > 100\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}\n */\nexport const gt = createComparisonCondition(\"gt\");\n\n/**\n * Creates a greater than or equal to (≥) condition\n * @example\n * gte(\"price\", 100) // price >= 100\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}\n */\nexport const gte = createComparisonCondition(\"gte\");\n\n/**\n * Creates a between condition that checks if a value is within a range (inclusive)\n * @example\n * between(\"age\", 18, 65) // age BETWEEN 18 AND 65\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators AWS DynamoDB - BETWEEN}\n */\nexport const between = (attr: string, lower: unknown, upper: unknown): Condition => ({\n type: \"between\",\n attr,\n value: [lower, upper],\n});\n\n/**\n * Creates a begins_with condition that checks if a string attribute starts with a substring\n * @example\n * beginsWith(\"email\", \"@example.com\") // begins_with(email, \"@example.com\")\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions AWS DynamoDB - begins_with}\n */\nexport const beginsWith = createComparisonCondition(\"beginsWith\");\n\n/**\n * Creates a contains condition that checks if a string contains a substring or if a set contains an element\n * @example\n * contains(\"tags\", \"important\") // contains(tags, \"important\")\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions AWS DynamoDB - contains}\n */\nexport const contains = createComparisonCondition(\"contains\");\n\n/**\n * Creates a condition that checks if an attribute exists\n * @example\n * attributeExists(\"email\") // attribute_exists(email)\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions AWS DynamoDB - attribute_exists}\n */\nexport const attributeExists = (attr: string): Condition => ({\n type: \"attributeExists\",\n attr,\n});\n\n/**\n * Creates a condition that checks if an attribute does not exist\n * @example\n * attributeNotExists(\"deletedAt\") // attribute_not_exists(deletedAt)\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions AWS DynamoDB - attribute_not_exists}\n */\nexport const attributeNotExists = (attr: string): Condition => ({\n type: \"attributeNotExists\",\n attr,\n});\n\n// --- Logical Operators ---\n\n/**\n * Combines multiple conditions with AND operator\n * @example\n * and(\n * eq(\"status\", \"ACTIVE\"),\n * gt(\"age\", 18)\n * ) // status = \"ACTIVE\" AND age > 18\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Logical AWS DynamoDB - AND}\n */\nexport const and = (...conditions: Condition[]): Condition => ({\n type: \"and\",\n conditions,\n});\n\n/**\n * Combines multiple conditions with OR operator\n * @example\n * or(\n * eq(\"status\", \"PENDING\"),\n * eq(\"status\", \"PROCESSING\")\n * ) // status = \"PENDING\" OR status = \"PROCESSING\"\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Logical AWS DynamoDB - OR}\n */\nexport const or = (...conditions: Condition[]): Condition => ({\n type: \"or\",\n conditions,\n});\n\n/**\n * Negates a condition\n * @example\n * not(eq(\"status\", \"DELETED\")) // NOT status = \"DELETED\"\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Logical AWS DynamoDB - NOT}\n */\nexport const not = (condition: Condition): Condition => ({\n type: \"not\",\n condition,\n});\n\n/**\n * Type-safe operators for building key conditions in DynamoDB queries.\n * Only includes operators that are valid for key conditions.\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions AWS DynamoDB - Key Condition Expressions}\n *\n * @example\n * // Using with sort key conditions\n * table.query({\n * pk: \"USER#123\",\n * sk: op => op.beginsWith(\"ORDER#\")\n * })\n */\nexport type KeyConditionOperator = {\n /** Equals comparison for key attributes */\n eq: (value: unknown) => Condition;\n /** Less than comparison for key attributes */\n lt: (value: unknown) => Condition;\n /** Less than or equal comparison for key attributes */\n lte: (value: unknown) => Condition;\n /** Greater than comparison for key attributes */\n gt: (value: unknown) => Condition;\n /** Greater than or equal comparison for key attributes */\n gte: (value: unknown) => Condition;\n /** Between range comparison for key attributes */\n between: (lower: unknown, upper: unknown) => Condition;\n /** Begins with comparison for key attributes */\n beginsWith: (value: unknown) => Condition;\n /** Combines multiple key conditions with AND */\n and: (...conditions: Condition[]) => Condition;\n};\n\n/**\n * Type-safe operators for building conditions in DynamoDB operations.\n * Includes all available condition operators with proper type inference.\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html AWS DynamoDB - Condition Expressions}\n *\n * @example\n * // Using with type-safe conditions\n * interface User {\n * status: string;\n * age: number;\n * email?: string;\n * }\n *\n * table.scan<User>()\n * .where(op => op.and(\n * op.eq(\"status\", \"ACTIVE\"),\n * op.gt(\"age\", 18),\n * op.attributeExists(\"email\")\n * ))\n *\n * @template T The type of the item being operated on\n */\nexport type ConditionOperator<T extends Record<string, unknown>> = {\n eq: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;\n ne: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;\n lt: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;\n lte: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;\n gt: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;\n gte: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;\n between: <K extends Path<T>>(attr: K, lower: PathType<T, K>, upper: PathType<T, K>) => Condition;\n beginsWith: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;\n contains: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;\n attributeExists: <K extends Path<T>>(attr: K) => Condition;\n attributeNotExists: <K extends Path<T>>(attr: K) => Condition;\n and: (...conditions: Condition[]) => Condition;\n or: (...conditions: Condition[]) => Condition;\n not: (condition: Condition) => Condition;\n};\n\n/**\n * Primary key type for QUERY operations.\n * Allows building complex key conditions for the sort key.\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html AWS DynamoDB - Query Operations}\n *\n * @example\n * // Query items with a specific partition key and sort key prefix\n * table.query({\n * pk: \"USER#123\",\n * sk: op => op.beginsWith(\"ORDER#2023\")\n * })\n *\n * @example\n * // Query items within a specific sort key range\n * table.query({\n * pk: \"USER#123\",\n * sk: op => op.between(\"ORDER#2023-01\", \"ORDER#2023-12\")\n * })\n */\nexport type PrimaryKey = {\n /** Partition key value */\n pk: string;\n /** Optional sort key condition builder */\n sk?: (op: KeyConditionOperator) => Condition;\n};\n\n/**\n * Primary key type for GET and DELETE operations.\n * Used when you need to specify exact key values without conditions.\n * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html AWS DynamoDB - Working with Items}\n *\n * @example\n * // Get a specific item by its complete primary key\n * table.get({\n * pk: \"USER#123\",\n * sk: \"PROFILE#123\"\n * })\n *\n * @example\n * // Delete a specific item by its complete primary key\n * table.delete({\n * pk: \"USER#123\",\n * sk: \"ORDER#456\"\n * })\n */\nexport type PrimaryKeyWithoutExpression = {\n /** Partition key value */\n pk: string;\n /** Optional sort key value */\n sk?: string;\n};\n","import type { 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 Record<string, unknown>, TConfig extends TableConfig = TableConfig> {\n private queryBuilder: QueryBuilderInterface<T, TConfig>;\n private readonly pageSize: number;\n private currentPage = 0;\n private lastEvaluatedKey?: Record<string, unknown>;\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","import {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n between,\n beginsWith,\n contains,\n attributeExists,\n attributeNotExists,\n and,\n or,\n not,\n type Condition,\n type ConditionOperator,\n} from \"../conditions\";\nimport { Paginator } from \"./paginator\";\nimport type { GSINames, TableConfig } from \"../types\";\nimport type { FilterBuilderInterface } from \"./builder-types\";\n\n/**\n * Configuration options for DynamoDB filter operations.\n * These are common options shared between query and scan operations.\n */\nexport interface FilterOptions {\n /** Filter conditions applied to results */\n filter?: Condition;\n /** Maximum number of items to return */\n limit?: number;\n /** Name of the Global Secondary Index to use */\n indexName?: string;\n /** Whether to use strongly consistent reads */\n consistentRead?: boolean;\n /** List of attributes to return in the result */\n projection?: string[];\n /** Token for starting the operation from a specific point */\n lastEvaluatedKey?: Record<string, unknown>;\n}\n\n/**\n * Abstract base builder for creating DynamoDB filter operations.\n * This class provides common functionality for both Query and Scan operations.\n *\n * The builder supports:\n * - Type-safe GSI selection\n * - Complex filter conditions\n * - Pagination\n * - Consistent reads\n * - Attribute projection\n *\n * @typeParam T - The type of items being filtered\n * @typeParam TConfig - The table configuration type for type-safe GSI selection\n */\nexport abstract class FilterBuilder<T extends Record<string, unknown>, TConfig extends TableConfig = TableConfig>\n implements FilterBuilderInterface<T, TConfig>\n{\n protected options: FilterOptions = {};\n protected selectedFields: Set<string> = new Set();\n\n /**\n * Sets the maximum number of items to return.\n * Use this method when you need to:\n * - Limit the number of dinosaurs returned\n * - Control the size of habitat reports\n * - Implement manual pagination of security logs\n *\n * Note: This limit applies to the items that match the key condition\n * before any filter expressions are applied.\n *\n * @example\n * ```typescript\n * // Get first 10 dinosaurs\n * const result = await builder\n * .limit(10)\n * .execute();\n * ```\n *\n * @param limit - Maximum number of items to return\n * @returns The builder instance for method chaining\n */\n limit(limit: number): this {\n this.options.limit = limit;\n return this;\n }\n\n /**\n * Gets the current limit set on the operation.\n * This is used internally by the paginator to manage result sets.\n *\n * @returns The current limit or undefined if no limit is set\n */\n getLimit(): number | undefined {\n return this.options.limit;\n }\n\n /**\n * Specifies a Global Secondary Index (GSI) to use for the operation.\n * Use this method when you need to:\n * - Find dinosaurs by species or status\n * - Search habitats by security level\n * - Find incidents by date\n * - List feeding schedules by time\n *\n * @example\n * ```typescript\n * // Find all dinosaurs of a specific species\n * builder\n * .useIndex('species-status-index')\n * .filter(op => op.eq('status', 'ACTIVE'));\n *\n * // Search high-security habitats\n * builder\n * .useIndex('security-level-index')\n * .filter(op =>\n * op.and([\n * op.gt('securityLevel', 8),\n * op.eq('status', 'OPERATIONAL')\n * ])\n * );\n * ```\n *\n * @param indexName - The name of the GSI to use (type-safe based on table configuration)\n * @returns The builder instance for method chaining\n */\n useIndex<I extends GSINames<TConfig>>(indexName: I): this {\n this.options.indexName = indexName as string;\n return this;\n }\n\n /**\n * Sets whether to use strongly consistent reads for the operation.\n * Use this method when you need to:\n * - Get real-time dinosaur status updates\n * - Monitor critical security systems\n * - Track immediate habitat changes\n * - Verify containment protocols\n *\n * Note:\n * - Consistent reads are not available on GSIs\n * - Consistent reads consume twice the throughput\n * - Default is eventually consistent reads\n *\n * @example\n * ```typescript\n * // Check immediate dinosaur status\n * const result = await builder\n * .filter(op => op.eq('status', 'ACTIVE'))\n * .consistentRead()\n * .execute();\n *\n * // Monitor security breaches\n * const result = await builder\n * .useIndex('primary-index')\n * .consistentRead(isEmergencyMode)\n * .execute();\n * ```\n *\n * @param consistentRead - Whether to use consistent reads (defaults to true)\n * @returns The builder instance for method chaining\n */\n consistentRead(consistentRead = true): this {\n this.options.consistentRead = consistentRead;\n return this;\n }\n\n /**\n * Adds a filter expression to refine the operation results.\n * Use this method when you need to:\n * - Filter dinosaurs by behavior patterns\n * - Find habitats with specific conditions\n * - Search for security incidents\n * - Monitor feeding patterns\n *\n * @example\n * ```typescript\n * // Find aggressive carnivores\n * builder.filter(op =>\n * op.and([\n * op.eq('diet', 'CARNIVORE'),\n * op.gt('aggressionLevel', 7),\n * op.eq('status', 'ACTIVE')\n * ])\n * );\n *\n * // Search suitable breeding habitats\n * builder.filter(op =>\n * op.and([\n * op.between('temperature', 25, 30),\n * op.lt('currentOccupants', 3),\n * op.eq('quarantineStatus', 'CLEAR')\n * ])\n * );\n * ```\n *\n * @param condition - Either a Condition object or a callback function that builds the condition\n * @returns The builder instance for method chaining\n */\n filter(condition: Condition | ((op: ConditionOperator<T>) => Condition)): this {\n if (typeof condition === \"function\") {\n const conditionOperator: ConditionOperator<T> = {\n eq,\n ne,\n lt,\n lte,\n gt,\n gte,\n between,\n beginsWith,\n contains,\n attributeExists,\n attributeNotExists,\n and,\n or,\n not,\n };\n this.options.filter = condition(conditionOperator);\n } else {\n this.options.filter = condition;\n }\n return this;\n }\n\n /**\n * Specifies which attributes to return in the results.\n * Use this method when you need to:\n * - Get specific dinosaur attributes\n * - Retrieve habitat statistics\n * - Monitor security metrics\n * - Optimize response size\n *\n * @example\n * ```typescript\n * // Get basic dinosaur info\n * builder.select([\n * 'species',\n * 'status',\n * 'stats.health',\n * 'stats.aggressionLevel'\n * ]);\n *\n * // Monitor habitat conditions\n * builder\n * .select('securityStatus')\n * .select([\n * 'currentOccupants',\n * 'temperature',\n * 'lastInspectionDate'\n * ]);\n * ```\n *\n * @param fields - A single field name or an array of field names to return\n * @returns The builder instance for method chaining\n */\n select(fields: string | string[]): this {\n if (typeof fields === \"string\") {\n this.selectedFields.add(fields);\n } else if (Array.isArray(fields)) {\n for (const field of fields) {\n this.selectedFields.add(field);\n }\n }\n\n this.options.projection = Array.from(this.selectedFields);\n return this;\n }\n\n /**\n * Creates a paginator that handles DynamoDB pagination automatically.\n * The paginator handles:\n * - Tracking the last evaluated key\n * - Managing page boundaries\n * - Respecting overall query limits\n *\n * @example\n * ```typescript\n * // Create a paginator for dinosaur records\n * const paginator = builder\n * .filter(op => op.eq('status', 'ACTIVE'))\n * .paginate(10);\n *\n * // Process pages of dinosaur results\n * while (paginator.hasNextPage()) {\n * const page = await paginator.getNextPage();\n * console.log(`Processing page ${page.page}, count: ${page.items.length}`);\n * // Process dinosaur data\n * }\n * ```\n *\n * @param pageSize - The number of items to return per page\n * @returns A Paginator instance that manages the pagination state\n * @see Paginator for more pagination control options\n */\n paginate(pageSize: number): Paginator<T, TConfig> {\n return new Paginator<T, TConfig>(this, pageSize);\n }\n\n /**\n * Sets the starting point using a previous lastEvaluatedKey.\n * Use this method when you need to:\n * - Implement manual dinosaur list pagination\n * - Resume habitat inspection reviews\n * - Continue security incident analysis\n * - Store operation position between sessions\n *\n * Note: This method is typically used for manual pagination.\n * For automatic pagination, use the paginate() method instead.\n *\n * @example\n * ```typescript\n * // First batch of dinosaurs\n * const result1 = await builder\n * .filter(op => op.eq('status', 'ACTIVE'))\n * .limit(5)\n * .execute();\n *\n * if (result1.lastEvaluatedKey) {\n * // Continue listing dinosaurs\n * const result2 = await builder\n * .filter(op => op.eq('status', 'ACTIVE'))\n * .startFrom(result1.lastEvaluatedKey)\n * .limit(5)\n * .execute();\n *\n * console.log('Additional dinosaurs:', result2.items);\n * }\n * ```\n *\n * @param lastEvaluatedKey - The exclusive start key from a previous result\n * @returns The builder instance for method chaining\n */\n startFrom(lastEvaluatedKey: Record<string, unknown>): this {\n this.options.lastEvaluatedKey = lastEvaluatedKey;\n return this;\n }\n\n /**\n * Creates a deep clone of this builder instance.\n * Use this method when you need to:\n * - Query different dinosaur statuses\n * - Check multiple habitat conditions\n * - Monitor various security levels\n * - Create report templates\n *\n * This is particularly useful when:\n * - Implementing pagination (used internally by paginate())\n * - Creating operation templates\n * - Running multiple variations of an operation\n *\n * @example\n * ```typescript\n * // Create base dinosaur query\n * const baseBuilder = builder\n * .useIndex('status-index')\n * .select(['id', 'status', 'location']);\n *\n * // Check active dinosaurs\n * const activeRaptors = baseBuilder.clone()\n * .filter(op => op.eq('status', 'HUNTING'))\n * .execute();\n *\n * // Check contained dinosaurs\n * const containedRaptors = baseBuilder.clone()\n * .filter(op => op.eq('status', 'CONTAINED'))\n * .execute();\n * ```\n *\n * @returns A new builder instance with the same configuration\n */\n abstract clone(): FilterBuilderInterface<T, TConfig>;\n\n /**\n * Executes the operation against DynamoDB.\n * This method must be implemented by subclasses to handle\n * their specific execution logic.\n */\n abstract execute(): Promise<{ items: T[]; lastEvaluatedKey?: Record<string, unknown> }>;\n}\n","import type { Condition } from \"../conditions\";\nimport { FilterBuilder, type FilterOptions } from \"./filter-builder\";\nimport type { TableConfig } from \"../types\";\nimport type { QueryBuilderInterface } from \"./builder-types\";\n\n/**\n * Configuration options for DynamoDB query operations.\n * Extends the base FilterOptions with query-specific options.\n */\nexport interface QueryOptions extends FilterOptions {\n /** Condition for the sort key in the table or index */\n sortKeyCondition?: Condition;\n /** Direction of sort key traversal (true for ascending, false for descending) */\n scanIndexForward?: boolean;\n}\n\n/**\n * Function type for executing DynamoDB query operations.\n * @typeParam T - The type of items being queried\n */\ntype QueryExecutor<T extends Record<string, unknown>> = (\n keyCondition: Condition,\n options: QueryOptions,\n) => Promise<{ items: T[]; lastEvaluatedKey?: Record<string, unknown> }>;\n\n/**\n * Builder for creating DynamoDB query operations.\n *\n * The builder supports:\n * - Type-safe GSI selection\n * - Complex filter conditions\n * - Automatic pagination handling\n * - Consistent reads\n * - Forward and reverse sorting\n *\n * @example\n * ```typescript\n * // Simple query\n * const result = await new QueryBuilder(executor, eq('userId', '123'))\n * .execute();\n *\n * // Complex query with GSI and filtering\n * const result = await new QueryBuilder(executor, eq('status', 'ACTIVE'))\n * .useIndex('status-index')\n * .filter(op => op.beginsWith('name', 'John'))\n * .select(['id', 'name', 'email'])\n * .sortDescending()\n * .limit(10)\n * .execute();\n *\n * // Query with pagination\n * const paginator = new QueryBuilder(executor, eq('type', 'order'))\n * .paginate(25);\n *\n * while (paginator.hasNextPage()) {\n * const page = await paginator.getNextPage();\n * // Process page.items\n * }\n * ```\n *\n * @typeParam T - The type of items being queried\n * @typeParam TConfig - The table configuration type for type-safe GSI selection\n */\nexport class QueryBuilder<T extends Record<string, unknown>, TConfig extends TableConfig = TableConfig>\n extends FilterBuilder<T, TConfig>\n implements QueryBuilderInterface<T, TConfig>\n{\n private readonly keyCondition: Condition;\n protected override options: QueryOptions = {};\n protected readonly executor: QueryExecutor<T>;\n\n constructor(executor: QueryExecutor<T>, keyCondition: Condition) {\n super();\n this.executor = executor;\n this.keyCondition = keyCondition;\n }\n\n /**\n * Sets the maximum number of items to return from the query.\n *\n * Note: This is the default behavior if no sort order is specified.\n *\n * @example\n * ```typescript\n * // Get orders in chronological order\n * const result = await new QueryBuilder(executor, eq('userId', '123'))\n * .sortAscending()\n * .execute();\n *\n * // Get events from oldest to newest\n * const result = await new QueryBuilder(executor, eq('entityId', 'order-123'))\n * .useIndex('entity-timestamp-index')\n * .sortAscending()\n * .execute();\n * ```\n *\n * @returns The builder instance for method chaining\n */\n /**\n * Sets the query to return items in ascending order by sort key.\n *\n * @example\n * ```typescript\n * // List dinosaurs by age\n * const result = await new QueryBuilder(executor, eq('species', 'Velociraptor'))\n * .useIndex('age-index')\n * .sortAscending()\n * .execute();\n *\n * // View incidents chronologically\n * const result = await new QueryBuilder(executor, eq('type', 'SECURITY_BREACH'))\n * .useIndex('date-index')\n * .sortAscending()\n * .execute();\n * ```\n *\n * @returns The builder instance for method chaining\n */\n sortAscending(): this {\n this.options.scanIndexForward = true;\n return this;\n }\n\n /**\n * Sets the query to return items in descending order by sort key.\n *\n * @example\n * ```typescript\n * // Get most recent security incidents\n * const result = await new QueryBuilder(executor, eq('type', 'SECURITY_BREACH'))\n * .useIndex('date-index')\n * .sortDescending()\n * .limit(10)\n * .execute();\n *\n * // Check latest dinosaur activities\n * const result = await new QueryBuilder(executor, eq('species', 'Velociraptor'))\n * .useIndex('activity-time-index')\n * .filter(op => op.eq('status', 'ACTIVE'))\n * .sortDescending()\n * .execute();\n * ```\n *\n * @returns The builder instance for method chaining\n */\n sortDescending(): this {\n this.options.scanIndexForward = false;\n return this;\n }\n\n /**\n * Creates a deep clone of this QueryBuilder instance.\n *\n * This is particularly useful when:\n * - Implementing pagination (used internally by paginate())\n * - Creating query templates\n * - Running multiple variations of a query\n *\n * @example\n * ```typescript\n * // Create base dinosaur query\n * const baseQuery = new QueryBuilder(executor, eq('species', 'Velociraptor'))\n * .useIndex('status-index')\n * .select(['id', 'status', 'location']);\n *\n * // Check active dinosaurs\n * const activeRaptors = baseQuery.clone()\n * .filter(op => op.eq('status', 'HUNTING'))\n * .execute();\n *\n * // Check contained dinosaurs\n * const containedRaptors = baseQuery.clone()\n * .filter(op => op.eq('status', 'CONTAINED'))\n * .execute();\n *\n * // Check sedated dinosaurs\n * const sedatedRaptors = baseQuery.clone()\n * .filter(op => op.eq('status', 'SEDATED'))\n * .execute();\n * ```\n *\n * @returns A new QueryBuilder instance with the same configuration\n */\n clone(): QueryBuilder<T, TConfig> {\n const clone = new QueryBuilder<T, TConfig>(this.executor, this.keyCondition);\n clone.options = { ...this.options };\n clone.selectedFields = new Set(this.selectedFields);\n return clone;\n }\n\n /**\n * Executes the query against DynamoDB.\n *\n * The method returns both the matched items and, if there are more results,\n * a lastEvaluatedKey that can be used with startFrom() to continue the query.\n *\n * @example\n * ```typescript\n * try {\n * // Find active carnivores in specific habitat\n * const result = await new QueryBuilder(executor, eq('habitatId', 'PADDOCK-A'))\n * .useIndex('species-status-index')\n * .filter(op =>\n * op.and([\n * op.eq('diet', 'CARNIVORE'),\n * op.eq('status', 'ACTIVE'),\n * op.gt('aggressionLevel', 7)\n * ])\n * )\n * .sortDescending()\n * .limit(5)\n * .execute();\n *\n * console.log(`Found ${result.items.length} dangerous dinosaurs`);\n *\n * if (result.lastEvaluatedKey) {\n * console.log('Additional threats detected');\n * }\n * } catch (error) {\n * console.error('Security scan failed:', error);\n * }\n * ```\n *\n * @returns A promise that resolves to an object containing:\n * - items: Array of items matching the query\n * - lastEvaluatedKey: Token for continuing the query, if more items exist\n */\n async execute(): Promise<{ items: T[]; lastEvaluatedKey?: Record<string, unknown> }> {\n return this.executor(this.keyCondition, this.options);\n }\n}\n"]}