{"_id":"@aaxis/azure-database","_rev":"1-e58b0bc8d5fa6a0174846318684acbde","name":"@aaxis/azure-database","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.3":{"name":"@aaxis/azure-database","version":"1.0.3","description":"The Azure Table Storage module for Nest framework (node.js)","author":{"name":"Derek Hu","email":"derekhu@aaxiscommerce.com"},"main":"./dist/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/nestjs/azure-database.git"},"scripts":{"test":"jest --passWithNoTests","precommit":"lint-staged","prettier":"prettier src/**/*.ts --write && git status","build":"rimraf dist && npm run build:lib","build:lib":"tsc -p tsconfig.json","prepare":"npm run build","prepublish:npm":"npm run build","publish:npm":"npm publish --access public","prepublish:next":"npm run build","publish:next":"npm publish --access public --tag next"},"peerDependencies":{"@nestjs/common":"^7.0.0","@nestjs/core":"^7.0.0"},"dependencies":{"@azure/cosmos":"^3.4.2","@azure/ms-rest-js":"^2.0.4","@nestjs/common":"^7.0.0","@nestjs/core":"^7.0.0","axios":"^0.19.2","azure-storage":"^2.10.3","lokijs":"^1.5.8"},"devDependencies":{"@nestjs/testing":"7.0.13","@types/jest":"25.2.3","@types/node":"11.13.21","dotenv":"^8.1.0","husky":"4.2.5","jest":"26.0.1","lint-staged":"10.2.4","prettier":"2.0.5","reflect-metadata":"^0.1.13","rimraf":"^3.0.0","supertest":"4.0.2","ts-jest":"26.0.0","tslint":"6.1.2","typescript":"3.9.3"},"lint-staged":{"*.ts":["prettier --write","git add"]},"husky":{"hooks":{"pre-commit":"lint-staged"}},"gitHead":"d74dd135c6e2725da9b5b4c224ffdb5ea0882387","bugs":{"url":"https://github.com/nestjs/azure-database/issues"},"homepage":"https://github.com/nestjs/azure-database#readme","_id":"@aaxis/azure-database@1.0.3","_nodeVersion":"10.20.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-cESxo7bsr10Y7v59/iu6+McnGOs6EpUwOVXp0xSKWlyIZDrihMWkUaoOgbnV5xZBaE9ZJT5nPDLhaGxxwJ9Y7Q==","shasum":"195950e65ab3979f15ddfe0c5bc3f9bdc7d21fac","tarball":"https://registry.npmjs.org/@aaxis/azure-database/-/azure-database-1.0.3.tgz","fileCount":62,"unpackedSize":143099,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6JcbCRA9TVsSAnZWagAAAUIQAJwzXrGNtygojD7u6SK3\n3SEJbTvfmhOZznswopgxvnfcP8YxPc7wW/PGyiRh2rMmh4GrAMV/VeMky1Ng\nbi3Mir/GXM4qv/07PXNEueBCQogxPxSxtRsbPVZDAfEKwA2NqENGp3YXWsAl\nEIMXRegTzGdf2OWaywO/Kb1kg7pMEDOqWMFxpYwV6YFm6TEgPGgRELDgMzyq\n0ZFmwzmNP49pMHNR1NYpGha+Q02N97E8HbWiQNvvUwno+b36Z9gySpUy8jXp\nPjcmu/5tJD+1Zx6PJPTO0u3ljr7VeJAOM6Mbkeri71qdmhPjlWcqAvbBK8zv\nB5HajZ4EQshKu/vQkZgEXaNoNiWe+iCoPqDu7HKc9ndWlu/Dei04LDN06P8Z\nNtZ+qKgGBT68obP2uA9G/gIyNfd017rzHcn6HNdUwfGIpr9TxazflkuAbJud\nRIlGSGVU7+grqlzNM/F01+jc2pHsMJpytoOIf6P1Ah2wZ0LzrIyl0CZLl8tZ\nBt2VpdIRQ3iYTVNLJhGb0NhOd6FHLwJVaMws8iHeyHrIf8n8KfQvsv0vqaSC\nQJkeYQYWwXg4xRluClg4+tyBjyQzavKFSs03XNFbElJiZdtoDdsm2qs8MEn6\neqegawnAFoWs0b1BlyRpJHKshBQsUng2HF2s17GIT97mUmhIxHHRbnUlPUDz\nXwKe\r\n=5vGz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDVR4SXbAKpo/7FzB+8941MhvP6QrvNdVISNUvjmlnUoAIhAOPn8yxuP2TP1868erstaXn8c/4joeetq7tssAVuYrJU"}]},"maintainers":[{"name":"aaxis","email":"zacharyhou@aaxiscommerce.com"}],"_npmUser":{"name":"aaxis","email":"zacharyhou@aaxiscommerce.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/azure-database_1.0.3_1592301339185_0.5922350471823514"},"_hasShrinkwrap":false}},"time":{"created":"2020-06-16T09:55:39.128Z","1.0.3":"2020-06-16T09:55:39.326Z","modified":"2022-04-04T10:56:26.934Z"},"maintainers":[{"name":"aaxis","email":"zacharyhou@aaxiscommerce.com"}],"description":"The Azure Table Storage module for Nest framework (node.js)","homepage":"https://github.com/nestjs/azure-database#readme","repository":{"type":"git","url":"git+https://github.com/nestjs/azure-database.git"},"author":{"name":"Derek Hu","email":"derekhu@aaxiscommerce.com"},"bugs":{"url":"https://github.com/nestjs/azure-database/issues"},"license":"MIT","readme":"<p align=\"center\">\n  <a href=\"http://nestjs.com/\" target=\"blank\"><img src=\"https://nestjs.com/img/logo_text.svg\" width=\"320\" alt=\"Nest Logo\" /></a>\n</p>\n\n[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master\n[travis-url]: https://travis-ci.org/nestjs/nest\n[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux\n[linux-url]: https://travis-ci.org/nestjs/nest\n\n  <p align=\"center\">A progressive <a href=\"http://nodejs.org\" target=\"blank\">Node.js</a> framework for building efficient and scalable server-side applications.</p>\n    <p align=\"center\">\n<a href=\"https://www.npmjs.com/~nestjscore\"><img src=\"https://img.shields.io/npm/v/@nestjs/core.svg\" alt=\"NPM Version\" /></a>\n<a href=\"https://www.npmjs.com/~nestjscore\"><img src=\"https://img.shields.io/npm/l/@nestjs/core.svg\" alt=\"Package License\" /></a>\n<a href=\"https://www.npmjs.com/~nestjscore\"><img src=\"https://img.shields.io/npm/dm/@nestjs/core.svg\" alt=\"NPM Downloads\" /></a>\n<a href=\"https://travis-ci.org/nestjs/nest\"><img src=\"https://api.travis-ci.org/nestjs/nest.svg?branch=master\" alt=\"Travis\" /></a>\n<a href=\"https://travis-ci.org/nestjs/nest\"><img src=\"https://img.shields.io/travis/nestjs/nest/master.svg?label=linux\" alt=\"Linux\" /></a>\n<a href=\"https://coveralls.io/github/nestjs/nest?branch=master\"><img src=\"https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#5\" alt=\"Coverage\" /></a>\n<a href=\"https://gitter.im/nestjs/nestjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge\"><img src=\"https://badges.gitter.im/nestjs/nestjs.svg\" alt=\"Gitter\" /></a>\n<a href=\"https://opencollective.com/nest#backer\"><img src=\"https://opencollective.com/nest/backers/badge.svg\" alt=\"Backers on Open Collective\" /></a>\n<a href=\"https://opencollective.com/nest#sponsor\"><img src=\"https://opencollective.com/nest/sponsors/badge.svg\" alt=\"Sponsors on Open Collective\" /></a>\n  <a href=\"https://paypal.me/kamilmysliwiec\"><img src=\"https://img.shields.io/badge/Donate-PayPal-dc3d53.svg\"/></a>\n  <a href=\"https://twitter.com/nestframework\"><img src=\"https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow\"></a>\n</p>\n  <!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)\n  [![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->\n\n## Description\n\nAzure Database ([Table Storage](http://bit.ly/nest_azure-storage-table), [Cosmos DB](https://azure.microsoft.com/en-us/services/cosmos-db/) and more) module for [Nest](https://github.com/nestjs/nest) framework (node.js)\n\n## Tutorial\n\nLearn how to get started with [Azure table storage for NestJS](https://trilon.io/blog/nestjs-nosql-azure-table-storage)\n\n## Before Installation\n\nFor Table Storage\n\n1. Create a Storage account and resource ([read more](http://bit.ly/nest_new-azure-storage-account))\n1. For [Table Storage](http://bit.ly/nest_azure-storage-table), In the [Azure Portal](https://portal.azure.com), go to **Dashboard > Storage > _your-storage-account_**.\n1. Note down the \"Storage account name\" and \"Connection string\" obtained at **Access keys** under **Settings** tab.\n\nFor Cosmos DB\n\n1. Create a Cosmos DB account and resource ([read more](https://azure.microsoft.com/en-us/services/cosmos-db/))\n1. For [Cosmos DB](http://bit.ly/nest_azure-storage-table), In the [Azure Portal](https://portal.azure.com), go to **Dashboard > Azure Cosmos DB > _your-cosmos-db-account_**.\n1. Note down the \"URI\" and \"Primary Key\" obtained at **Keys** under **Settings** tab.\n\n## Installation\n\n```bash\n$ npm i --save @nestjs/azure-database\n```\n\n## Usage\n\n### For Azure Table Storage support\n\n1. Create or update your existing `.env` file with the following content:\n\n```\nAZURE_STORAGE_CONNECTION_STRING=\n```\n\n2. **IMPORTANT: Make sure to add your `.env` file to your .gitignore! The `.env` file MUST NOT be versioned on Git.**\n\n3. Make sure to include the following call to your main file:\n\n```typescript\nif (process.env.NODE_ENV !== 'production') require('dotenv').config();\n```\n\n> This line must be added before any other imports!\n\n### Example\n\n#### Prepare your entity\n\n0. Create a new feature module, eg. with the nest CLI:\n\n```shell\n$ nest generate module contact\n```\n\n1. Create a Data Transfer Object (DTO) inside a file named `contact.dto.ts`:\n\n```typescript\nexport class ContactDTO {\n  name: string;\n  message: string;\n}\n```\n\n2. Create a file called `contact.entity.ts` and describe the entity model using the provided decorators:\n\n- `@EntityPartitionKey(value: string)`: Represents the `PartitionKey` of the entity (**required**).\n\n- `@EntityRowKey(value: string)`: Represents the `RowKey` of the entity (**required**).\n\n- `@EntityInt32(value?: string)`: For signed 32-bit integer values.\n\n- `@EntityInt64(value?: string)`: For signed 64-bit integer values.\n\n- `@EntityBinary(value?: string)`: For binary (blob) data.\n\n- `@EntityBoolean(value?: string)`: For `true` or `false` values.\n\n- `@EntityString(value?: string)`: For character data.\n\n- `@EntityDouble(value?: string)`: For floating point numbers with 15 digit precision.\n\n- `@EntityDateTime(value?: string)`: For time of day.\n\nFor instance, the shape of the following entity:\n\n```typescript\nimport { EntityPartitionKey, EntityRowKey, EntityString } from '@nestjs/azure-database';\n\n@EntityPartitionKey('ContactID')\n@EntityRowKey('ContactName')\nexport class Contact {\n  @EntityString() name: string;\n  @EntityString() message: string;\n}\n```\n\nWill be automatically converted to:\n\n```json\n{\n  \"PartitionKey\": { \"_\": \"ContactID\", \"$\": \"Edm.String\" },\n  \"RowKey\": { \"_\": \"ContactName\", \"$\": \"Edm.String\" },\n  \"name\": { \"_\": undefined, \"$\": \"Edm.String\" },\n  \"message\": { \"_\": undefined, \"$\": \"Edm.String\" }\n}\n```\n\n> Note: The provided entity type annotations represent the [Entity Data Model][edm-types] types.\n\n3. Import the `AzureTableStorageModule` inside your Nest feature module `contact.module.ts`:\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { AzureTableStorageModule } from '@nestjs/azure-database';\nimport { ContactController } from './contact.controller';\nimport { ContactService } from './contact.service';\nimport { Contact } from './contact.entity';\n\n@Module({\n  imports: [AzureTableStorageModule.forFeature(Contact)],\n  providers: [ContactService],\n  controllers: [ContactController],\n})\nexport class ContactModule {}\n```\n\nYou can optionally pass in the following arguments:\n\n```typescript\nAzureTableStorageModule.forFeature(Contact, {\n  table: 'AnotherTableName',\n  createTableIfNotExists: true,\n});\n```\n\n- `table: string`: The name of the table. If not provided, the name of the `Contact` entity will be used as a table name\n- `createTableIfNotExists: boolean`: Whether to automatically create the table if it doesn't exists or not:\n  - If `true` the table will be created during the startup of the app.\n  - If `false` the table will not be created. **You will have to create the table by yourself before querying it!**\n\n#### CRUD operations\n\n0. Create a service that will abstract the CRUD operations:\n\n```shell\n$ nest generate service contact\n```\n\n1. Use the `@InjectRepository(Contact)` to get an instance of the Azure `Repository` for the entity definition created earlier:\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { Repository, InjectRepository } from '@nestjs/azure-database';\nimport { Contact } from './contact.entity';\n\n@Injectable()\nexport class ContactService {\n  constructor(\n    @InjectRepository(Contact)\n    private readonly contactRepository: Repository<Contact>,\n  ) {}\n}\n```\n\nThe `AzureTableStorageRepository` provides a couple of public APIs and Interfaces for managing various CRUD operations:\n\n##### CREATE\n\n`create(entity: T, rowKeyValue?: string): Promise<T>`: creates a new entity.\n\n```typescript\n\n  @Post()\n  async create(contact: Contact, rowKeyValue: string): Promise<Contact> {\n    //if rowKeyValue is null, rowKeyValue will generate a UUID\n    return this.contactRepository.create(contact, rowKeyValue)\n  }\n```\n\n##### READ\n\n`find(rowKey: string, entity: Partial<T>): Promise<T>`: finds one entity using its `RowKey`.\n\n```typescript\n  @Get(':rowKey')\n  async getContact(@Param('rowKey') rowKey) {\n    try {\n      return await this.contactRepository.find(rowKey, new Contact());\n    } catch (error) {\n      // Entity not found\n      throw new UnprocessableEntityException(error);\n    }\n  }\n```\n\n`findAll(tableQuery?: azure.TableQuery, currentToken?: azure.TableService.TableContinuationToken): Promise<AzureTableStorageResultList<T>>`: finds all entities that match the given query (return all entities if no query provided).\n\n```typescript\n  @Get()\n  async getAllContacts() {\n    return await this.contactRepository.findAll();\n  }\n```\n\n##### UPDATE\n\n`update(rowKey: string, entity: Partial<T>): Promise<T>`: Updates an entity. It does a partial update.\n\n```typescript\n  @Put(':rowKey')\n  async saveContact(@Param('rowKey') rowKey, @Body() contactData: ContactDTO) {\n    try {\n      const contactEntity = new Contact();\n      // Disclaimer: Assign only the properties you are expecting!\n      Object.assign(contactEntity, contactData);\n\n      return await this.contactRepository.update(rowKey, contactEntity);\n    } catch (error) {\n      throw new UnprocessableEntityException(error);\n    }\n  }\n  @Patch(':rowKey')\n  async updateContactDetails(@Param('rowKey') rowKey, @Body() contactData: Partial<ContactDTO>) {\n    try {\n      const contactEntity = new Contact();\n      // Disclaimer: Assign only the properties you are expecting!\n      Object.assign(contactEntity, contactData);\n\n      return await this.contactRepository.update(rowKey, contactEntity);\n    } catch (error) {\n      throw new UnprocessableEntityException(error);\n    }\n  }\n```\n\n##### DELETE\n\n`delete(rowKey: string, entity: T): Promise<AzureTableStorageResponse>`: Removes an entity from the database.\n\n```typescript\n\n  @Delete(':rowKey')\n  async deleteDelete(@Param('rowKey') rowKey) {\n    try {\n      const response = await this.contactRepository.delete(rowKey, new Contact());\n\n      if (response.statusCode === 204) {\n        return null;\n      } else {\n        throw new UnprocessableEntityException(response);\n      }\n    } catch (error) {\n      throw new UnprocessableEntityException(error);\n    }\n  }\n```\n\n### For Azure Cosmos DB support\n\n1. Create or update your existing `.env` file with the following content:\n\n```\nAZURE_COSMOS_DB_NAME=\nAZURE_COSMOS_DB_ENDPOINT=\nAZURE_COSMOS_DB_KEY=\n```\n\n2. **IMPORTANT: Make sure to add your `.env` file to your .gitignore! The `.env` file MUST NOT be versioned on Git.**\n\n3. Make sure to include the following call to your main file:\n\n```typescript\nif (process.env.NODE_ENV !== 'production') require('dotenv').config();\n```\n\n> This line must be added before any other imports!\n\n### Example\n\n> Note: Check out the CosmosDB example project included in the [sample folder](https://github.com/nestjs/azure-database/tree/master/sample/cosmos-db)\n\n#### Prepare your entity\n\n0. Create a new feature module, eg. with the nest CLI:\n\n```shell\n$ nest generate module event\n```\n\n1. Create a Data Transfer Object (DTO) inside a file named `event.dto.ts`:\n\n```typescript\nexport class EventDTO {\n  name: string;\n  type: string;\n  date: Date;\n  location: Point;\n}\n```\n\n2. Create a file called `event.entity.ts` and describe the entity model using the provided decorators:\n\n- `@CosmosPartitionKey(value: string)`: Represents the `PartitionKey` of the entity (**required**).\n\n- `@CosmosDateTime(value?: string)`: For DateTime values.\n\nFor instance, the shape of the following entity:\n\n```typescript\nimport { CosmosPartitionKey, CosmosDateTime, Point } from '@nestjs/azure-database';\n\n@CosmosPartitionKey('type')\nexport class Event {\n  id?: string;\n  type: string;\n  @CosmosDateTime() createdAt: Date;\n  location: Point;\n}\n```\n\nWill be automatically converted to:\n\n```json\n{\n  \"type\": \"Meetup\",\n  \"createdAt\": \"2019-11-15T17:05:25.427Z\",\n  \"position\": {\n    \"type\": \"Point\",\n    \"coordinates\": [2.3522, 48.8566]\n  }\n}\n```\n\n3. Import the `AzureCosmosDbModule` inside your Nest feature module `event.module.ts`:\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { AzureCosmosDbModule } from '@nestjs/azure-database';\nimport { EventController } from './event.controller';\nimport { EventService } from './event.service';\nimport { Event } from './event.entity';\n\n@Module({\n  imports: [\n    AzureCosmosDbModule.forRoot({\n      dbName: process.env.AZURE_COSMOS_DB_NAME,\n      endpoint: process.env.AZURE_COSMOS_DB_ENDPOINT,\n      key: process.env.AZURE_COSMOS_DB_KEY,\n    }),\n    AzureCosmosDbModule.forFeature([{ dto: Event }]),\n  ],\n  providers: [EventService],\n  controllers: [EventController],\n})\nexport class EventModule {}\n```\n\n#### CRUD operations\n\n0. Create a service that will abstract the CRUD operations:\n\n```shell\n$ nest generate service event\n```\n\n1. Use the `@InjectModel(Event)` to get an instance of the Azure Cosmos DB [Container](https://docs.microsoft.com/en-us/javascript/api/@azure/cosmos/container) for the entity definition created earlier:\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { InjectModel } from '@nestjs/azure-database';\nimport { Event } from './event.entity';\n\n@Injectable()\nexport class EventService {\n  constructor(\n    @InjectModel(Event)\n    private readonly eventContainer,\n  ) {}\n}\n```\n\nThe Azure Cosmos DB `Container` provides a couple of public APIs and Interfaces for managing various CRUD operations:\n\n##### CREATE\n\n`create(entity: T): Promise<T>`: creates a new entity.\n\n```typescript\n\n  @Post()\n  async create(event: Event): Promise<Event> {\n      return this.eventContainer.items.create(event)\n  }\n\n```\n\n##### READ\n\n`query<T>(query: string | SqlQuerySpec, options?: FeedOptions): QueryIterator<T>`: run a SQL Query to find a document.\n\n```typescript\n  @Get(':id')\n  async getContact(@Param('id') id) {\n    try {\n       const querySpec = {\n           query: \"SELECT * FROM root r WHERE r.id=@id\",\n           parameters: [\n             {\n               name: \"@id\",\n               value: id\n             }\n           ]\n         };\n        const { resources } = await this.eventContainer.items.query<Event>(querySpec).fetchAll()\n         return resources\n    } catch (error) {\n      // Entity not found\n      throw new UnprocessableEntityException(error);\n    }\n  }\n```\n\n##### UPDATE\n\n`read<T>(options?: RequestOptions): Promise<ItemResponse<T>>`: Get a document.\n`replace<T>(body: T, options?: RequestOptions): Promise<ItemResponse<T>>`: Updates a document.\n\n```typescript\n  @Put(':id')\n  async saveEvent(@Param('id') id, @Body() eventData: EventDTO) {\n    try {\n      const { resource: item } = await this.eventContainer.item<Event>(id, 'type').read()\n\n      // Disclaimer: Assign only the properties you are expecting!\n      Object.assign(item, eventData);\n\n      const { resource: replaced } = await this.eventContainer\n       .item(id, 'type')\n       .replace<Event>(item)\n      return replaced\n    } catch (error) {\n      throw new UnprocessableEntityException(error);\n    }\n  }\n```\n\n##### DELETE\n\n`delete<T>(options?: RequestOptions): Promise<ItemResponse<T>>`: Removes an entity from the database.\n\n```typescript\n\n  @Delete(':id')\n  async deleteEvent(@Param('id') id) {\n    try {\n      const { resource: deleted } = await this.eventContainer\n       .item(id, 'type')\n       .delete<Event>()\n\n      return deleted;\n    } catch (error) {\n      throw new UnprocessableEntityException(error);\n    }\n  }\n```\n\n## Support\n\nNest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).\n\n## Stay in touch\n\n- Author - [Wassim Chegham](https://wassim.dev)\n- Website - [https://wassim.dev](https://wassim.dev/)\n- Twitter - [@manekinekko](https://twitter.com/manekinekko)\n\n## License\n\nNest is [MIT licensed](LICENSE).\n\n[edm-types]: http://bit.ly/nest-edm\n","readmeFilename":"README.md"}