{"id":42121354,"url":"https://github.com/oolio-group/dynamo-helper","last_synced_at":"2026-01-26T14:33:23.149Z","repository":{"id":46060351,"uuid":"285447313","full_name":"oolio-group/dynamo-helper","owner":"oolio-group","description":"DynamoDB client and query expression builder. Helps with most of the DynamoDB operations and takes care of the hard stuff for you.","archived":false,"fork":false,"pushed_at":"2025-11-13T08:33:07.000Z","size":482,"stargazers_count":6,"open_issues_count":18,"forks_count":3,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-11-13T09:17:31.339Z","etag":null,"topics":["aws","documentclient","dynamodb","nodejs","nosql"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oolio-group.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-08-06T01:53:23.000Z","updated_at":"2025-05-03T03:05:35.000Z","dependencies_parsed_at":"2023-09-12T09:42:09.744Z","dependency_job_id":"4b88bfc6-c425-431c-8d88-fab281c8c99c","html_url":"https://github.com/oolio-group/dynamo-helper","commit_stats":null,"previous_names":["oolio-group/dynamo-helper","hitz-group/dynamo-helper"],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/oolio-group/dynamo-helper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oolio-group%2Fdynamo-helper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oolio-group%2Fdynamo-helper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oolio-group%2Fdynamo-helper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oolio-group%2Fdynamo-helper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oolio-group","download_url":"https://codeload.github.com/oolio-group/dynamo-helper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oolio-group%2Fdynamo-helper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28780349,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T13:55:28.044Z","status":"ssl_error","status_checked_at":"2026-01-26T13:55:26.068Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","documentclient","dynamodb","nodejs","nosql"],"created_at":"2026-01-26T14:33:22.172Z","updated_at":"2026-01-26T14:33:23.133Z","avatar_url":"https://github.com/oolio-group.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @oolio-group/dynamo-helper\n\nLibrary package that exports several methods for helping with DynamoDB operations. Abstracts most DynamoDB operations and builds query parameters using a unified filter object. Mainly aimed at single table design pattern\n\n[![codecov](https://codecov.io/gh/oolio-group/dynamo-helper/branch/master/graph/badge.svg?token=WDLQ7IBV6Y)](https://codecov.io/gh/oolio-group/dynamo-helper) [![npm](https://img.shields.io/npm/v/@oolio-group/dynamo-helper/latest.svg)](https://www.npmjs.com/package/@oolio-group/dynamo-helper) ![Build](https://github.com/oolio-group/dynamo-helper/workflows/Unit%20Tests%20and%20ESLint/badge.svg)\n\n## Usage\n\n### Create DynamoHelper instance\n\nImport DynamoHelper\n\n```typescript\nimport { DynamoHelper } from '@oolio-group/dynamo-helper';\n\nconst { DynamoHelper } = require('@oolio-group/dynamo-helper');\n```\n\nUse constructor to create the DynamoHelper instance\n\n```typescript\n// region and endpoint are optional\nconst dynamoHelper = new DynamoHelper(tableConf, region, endpoint);\n```\n\ntableConf should be of type TableConfig\n\n```typescript\ntype TableIndex = { partitionKeyName: string; sortKeyName: string };\n\nexport interface TableConfig {\n  name: string;\n  indexes: { default: TableIndex } \u0026 Record\u003cstring, TableIndex\u003e;\n}\n```\n\n### Example\n\n```typescript\nimport { DynamoHelper } from '@oolio-group/dynamo-helper';\n\nconst table = {\n  name: 'my-ddb-table',\n  indexes: {\n    default: {\n      partitionKeyName: 'pk',\n      sortKeyName: 'sk',\n    },\n  },\n};\nconst client = new DynamoHelper(table, 'ap-south-1');\n\nawait client.getItem({ id: 'book-123' });\nawait client.getItem({ pk: 'library#books', sk: 'book-123' });\n\nawait client.query({\n  where: {\n    pk: 'library#books',\n    publishedAt: {\n      between: [15550000, 15800000],\n    },\n  },\n});\n```\n\n### buildQueryTableParams\n\n```typescript\nimport { buildQueryTableParams } from '@oolio-group/dynamo-helper';\n\nconst { buildQueryTableParams } = require('@oolio-group/dynamo-helper');\n```\n\nThis method generates DynamoDB query input params from given filter object of type `Filter\u003cT\u003e`\n\n```typescript\nbuildQueryTableParams\u003cT extends object = AnyObject\u003e(\n  filter: Filter\u003cT\u003e,\n  partitionKey = 'pk',\n  sortKey = 'sk',\n): QueryInput\n```\n\nIt thoroughly validates input based on following criteria\n\n- Filter must strictly be of type `Filter\u003cT\u003e`\n- PartitionKey and sortKey if given needs to be string\n- PartitionKey cannot be empty and is required for query operation\n- Where is required and needs to contain at least partition key condition\n- Partition key condition can only be equal operation\n- Fields if provided needs to contain string (fields of model)\n- Limit if provided needs to be a number greater than zero\n\n#### Filter\n\n```typescript\nexport interface Filter\u003cMT extends object = AnyObject\u003e {\n  /**\n   * The matching criteria\n   */\n  where?: Where\u003cMT\u003e;\n  /**\n   * To include/exclude fields\n   */\n  fields?: Fields\u003cMT\u003e;\n  /**\n   * Maximum number of entities\n   */\n  limit?: number;\n  /**\n   * Sort order. Only works with sort keys\n   */\n  orderBy?: Direction;\n}\n```\n\n#### keys\n\nYou can provide the name of your partition key and sort key, they are defaulted to `pk` and `sk`\n\n#### Return value\n\nIt returns a partial `QueryInput` which does not contain `TableName` or `IndexName`\n\n#### Usage\n\n```typescript\nimport { buildQueryTableParams } from '@oolio-group/dynamo-helper';\n\n// Get all inactive product id's in organization\nconst queryInput = buildQueryTableParams\u003cProductModel\u003e({\n  where: {\n    pk: 'org_uuid',\n    sk: {\n      beginsWith: 'product_',\n    },\n    isActive: false,\n  },\n  fields: ['id'],\n  limit: 5,\n});\n```\n\n### query\n\nPerform a query operation in DynamoDB. Input parameter `Filter` can be customized with various operations\n\nSee type `Filter` for supported operations\n\n```typescript\nimport { query } from '@oolio-group/dynamo-helper';\n\n// Get all inactive product id's in organization\nconst products = await dynamoHelper.query\u003cProductModel\u003e({\n  where: {\n    pk: 'org_uuid',\n    sk: {\n      beginsWith: 'product_',\n    },\n    isActive: false,\n    fields: ['id'],\n  },\n});\n```\n\n#### Consistent Read\n\nBy default, DynamoDB uses eventually consistent reads. To use strongly consistent reads, pass `true` as the third parameter to the query method:\n\n```typescript\n// Perform a strongly consistent read\nconst products = await dynamoHelper.query\u003cProductModel\u003e(\n  {\n    where: {\n      pk: 'org_uuid',\n      sk: {\n        beginsWith: 'product_',\n      },\n    },\n  },\n  undefined,  // indexName\n  true        // consistentRead\n);\n```\n\n**Note:** Consistent reads are only supported on the base table and local secondary indexes, not on global secondary indexes. Consistent reads consume twice the read capacity units compared to eventually consistent reads.\n\n### pginated based query (cursor)\n\n- DynamoDB official docs - [Paginate table query result](https://docs.amazonaws.cn/en_us/amazondynamodb/latest/developerguide/Query.Pagination.html) and [Query](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html)\n- To use this method, the table must have a `range key` associated to partition key\n- Using the method from this library (`queryWithCursor`)\n  Example 1:\n\n```tsx\n// Paginate with a custom page size (refer to AWS DynamoDB docs to check the max size / limit)\n// Get first `6` organizations (DynamoDB default sort order will be ascending)\nconst resultForFirstIterationOrPage = await query({\n  where: {\n    pk: 'org_uuid',\n  },\n  limit: 6,\n});\n\n// The next `6` orgs can be retrived based on the `cursor` value (from previous response)\nconst resultForFirstIterationOrPage = await query({\n  where: {\n    pk: 'org_uuid',\n  },\n  limit: 6,\n  prevCursor: result.cursor,\n});\n\n// The same step can be repeated until the `cursor` returns `undefined`\n```\n\nExample 2:\n\n```tsx\n// Sort the results in reverse order with a page size `7`- descending\nconst result = await query({\n  where: {\n    pk: 'org_uuid',\n  },\n  limit: 7,\n  orderBy: Direction.DESC,\n});\n```\n\n#### Supported filter operators\n\n- `eq`\n- `neq` (filter conditions only)\n- `gt`\n- `gte`\n- `lt`\n- `lte`\n- `inq`\n- `between`\n- `like`\n- `beginsWith`\n\n### getItem\n\nFetch an item using pk and sk combination. Returns item if found or returns null\n`getItem\u003cT\u003e(key: DocumentClient.Key, fields: Array\u003ckeyof T\u003e)`\n\n#### key\n\nRequired, at least partition key values must be provided.\n\n#### fields\n\nOptional, specify fields to project\n\n```typescript\nimport { getItem } from '@oolio-group/dynamo-helper';\n\n// Get a single product matching the key\nawait dynamoHelper.getItem\u003cProductModel\u003e({ pk: 'org_uuid', sk: 'product_xxx' });\nawait dynamoHelper.getItem\u003cProductModel\u003e({ id: 'product_xxx' }, [\n  'id',\n  'isActive',\n]);\n```\n\n#### Consistent Read\n\nTo use strongly consistent reads with `getItem`, pass `true` as the third parameter:\n\n```typescript\n// Get item with strongly consistent read\nconst product = await dynamoHelper.getItem\u003cProductModel\u003e(\n  { pk: 'org_uuid', sk: 'product_xxx' },\n  ['id', 'name', 'price'],\n  true  // consistentRead\n);\n```\n\n**Note:** Consistent reads consume twice the read capacity units compared to eventually consistent reads.\n\n### batchGetItems\n\nFetch many items using pk and sk combination\n\n```typescript\nimport { batchGetItems } from '@oolio-group/dynamo-helper';\n\n// Get all products matching the keys\nconst products = await dynamoHelper.batchGetItems\u003cProductModel\u003e([\n  { pk: 'x', sk: '1' },\n  { pk: 'y', sk: '2' },\n]);\n```\n\n#### Consistent Read\n\nTo use strongly consistent reads with `batchGetItems`, pass `true` as the third parameter:\n\n```typescript\n// Batch get items with strongly consistent read\nconst products = await dynamoHelper.batchGetItems\u003cProductModel\u003e(\n  [\n    { pk: 'org_uuid', sk: 'product_1' },\n    { pk: 'org_uuid', sk: 'product_2' },\n  ],\n  ['id', 'name', 'price'],  // fields to project\n  true  // consistentRead\n);\n```\n\n**Note:** Consistent reads consume twice the read capacity units compared to eventually consistent reads.\n\n### exists\n\nCheck if an item exists in the database with the keys provided. Returns a boolean value\n\n```typescript\nimport { exists } from '@oolio-group/dynamo-helper';\n\n// Check if product already exists\nif (await dynamoHelper.exists({ id: 'x' })) {\n  console.log('exists');\n}\n```\n\n### putItem\n\nCreate a new item or replace an existing item in the database\n\n```typescript\nimport { putItem } from '@oolio-group/dynamo-helper';\n\nawait dynamoHelper.putItem({\n  pk: 'x',\n  sk: '1',\n  name: 'Product A',\n});\n```\n\n#### Conditional Put\n\nSupports conditional put operations using [Conditional writes](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.ConditionalUpdate). This is useful to prevent overwriting existing items.\n\n```typescript\nimport {\n  putItem,\n  ConditionExpressionInput,\n  ConditionExpressionKind,\n} from '@oolio-group/dynamo-helper';\n\n// Prevent overwriting an existing item - only put if partition key doesn't exist\nconst conditions: ConditionExpressionInput[] = [\n  {\n    kind: ConditionExpressionKind.Comparison,\n    key: 'pk',\n    comparator: 'exists',\n    value: false,\n  },\n];\n\nawait dynamoHelper.putItem(\n  {\n    pk: 'product_123',\n    sk: 'product_123',\n    name: 'New Product',\n  },\n  conditions\n);\n```\n\nYou can also use multiple conditions with AND/OR logic:\n\n```typescript\n// Put item only if it doesn't exist OR if status is inactive\nconst conditions: ConditionExpressionInput[] = [\n  {\n    kind: ConditionExpressionKind.Comparison,\n    key: 'pk',\n    comparator: 'exists',\n    value: false,\n  },\n  {\n    kind: ConditionExpressionKind.AndOr,\n    value: 'OR',\n  },\n  {\n    kind: ConditionExpressionKind.Comparison,\n    key: 'status',\n    comparator: 'eq',\n    value: 'inactive',\n  },\n];\n\nawait dynamoHelper.putItem(\n  {\n    pk: 'product_123',\n    sk: 'product_123',\n    name: 'Updated Product',\n    status: 'active',\n  },\n  conditions\n);\n```\n\n\n### deleteItem\n\nRemove an item from database matching the key provided if it exists\n\n```typescript\nimport { deleteItem } from '@oolio-group/dynamo-helper';\n\n// delete product\nawait dynamoHelper.deleteItem({ id: '1' });\n```\n\n### transactPutItems\n\nCreate or replace multiple items in the database as a transaction\nIf any of the many operations fails then whole transaction is considered as failed.\nThis is useful when multiple entries needs to be created or replaced for an API operation\n\n```typescript\nimport { transactPutItems } from '@oolio-group/dynamo-helper';\n\n// initiate a transaction\nawait dynamoHelper.transactPutItems([\n  {\n    pk: 'product_1',\n    sk: 'product_1',\n    name: 'Product A',\n  },\n  {\n    pk: 'product_2',\n    sk: 'product_2',\n    name: 'Product B',\n  },\n  {\n    pk: 'org_1',\n    sk: 'product_1',\n    isActive: true,\n  },\n]);\n```\n\n### batchPutItems\n\nCreate or replace multiple items in the database at the same time. This method will chunk your data into batches of 25 items.\n\n\u003e The BatchWriteItem operation puts or deletes multiple items in one or more tables. A single call to BatchWriteItem can write up to 16 MB of data, which can comprise as many as 25 put or delete requests. Individual items to be written can be as large as 400 KB.\n\n```typescript\nimport { batchPutItems } from '@oolio-group/dynamo-helper';\n\n// create multiple items\nawait dynamoHelper.batchPutItems([\n  {\n    pk: 'product_1',\n    sk: 'product_1',\n    name: 'Product A',\n  },\n  {\n    pk: 'product_2',\n    sk: 'product_2',\n    name: 'Product B',\n  },\n  {\n    pk: 'org_1',\n    sk: 'product_1',\n    isActive: true,\n  },\n]);\n```\n\n### batchDeleteItems\n\nDelete multiple items in the database at the same time. This method will chunk your data into batches of 25 items.\n\n\u003e The BatchWriteItem operation puts or deletes multiple items in one or more tables. A single call to BatchWriteItem can write up to 16 MB of data, which can comprise as many as 25 put or delete requests. Individual items to be written can be as large as 400 KB.\n\n```typescript\nimport { batchDeleteItems } from '@oolio-group/dynamo-helper';\n\n// delete multiple items\nawait dynamoHelper.batchDeleteItems([\n  {\n    pk: 'product_1',\n    sk: 'product_1',\n  },\n  {\n    pk: 'product_2',\n    sk: 'product_2',\n  },\n  {\n    pk: 'org_1',\n    sk: 'product_1',\n  },\n]);\n```\n\n### batchExists\n\nChecks if keys provided exists in database or not. Returns empty list if all items are found in DB. Returns list of items not found in DB if there are non existent items.\n\n```typescript\nimport { batchExists } from '@oolio-group/dynamo-helper';\n\nconst result = await dynamoHelper.batchExists([\n  {\n    pk: 'product_1',\n    sk: 'product_1',\n  },\n  {\n    pk: 'product_2',\n    sk: 'product_2',\n  },\n  {\n    pk: 'org_1',\n    sk: 'product_1',\n  },\n]);\n\nif (result.length === 0) {\n  // All items exists\n} else {\n  // Items that does not exist\n  console.log(result);\n}\n```\n\n### updateItem\n\nSupports updating item conditionally using [Conditional writes](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.ConditionalUpdate)\n\n```typescript\nimport {\n  updateItem,\n  ConditionExpressionInput,\n} from '@oolio-group/dynamo-helper';\n\nconst where = {\n  pk: 'product_123',\n};\n\nconst conditions: ConditionExpressionInput[] = [\n  {\n    kind: ConditionExpressionKind.Comparison,\n    key: 'Price',\n    comparator: 'gt',\n    value: 50,\n  },\n  {\n    kind: ConditionExpressionKind.AndOr,\n    value: 'AND',\n  },\n  {\n    kind: ConditionExpressionKind.Comparison,\n    key: 'Quantity',\n    comparator: 'lt',\n    value: 20,\n  },\n  {\n    kind: ConditionExpressionKind.AndOr,\n    value: 'OR',\n  },\n  {\n    kind: ConditionExpressionKind.Comparison,\n    key: 'IsPromotionalProduct',\n    comparator: 'eq',\n    value: true,\n  },\n  {\n    kind: ConditionExpressionKind.AndOr,\n    value: 'OR',\n  },\n  {\n    kind: ConditionExpressionKind.Comparison,\n    key: 'color',\n    comparator: 'like',\n    value: 'red',\n  },\n  {\n    kind: ConditionExpressionKind.AndOr,\n    value: 'AND',\n  },\n  {\n    kind: ConditionExpressionKind.Comparison,\n    key: 'createdAt',\n    comparator: 'between',\n    value: [1670803200000, 1674586168676],\n  },\n];\n\nconst prevPrice = 3000;\nconst prevSales = 2;\nconst updates = {\n  price: prevPrice - 100,\n  salesCount: prevSales + 1,\n};\n\nupdateItem(where, conditions, updates);\n```\n\n## TODO\n\n- [ ] Scan operation support\n- [x] Support tables without sort key\n\n## Development\n\n### Build\n\nBuild all projects `yarn build`\nClean build output `yarn clean`\n\n### Publishing new package\n\nFollow these steps to publish package to npm whenever a new version is available:\n\n- Step 1: Create a new publish branch\n- Step 2: Change package version in `package.json` to whatever version that fits (Eg: 0.4.14)\n- Step 3: Commit the change with commit message as `Release \u003cversion number\u003e` (Eg: `Release 0.4.14`)\n- Step 4: Push all the changes and create a PR for the release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foolio-group%2Fdynamo-helper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foolio-group%2Fdynamo-helper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foolio-group%2Fdynamo-helper/lists"}