{"id":26235796,"url":"https://github.com/spencerlepine/dynamo-query","last_synced_at":"2025-10-29T22:21:28.785Z","repository":{"id":280494703,"uuid":"942166737","full_name":"spencerlepine/dynamo-query","owner":"spencerlepine","description":"⚡ Type-safe ORM for AWS DynamoDB NoSQL, inspired by Prisma","archived":false,"fork":false,"pushed_at":"2025-03-03T19:07:08.000Z","size":4523,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-03T19:21:45.006Z","etag":null,"topics":["aws-dynamodb","dynamo","dynamo-db","dynamo-sdk","dynamodb","nosql","nosql-query-builder","orm","prisma","prisma-orm","query-builder","querybuilder","sql-query-builder"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/dynamo-query","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spencerlepine.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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}},"created_at":"2025-03-03T17:20:01.000Z","updated_at":"2025-03-03T19:07:11.000Z","dependencies_parsed_at":"2025-03-03T19:21:47.036Z","dependency_job_id":"2e649763-4fc3-4c05-961a-5c55364f38f9","html_url":"https://github.com/spencerlepine/dynamo-query","commit_stats":null,"previous_names":["spencerlepine/dynamo-query"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spencerlepine%2Fdynamo-query","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spencerlepine%2Fdynamo-query/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spencerlepine%2Fdynamo-query/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spencerlepine%2Fdynamo-query/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spencerlepine","download_url":"https://codeload.github.com/spencerlepine/dynamo-query/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243330300,"owners_count":20274039,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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-dynamodb","dynamo","dynamo-db","dynamo-sdk","dynamodb","nosql","nosql-query-builder","orm","prisma","prisma-orm","query-builder","querybuilder","sql-query-builder"],"created_at":"2025-03-13T03:18:00.946Z","updated_at":"2025-10-29T22:21:23.719Z","avatar_url":"https://github.com/spencerlepine.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/logo.png\" /\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eDynamo-Query\u003c/h1\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/dynamo-query.svg?style=flat\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg\" /\u003e\u003c/a\u003e\n  \u003ca href=\"./LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue\" /\u003e\u003c/a\u003e\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n\u003c/div\u003e\n\n\u003e This is a type-safe ORM for AWS DynamoDB NoSQL, inspired by [Prisma.io](https://www.prisma.io/)\n\nThis package is for you if you're building data-driven applications and you're using AWS DynamoDB NoSQL as the main database.\n\nIf you're tired of writing raw SQL for querying AWS DynamoDB NoSQL database with complex filters, then this package is for you, too.\n\n## 🧠 Why Dynamo-Query over `@aws-sdk/client-dynamodb`?\n\n- ✅ Type-safe advanced filtering\n- 💪 Build-in SQL query-builder\n- 🚀 Dynamic, type-safe field-selection - maximizing performance\n- 🍃 No more hard-coding SQL queries, just bring your models\n\n## 🚶‍♂️ How to get started?\n\nInstall this package\n\n```shell\nnpm install dynamo-query\nyarn install dynamo-query\npnpm install dynamo-query\n```\n\nInstantiate the client\n\n```typescript\nimport { createClient } from 'dynamo-query';\n\ntype User = {\n  id: string;\n  firstName: string;\n  lastName: string;\n  age: number;\n  createdAt: Date;\n  isSuperAdmin: boolean;\n};\n\ntype Post = {\n  id: string;\n  title: string;\n  content: string;\n  createdBy: string; // foreign key - User.id\n};\n\n// Example 1 - Using connection string\nconst orm = createClient({\n  region: 'us-east-1', // AWS region\n  credentials: {\n    accessKeyId: '\u003cAWS_ACCESS_KEY_ID\u003e',\n    secretAccessKey: '\u003cAWS_SECRET_ACCESS_KEY\u003e',\n  },\n  models: t =\u003e ({\n    user: t.createModel\u003cUser\u003e({\n      tableName: 'Users',\n      partitionKey: 'userId',\n      options: { fields: ['name', 'email', 'createdAt'] },\n    }),\n    post: t.createModel\u003cPost\u003e({\n      tableName: 'Posts',\n      partitionKey: 'postId',\n      sortKey: 'createdAt',\n      options: { fields: ['title', 'content', 'authorId'] },\n    }),\n  }),\n});\n\n// Example 2 - Using custom endpoint (useful for local development/testing)\nconst orm = createClient({\n  region: 'us-east-1',\n  endpoint: 'http://localhost:8000', // Custom endpoint for local DynamoDB\n  credentials: {\n    accessKeyId: 'fakeMyKeyId',\n    secretAccessKey: 'fakeSecretAccessKey',\n  },\n  models: t =\u003e ({\n    user: t.createModel\u003cUser\u003e({\n      tableName: 'Users',\n      partitionKey: 'userId',\n      options: { fields: ['name', 'email', 'createdAt'] },\n    }),\n    post: t.createModel\u003cPost\u003e({\n      tableName: 'Posts',\n      partitionKey: 'postId',\n      sortKey: 'createdAt',\n      options: { fields: ['title', 'content', 'authorId'] },\n    }),\n  }),\n});\n\n// Example 3 - With additional model options\nconst orm = createClient({\n  region: 'us-east-1',\n  credentials: {\n    accessKeyId: '\u003cAWS_ACCESS_KEY_ID\u003e',\n    secretAccessKey: '\u003cAWS_SECRET_ACCESS_KEY\u003e',\n  },\n  models: t =\u003e ({\n    user: t.createModel\u003cUser\u003e({\n      tableName: '\u003cUSER_TABLE_NAME\u003e',\n      partitionKey: 'id',\n      options: {\n        fields: {\n          id: true, // Auto-generate IDs\n          timestamp: true, // Auto-generate createdAt/updatedAt\n        },\n      },\n    }),\n    post: t.createModel\u003cPost\u003e({\n      tableName: '\u003cPOST_TABLE_NAME\u003e',\n      partitionKey: 'id',\n      sortKey: 'createdAt',\n      options: {\n        fields: false, // Disable auto-generated fields\n      },\n    }),\n  }),\n});\n\n// Notes:\n// - The 'partitionKey' is required and must match an attribute in your table\n// - The 'sortKey' is optional and enables range queries when specified\n// - Tables must be created beforehand with matching partition/sort keys\n```\n\nMake queries with simple filters\n\n```typescript\nconst getFilteredUsers = async () =\u003e {\n  return await orm.user.findMany({\n    where: { firstName: { contains: 'Sam' } },\n  });\n};\n\nconst getFilteredUsers = async () =\u003e {\n  return await orm.user.findMany({\n    where: { age: { gte: 18 } },\n  });\n};\n\nconst getFilteredUsers = async () =\u003e {\n  return await orm.user.findMany({\n    where: { createdAt: { gte: new Date('2024-01-01') } },\n  });\n};\n\nconst getFilteredposts = async () =\u003e {\n  return await orm.post.findMany({\n    where: { createdBy: { equals: '\u003cSOME_USER_ID\u003e' } },\n  });\n};\n```\n\nMake a query without any filters\n\n```typescript\n// This will return maximum of 100 items by default\nconst result = orm.user.findMany({});\n```\n\nOr, make a query by applying some complex filters, field-selections, and pagination logic:\n\n```typescript\nconst getFilteredUsers = async () =\u003e {\n  return await orm.user.findMany({\n    where: {\n      firstName: {\n        startsWith: 'Sa',\n        endsWith: 'lyn',\n        mode: 'INSENSITIVE',\n      },\n      age: {\n        lte: 20,\n        gte: 10,\n        not: 15,\n      },\n      isSuperAdmin: {\n        not: true,\n      },\n      createdAt: {\n        lte: new Date('2024-12-31'),\n        gte: new Date('2024-12-01'),\n        not: new Date('2024-12-15'),\n      },\n    },\n    orderBy: {\n      firstName: 'ASC',\n    },\n    take: 10,\n    select: {\n      id: true,\n      firstName: true,\n      age: true,\n    },\n    nextCursor: '\u003cPAGINATION_TOKEN\u003e',\n  });\n};\n```\n\nFind an item by ID\n\n```typescript\n// without field-selection\nconst result = orm.user.findOne({\n  where: { id: 'USER_ID' },\n});\n\n// with field-selection\nconst result = orm.user.findOne\u003cUser\u003e({\n  where: { id: 'USER_ID' },\n  select: { id: true, firstName: true },\n});\n```\n\nCreate an item\n\n```typescript\ntype CreateUserInput = Partial\u003cUser\u003e;\n\nconst result = orm.user.create\u003cCreateUserInput\u003e({\n  data: {\n    firstName: '\u003cFIRST_NAME\u003e',\n    lastName: '\u003cLAST_NAME\u003e',\n  },\n});\n```\n\nUpdate an item\n\n```typescript\ntype UpdateUserInput = Partial\u003cUser\u003e;\n\nconst result = orm.user.update\u003cUpdateUserInput\u003e({\n  where: { id: '\u003cUSER_ID\u003e' },\n  data: {\n    firstName: '\u003cUPDATED_FIRST_NAME\u003e',\n  },\n});\n```\n\nDelete an item\n\n```typescript\nconst result = orm.user.delete({\n  where: { id: '\u003cUSER_ID\u003e' },\n});\n```\n\n## 📝 Roadmap\n\n- Core Query builder\n- Comprehensive unit/e2e test coverage\n- Bulk create / update operations\n- Observability - query logging\n- Filtering on more complex data types such as enums, enum arrays, string arrays \u0026 number arrays\n\n## Contributing\n\nWe welcome contributions from the community! If you're interested in contributing to this project, please read the [CONTRIBUTING.md](./CONTRIBUTING.md) file to get started.\n\n## Disclaimer\n\nThis project is a fork of [Mingyang-Li/cosmox](https://github.com/Mingyang-Li/cosmox) (credit to [@Mingyang-Li](https://github.com/Mingyang-Li)), inspired by Prisma, and is not an\nofficial AWS product. Provided \"as is\" without warranty.\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspencerlepine%2Fdynamo-query","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspencerlepine%2Fdynamo-query","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspencerlepine%2Fdynamo-query/lists"}