{"_id":"@arcticleaf/aws-util-dynamodb","_rev":"50-18b679e11be237edf864945fef304951","name":"@arcticleaf/aws-util-dynamodb","dist-tags":{"alpha":"2.0.0-alpha.34","beta":"2.0.0-beta.1","production":"2.0.0","latest":"1.2.12"},"versions":{"1.2.5":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.5","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.5","maintainers":[{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://git.arcticleaf.io/modules/aws-util-dynamodb#readme","bugs":{"url":"https://git.arcticleaf.io/modules/aws-util-dynamodb/issues"},"dist":{"shasum":"5bb2f3edb456e1c4d81e596773c7fa27787077e3","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.5.tgz","fileCount":20,"integrity":"sha512-A3I5sRh+l0gSYvvhNpZBGj0QPR8tIVZKQm7ccQv70bGLuSgj1E/NAsX9AejhWLguIcPv7adtD+Z0erwKp8ba2Q==","signatures":[{"sig":"MEQCIG6jPrSxKwsO8PF787C8zqURvJweN1Edrp/4ar7JoOoFAiBuRpKZzNcBY+IYbYMI0vkk86IMy5A//ecBD3ovv2J2Xg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":142562},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"56adb3a0c80a5ef43840aa5f3c98589f409452ab","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo \"Error: no test specified\" && exit 1","build":"tsc","monitor":"tsc --watch","lint-fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://git.arcticleaf.io/modules/aws-util-dynamodb.git","type":"git"},"_npmVersion":"7.24.2","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"14.17.5","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.3.3","@aws-sdk/util-dynamodb":"^3.39.0","@aws-sdk/client-dynamodb":"^3.39.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.32.0","typescript":"^4.4.4","semantic-release":"^17.4.7","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.25.2","@semantic-release/git":"^9.0.1","@semantic-release/npm":"^7.1.3","eslint-config-loopback":"^13.1.0","@semantic-release/gitlab":"^6.2.2","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.0","@typescript-eslint/eslint-plugin":"^4.33.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.5_1635548719024_0.21123118935912988","host":"s3://npm-registry-packages"}},"1.2.6":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.6","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.6","maintainers":[{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://git.arcticleaf.io/modules/aws-util-dynamodb#readme","bugs":{"url":"https://git.arcticleaf.io/modules/aws-util-dynamodb/issues"},"dist":{"shasum":"17ef8f1331e0b54aa724b856a0bd07e9fefcb9b3","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.6.tgz","fileCount":20,"integrity":"sha512-nXV75dpKbZhux9+xlpnPS/ELaB2ObmHDBLD5hbnl9qPJrtwSMI0W1f6BL6Uuajr2qtlWHONN2hEbTMu5iQbX0w==","signatures":[{"sig":"MEUCIQD2JrmzH6Dli9ubs66Jk0oJNViZLx4KAihpKLcbkoOT8AIgce5ex1kNzAJvhrqOrHg3lbHRsZ/QqP9M+3ssQWv7Lq8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":140082,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJht7BACRA9TVsSAnZWagAA/QAQAJiickLJJnXx5G1bBdvC\ngTSiY06c5Y3uTbe4sJLBJWU5g5u5wOC1KJs9QeaiOS4o4WVqWg0iKkXgNYm4\nreVIrQl3tpi7ceHiNU7EvPQBpBsRXXVLyPeQtsU8qiW1KI3PZeQCa+6mFwV0\nX4hsuszYOCt7VK/sfK4J6T7/PV8Vek6cxMfiCtl+fk8d+Uznz2sPN5C34kRg\nJSmM+3q5AFViYEWeL0JQv5B693UUDRC/0P3SgtTIXtEutlvL5w8DB90wallY\nRs14iZoK13X5pskuCPTi0AxKzuPmroa/jx+xS6wTsi50LerAsWSx+dxwtFWu\n2XcdjNUScs5CEjX9edOO++meVmoDZ7wCPzmlfJ74FOOt0H3/Nr2EOWZhgHZL\nUeNneL0VIgNd/BoTr1e1TXekFcoMIHcclhq1yV9theVMRqLXwFZGwlGruyjr\ntcyOvGQmnYu5DjNvAgoPauZCkSTU+fE2On9xHVc7E/UOcLp+SwZjXbdQ5ivM\nKS27FA4bSVfVR8QlbFeumgFY0byDDkRKYfx/cQ+2K0sdNLhmjhNEzW8BZZDW\nqsvXnjXTNc9OzjE5EkDVkbWJR70yPiS5UB6pIQVRhn+PJ5ZfWMD347cd5vhc\nN76CAwHD/Zc3/UM+p5vPH1yOZ0nXsHf4cUeHMRdqJWEzqTFNwu1rJ+C0djX5\no3sa\r\n=AdU6\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"3da641ec9772f6189eac2bde3a9400c9f4dbc23e","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo \"Error: no test specified\" && exit 1","build":"tsc","monitor":"tsc --watch","lint-fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://git.arcticleaf.io/modules/aws-util-dynamodb.git","type":"git"},"_npmVersion":"7.24.2","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"14.17.5","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.3.4","@aws-sdk/util-dynamodb":"^3.44.0","@aws-sdk/client-dynamodb":"^3.44.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.32.0","typescript":"^4.5.3","semantic-release":"^17.4.7","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.25.3","@semantic-release/git":"^9.0.1","@semantic-release/npm":"^7.1.3","eslint-config-loopback":"^13.1.0","@semantic-release/gitlab":"^6.2.2","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.1","@typescript-eslint/eslint-plugin":"^4.33.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.6_1639428160774_0.9431975231547722","host":"s3://npm-registry-packages"}},"1.2.7":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.7","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.7","maintainers":[{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://git.arcticleaf.io/modules/aws-util-dynamodb#readme","bugs":{"url":"https://git.arcticleaf.io/modules/aws-util-dynamodb/issues"},"dist":{"shasum":"520ebc5ca5a2bac432bfa0dd719e48a6105d6e19","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.7.tgz","fileCount":20,"integrity":"sha512-geui/bbBJ3IY7TB/Py+EweLwYSNnOxtW/GUr5axKsN/+hzLe3T0OZOZfUiuPYAeyQQ/BXroew8f+5b0CWQXTkw==","signatures":[{"sig":"MEUCIEennA+QHmXZoOC2q8CoA/B92ZEvMAE8O8jkXR24ZglaAiEAvzV2DetxF60A/j73Ylr0DaRN2wucE10Gl/w8TiZITp0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":134758,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhw0WmCRA9TVsSAnZWagAA1lMP/2cushGLOvlmD8nffSCq\nym/LYpAg7a18WPwum8XKu5jLnaoFaDPohdYPRvjKBf1abhah7fESNg0Aemr6\nIAlICVIk/gZmvLRVbEUDsAD0VBbn9DzKWrfvMwUkOV9WZitX/euI14NGPHJ2\nuk53wxcaq9aRl3nYD0LrBx67U99hnkR1oxBUfskFYIRg2xOPocqaJE3xImAH\nuJD8RVjBdHoLWSrepIGglRFFk2T6ngCD2QR6asVLf2LC0avFV8jlaJF36JHb\nOjVFRWty55oFxGvnLEwHv0j//ORYzpAtr8QCk43kbYzUWOCuaEnFo9qm2Tl7\nVxCavMWWZrjB/6hLXxQeNAQvjcnVrYOGw+kQhLJIg0jj+pHTydAvJmwfaUtO\nF8OLQ2Qgy8RET7NxjY78Td5kixwEPbgXMNtLWDTf8af4IVaOhQxaFB+q/3Sn\nrdFqygNVHZyW03nPaYBFtXMt+mD9ZB/n0ihw3UbvqhYE4DLZ9xBUZnbiJ6hL\nP05jM5ckiSgELXQ3ELlGu6KTkUZVsdYjNOL5plCcaZzOyXTxEK12t4t4m1Eq\nBWIfDhymPM4/OfGAyHUVkydAG1nc4C+8owym54W3UJUKA8c9PYNc84J68q4z\nh+BjmGj3qTqbatpJ98XHqhKZfH2TS9u11zJ8lZKhuMaqRZphemhhheHhlYpi\nIAYz\r\n=EqhL\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"0fc302e34027c14bacdd09b0568ae8329ab775e8","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo \"Error: no test specified\" && exit 1","build":"tsc","monitor":"tsc --watch","lint-fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://git.arcticleaf.io/modules/aws-util-dynamodb.git","type":"git"},"_npmVersion":"7.24.2","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"14.17.5","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.3.4","@aws-sdk/util-dynamodb":"^3.44.0","@aws-sdk/client-dynamodb":"^3.44.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.32.0","typescript":"^4.5.3","semantic-release":"^17.4.7","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.25.3","@semantic-release/git":"^9.0.1","@semantic-release/npm":"^7.1.3","eslint-config-loopback":"^13.1.0","@semantic-release/gitlab":"^6.2.2","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.1","@typescript-eslint/eslint-plugin":"^4.33.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.7_1640187302263_0.10193378557699706","host":"s3://npm-registry-packages"}},"1.2.8":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.8","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.8","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://git.arcticleaf.io/modules/aws-util-dynamodb#readme","bugs":{"url":"https://git.arcticleaf.io/modules/aws-util-dynamodb/issues"},"dist":{"shasum":"02639f10cb14e4238cab720e30ab623e6c00c918","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.8.tgz","fileCount":20,"integrity":"sha512-EJtrzlaGwOBW1n5pTRHc8Q+D3FU5crnzX/mxu2YUyUO78IkdqSmVRloF6Vb1BP9wdUaEnD9qtfhhikr99D+eaQ==","signatures":[{"sig":"MEYCIQDHazyTcI5Of+272dC/z4U6BCh28IpnC5S6U6LpUUPvFQIhAJ7Gz1jO411MwewKm8CW2LPLR6Lqoh5aNxCs1j8Lkis0","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":135762,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJifGJfACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqlnw/9GCxdQutg9GlLuNdWHdpn8srJvsv1DV+Hp9katVO0yDK+xKAo\r\n4GbN0ElctVyZaH1az2E1/e7rwnZ/p0UtGtBAB8jc/jhBemowxVN3hQhpO0Dz\r\nrtllBrwennBLxTWAQxQ3MdcDK3KVkTL0Rgn/0ME5AyWk1FMmRKh8H2Dbtmuo\r\nalPx9nqFJKYAPUaOHbh3OcG7qywMWxKaTo1otXYJUUuKz2ixjKDVBn0ktsVw\r\nyUU4lTdeL3qNw9XTuPKCZs2l7O96H0RQEJ/AYmAAVYA7eDHmtzqgeKj13U4m\r\nvdXBc4uMviurq9U4ab3sgVEB7OmXLwz0EuWavGeCeGN9jrUqxuxLyqXybFWW\r\njyK1a9uQyP8buOwr4hf2Bm2Hf2TJVyOZMM1yys1qFoGZUdXDF03lhj5lgLPJ\r\nfmMdBc6a9RLwtp8h0tWzdYS1624EERpDyu5QL1LChM1cTWXhLxhfhS+yTOzC\r\ndZOcI1Q32gfxcrdfApIp3gvHsUubr5ygrjQ5L42gWP87wTFyGM1DEaRckrFs\r\niZvQ6A3GCkPO+fYpdcnIF15zPB5sZhi2FIoDThdce4yHGVJQTmQFWOEMNpDF\r\nA+wjhcEW0ZNTspvlX+FLluOIoHBrsBZj7MoVWvf+0lNwAS01HFv124aksC99\r\nRoFJFk2KQbBxF/PXp5B/SIKezIFqGbL8eBQ=\r\n=HjFB\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"83a205f2bd1f0f14944a2478423068728f018a70","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo \"Error: no test specified\" && exit 1","build":"tsc","monitor":"tsc --watch","lint-fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://git.arcticleaf.io/modules/aws-util-dynamodb.git","type":"git"},"_npmVersion":"7.24.2","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"14.17.5","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.3.5","@aws-sdk/util-dynamodb":"^3.87.0","@aws-sdk/client-dynamodb":"^3.87.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.32.0","typescript":"^4.6.4","semantic-release":"^17.4.7","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.26.0","@semantic-release/git":"^9.0.1","@semantic-release/npm":"^7.1.3","eslint-config-loopback":"^13.1.0","@semantic-release/gitlab":"^6.2.2","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.1","@typescript-eslint/eslint-plugin":"^4.33.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.8_1652318815213_0.8039461051742809","host":"s3://npm-registry-packages"}},"1.2.9":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.9","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.9","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"43d512602bd7d2fae7f6e878a9fe8bf97d0983d4","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.9.tgz","fileCount":20,"integrity":"sha512-4mKtDf+Qc/3oGXEyrTH2rYiWl4MxAhYELj8HERbIchQqHX+wuc1f2XmRdb01QzpwDalGl8RV69+Pgll+Bxy1vg==","signatures":[{"sig":"MEUCIQDsQ9M8QISfMjeqC/D1wRO0Jv8ghQaisLHHg1+A1Je/jQIgYZYE8C7CVo4/1lmpW3aJR6oQ9AjG8ND5pDNrhHXCnn0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":136345,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjmfCeACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp9cQ//UECrayG4Zfu4XPcTYTyjc7i068Lee76t1P+DWZtwTNtM/sJG\r\n/+3qOBvx91ZYjQkMbRwpF629mmTjU4QwSmmm2eUoZTY9rOqKJoKf5LgDDzmH\r\nKTqaWxQGnDX1oNH/MrslkuW3Wa8A+niuw2LiPSseSEQH6VC0GmlI4RYRg6e1\r\norhJfZFLGjfQE7Z3xwHBd9BKSoHmP7AJvEzAQMF1Rm7moHwLMLuN+vg4M9Zg\r\norceTVZ9l6c6TQJiSbvcuQ9r4lPu7e50tmQwMFxw5wMonbsAtIWQWaL//VVF\r\n68FyK9/bGbpEeHwEf1sBnBOVuvlXyabqmLzvE4Z+eR4BT1ext+zRV8qI0erp\r\nyWJGq0XvNyl8qYwLPFGMeK9VK9jNWjQeHFre4iPc0Pg/pI1VEjjsDo1LRjCx\r\nhMv7H6DqQ0jDbB4SmF/b9c6d2ci3VaqjdsshtiB0l/fo3z8XKOQv89zoFNmR\r\n3DhUikUdwVcQ0qy2xjT2zoKb4JpCRQnxBD6Du2CvsqJzzeEVKau9oADAnSIW\r\nxgEmt93j5LWviaMfs7VL8qbzqcxfLuSyePcYRpDx3YYGssSF7d8JHSVrDiMv\r\nS5ruR7boOMu33+qnLgAzNtHDurhDcRKGMQNoB5+22BroBRFdJtfEa2pjDj9u\r\nDqc4Ie0bGYk1vzR/tHwYBazV8YcRc+B5tTU=\r\n=ooPs\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"a81ad9d6b15babdda1a3e8cadc7767fb4a46e65b","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo \"Error: no test specified\" && exit 1","build":"tsc","monitor":"tsc --watch","lint-fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"7.24.2","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"16.18.1","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.3.5","@aws-sdk/util-dynamodb":"^3.87.0","@aws-sdk/client-dynamodb":"^3.87.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.32.0","typescript":"^4.6.4","semantic-release":"^17.4.7","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.26.0","@semantic-release/git":"^9.0.1","@semantic-release/npm":"^7.1.3","eslint-config-loopback":"^13.1.0","@semantic-release/gitlab":"^6.2.2","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.1","@typescript-eslint/eslint-plugin":"^4.33.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.9_1671032989986_0.635550134318438","host":"s3://npm-registry-packages"}},"2.0.0-alpha.1":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.1","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.1","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"d6e3248d256bb94917a14e5df9207ef5b13c9dad","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.1.tgz","fileCount":64,"integrity":"sha512-LeqhIqF6cL6KmrixsSv5l+zHoJLkM8Cw2csWfs5fYL+bk1NtTmBbNCgTshdSiAsKwtsMwBYScwpv8lCZWZ3TYA==","signatures":[{"sig":"MEUCIQCScrFoj4q9yDSuvmhOKiUFT+fEbXh5kStbchmo3Dp44gIgDV9ph3j8pRT5HBxvhQCbMb0zJj9Q6gviCWOSt0aKGms=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":165406,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjuwlCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpgSg//WAjDdPMZ15H14EP6JPH12cWX1I24CUJnKXn+9CaL8gJQFdEe\r\nfK2kUURCzqDrMmfFbG0tvb++Cdty9/kwDOnSdQ8vwk4PftW6XkReLekiADG6\r\n0xLI7y0LxvhJuzyNSW1z9Hrl1TJo09z3nOkCMh21Ca7LJhnb6UCFR57kGRVx\r\nCdql6Ai+CuRfbhgReSZxWxBKzD7fjArg0kOEdB5Z/R4LAZ0wkjlNLNWaa4t2\r\nrT75Gf+6rBEAP19s727JpImG6K3wOz7+jF0pfzgAuow2vFkGSiBC2gddTKqF\r\nQ92kL+31KaGwFkZhaBQi1evPL/wHseC+5AZFFZ9Q8B4HnJfRCk7yf1QsuH3i\r\nV2PCOORr/pm4U3aNc2EQ59RsX/b2TrpGGxpn9OaeqOQJSBz0I9L2dbgYTnxQ\r\nq+NSwHbeIpeoXWfdyN/j9sTVE0PC3qMvRiY9iH3bLjHFvgFMHFdK0b4zqxtm\r\nJm14FREDyTgHfEjoOjHW35J5m1DZ1DDGes2Yrsd25UdsIvrsbZSGlyw+Xt32\r\nAe8/Cx54lFa/8u54E5RG1G6nuZF94P8n8HZdzG7Mgw0d8uXPiKhMZokphqkZ\r\nuyDf6zp99Fdf/AAI803lW8B+/omjmZfCjZum6D5tLIYEecV7RvZAPpOL2L7W\r\nvgJzR0Hic3NrTzX3eV0zqE1J0JXXpPtXW9k=\r\n=tNP0\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    static BaseTableName() : string {\r\n     return 'MyDataStructures';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    public BaseTableName() : string {\r\n     return MyClass.BaseTableName();\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **master**\r\n3. Update (merge) into **master**\r\n4. Merge **release** => **master** (in order to pick the last version number deployed)\r\n     * _this may have already been done but it's a safety check_\r\n5. Create a PR to merge **master** => **release**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **release** branch __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"ae4c5fb3f60c476dc0bd5fd5748e2bb22eedc33f","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.12.1","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.15","ts-jest":"^29.0.3","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.26.0","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.2","eslint-plugin-sort-imports-es6-autofix":"^0.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.1_1673201986774_0.5970528830800901","host":"s3://npm-registry-packages"}},"2.0.0-alpha.2":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.2","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.2","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"7ff2235c192b66a7cf98753244705e1899cf9577","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.2.tgz","fileCount":64,"integrity":"sha512-f/kmCRjic45ndpyOAxnZGQu4pAI1Nv98bjKmeGhdZxKleLD52r21tz47RIeUtadIt3szvI9JIbFNisM3WyO93g==","signatures":[{"sig":"MEYCIQCQXFkdB2EiPdOHfyCZ4YC3fTm5tBNtZItWoLi8x8evBAIhAKyPgI/AnlSEZzdU32ZSj9OC1PEcMtYEIUr3+fdNaAYG","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":165548,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjuwsfACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp/Ug/+Mg8fOc5cz4eO5+Xs87KLZXrmWWbf205AvReBqgPr1izDrOfF\r\nB4NTEcy9vV4EpeF36qovXd7NTJvAHa5PoVjngx619VIT6b7ZOTH/3yRTGq2B\r\n0etgPmt4kchNsBNXQZn0znDdGYdSNjiXEF/ojfT4uRUiJBw9DEVdJCE3AqID\r\nxAtQrM+1HHajtKt6eqB+z7A3czfbc3pTWIIKwj8SXTRNBhdpuO1B2jgIW3IC\r\npWjhdl8cD7pDOeTxuEAYMawtTnhYDZ5yz1hf/5FngtAgL+wiL/Rfzu7I2fFi\r\n60UDpuPML5SSPfbk/5bfTFcG9kIi1U+58IajW82fJwEEl6wE57Q99/tCMnqM\r\n9senxhCAre1HoRlwYRZqEgrHXKFEE8SGPCbkAteBoI7DwQWIh8aG89H1Qqgu\r\njdz5VzHJ9Fb3Fpydv5uHIhAwEnvNmBKDZ6+aZXPjuuPPBdapDrVPZc6BJsO5\r\nQLurkzk9BeGBqzh7U5kw4dtRzf/lSxg1PdkyYv6sSRqQEK7LzJce1aDaMAQC\r\nGEbTFbcnQvuuXKPTU4z/wOj2fERBwbdJx+G8ktwKksNn9rcGWM3uyZOWxNp4\r\nIKNpTU63VRdtswLJ6/KAtoh+74FjnU5vjD/6AmXZ8uGQB/mvN1r9QlFBTo1/\r\nP3kS+Qi7oLbDNiRFOJ1I+YdA6JbTWVHASt0=\r\n=gpxf\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    static BaseTableName() : string {\r\n     return 'MyDataStructures';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    public BaseTableName() : string {\r\n     return MyClass.BaseTableName();\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"2d1db6cad14eec3131691e31eb35597515dde0b5","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.12.1","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.15","ts-jest":"^29.0.3","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.26.0","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.2","eslint-plugin-sort-imports-es6-autofix":"^0.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.2_1673202463591_0.18619953815771884","host":"s3://npm-registry-packages"}},"2.0.0-alpha.3":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.3","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.3","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"b3b8ebb6b72a576c9cdf24e228df6a6f77a048b3","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.3.tgz","fileCount":64,"integrity":"sha512-coZxKlfj+Ilv2U80bUNchXruYge2WQoQvuA77Z7ClWPLRdsZeq9SVNCV52c7ZTdBl32tcn3CJipqcMKCFIcv5Q==","signatures":[{"sig":"MEUCIDqIK0CYycu81ZeZAbHc+lZ1QJcQ6eBw5iRVKXqUIRw0AiEA0fIa2SeHbBVhZrJAnrGliQyQZG4icQFt3bBEQ5kbjtU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":166053,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJju1oTACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoPMhAAluj5S/a9AWunUoOMMIM5oxzt/yytIApgwdq822Nk+hCDp9Bf\r\nFNe2QoMsABHJFl4yVgB5qK+4wwglqH0YqbC4svz7gtYz668k0xywixfLkmXv\r\nay6hYK7L6k6z6w2KIIfqkGELQzGfINMwgf+JmGc0k0h8lx66rKPyTJIYE5EL\r\nfARPYCz+YMbAwKzlyu1JLHGe3pV70LpWc+jVkAeIGkU/pL/uTG2GGXveHoeE\r\nRlu7CnxjBJ9RAyszS3Owd4fWQVa1Wm93+tJ3U8ikF5WusSPYxx4jr6RKg7El\r\nJ+cf14Z8yNO0MUNVt8zaoauW57PmUfB/yLUQIbVBUdZ2UDw2PskM2DshrWMZ\r\nB6LZPYdEGoD2/LBBKuXtpqAl7Zhz3xOn8NnFslCyVC5T7C0mJw87g+uAagi1\r\nskqZ4P00d1RvKvgwzM8aNpUyXrUCkHpDvjfBHqgsM4oyJ0rS5+3gh6M5JkCF\r\nOqxKmqgF5k+2qTvmhb3h/BxC/p423Wk1iQJlVHbxYMo/vOcaL3myUUzIeVwb\r\n+1q2u3Z/Qk97ENUaNoGDigq/AQ0puMPDGkmFKCo15BXzKNeD0fry42L+DWKY\r\nqZR19Qer8+FKpYl4oTW2uGnGhuQ5E29CnAW69AxA2hnLxIMH42Zkb73CMbfI\r\nq6OJN1U/IQzLxTEFmQzzsh9weqdEvqzN8t8=\r\n=c6dQ\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"3153a944176b0078ede2d9f2b9f9d8155af4b846","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.12.1","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.15","ts-jest":"^29.0.3","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.26.0","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.2","eslint-plugin-sort-imports-es6-autofix":"^0.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.3_1673222675652_0.8286193479590476","host":"s3://npm-registry-packages"}},"2.0.0-alpha.4":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.4","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.4","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"d8ca0b6b045290beea9fd5fe2c53e22ca2667d6f","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.4.tgz","fileCount":64,"integrity":"sha512-a6OOAoPo2nWLM6sBfnaNdVNqxnsqt/3YvUD85jkgGdt8dnUsQvh/fAR7Iz9LiB/lvXxwOy33YAAld6b1pZtbqA==","signatures":[{"sig":"MEQCIEXzVIdGwM3prP6o1W0Z1+SWf4XOzHR3cRjmDjAmM4M2AiBsck+OVng6C5EC23tua2sOnXCAHOysmXFB00qH69Dzvw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":165669,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJju1tIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrwKQ//f1PQOFaQZ6yGGPXlSyP8QqFSe6VdJldqa53u42b7Mgch+og6\r\nqOxQKHaxks9FlHTtj72HMdu/aF/laDwOZ8UBPQV3NBelNmNxKCCAigakd8/T\r\nbp3V0pz/VuGyD4KT1CSuJDsJ/RvZCDHZaITzqq2i4NXpGAaXw/ROFuR1YQiI\r\nbst0TVrZQgnUv3nemBOrbb0YL0j840sF4/KdC1fIJIyLMDGwJSdA3LSX8yiI\r\nTQraUmsC2AVLbwZV23vihIA0l14nf7RX5p7wHIPCgqGHSQp9mTGn7tis/vsS\r\nwylKPZ1Xcw6pcGJ7GtW7zpkMHLG3aCDqZBKHYFatxGFpOS0UBUQHXWx4Z2E6\r\nOogDmywifBsZeImWEeDMwkgoyHq868DgLc7MiqfIK604ZbTL5M2kauWfYDkp\r\n/CTwGlshdxbaBl4PucAsdrYGKgDm+k5dO/Th+pVldfvO41e35NKKQLBzlzFG\r\n9y2+ySIGmZSlm79U7OXxKgwmS96/e6MLIO2aJyihpjyVQiI6EFQo4z0Hkkai\r\naJNCd4AWjBCxOttXyyuPS1PjoWj+QWG1OqyrjYhoQ3z+DUSuTCGIS1b6+O92\r\nTvlRz3yFv2p+EluneLz0XvzDVhemu6Av8j21SOXbLjSBMEivIKIDQaa+qN6i\r\nxvg+RHObKGaWINzefZuZMtyn1lRt6mD2eak=\r\n=Pba1\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"b61a1b9da55c6969cee84ca6987431cf5d8bbaa6","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.12.1","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.15","ts-jest":"^29.0.3","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.26.0","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.2","eslint-plugin-sort-imports-es6-autofix":"^0.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.4_1673222984746_0.9712889061581524","host":"s3://npm-registry-packages"}},"2.0.0-alpha.5":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.5","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.5","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"76f89097519405d2f5c6f2ddfb491c92480cc2ed","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.5.tgz","fileCount":64,"integrity":"sha512-+nU1d4U0A/L4jx/DMpE21f7/DPJ9DWiRA9LQ8Yjfr0KBW5iyJSgZbgTc25bpI6kEpRGI3Qg2uCR2tfAMtDieYw==","signatures":[{"sig":"MEUCIQCyJkMCUZ74nIT0GKSRyVi3gaWrsN+J6Iu8xkYuPzSt9wIgCz1Ti+7b4iYES1I9a1ccL2uWc13nrVAC++mtKeAk8YM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":165744,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJju2KEACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqPvg//Ru8kEOPlCjug3AZ9WygWT1kLzhPz2tJOz0WujLAWmXx1ol5F\r\nE5umIiAtlSNiYba0Jm+D7hSV62eQKD9kZig7quR5O0lZDUL497VnIzBKWg97\r\n8gwOypBlB9bkxGhARUc1DxP25Bf6IrqJ2w/n6ham6pEY+YDlVADhMqY8ps/v\r\nca/ApOrouti/dhhcH+1R5CNSq9HXJQE6MsHXYUq+bwOrlJm/AcOqV0i4/Ulj\r\nLLNn1A6rujSltU+p1vPaUkU7zTA0wn4qFWcZ68lRLtQWK1RRog8wIYZKBLVY\r\nyk52lhjyoTnk6xbN+0RME2YpLhJ0qL8qCoa1ext/r9fbTz0B9Hezy/Q3Wtd9\r\ne/FjdB5ttS0tYLFKHvoG8ySrkpKPx9IuN2nOEB0eIYg9AeFvbV8O1LF8iTuf\r\ndjIiTvolEvwRLnzFWp4Bn5xmNcwOO2x5rmvu47BNL8jDbv05fgb06914EAKk\r\nuHaKM3rG8VKnPLiPlmYWYoJyAiVpOWwjAA6iYp+FhYdM1yv0tyPByAivXE/p\r\neoiG8S7rZxnoNb8qkx4WWqYSoUqo6hQyKkzZX3LJh7Ev7yHRQSVQoB5sqdyZ\r\nzp8BE2MBi8tiYcZ67ThREePHFpOK9T2JVUB6Ws6sonnHGy4F+QIUrFDY9VzS\r\nazOlnWgUuWEPR5rZSZ1NRvHYHIa152fabbs=\r\n=20eN\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"e3449f8457a2c0483ef7e00e84657adebb42fa43","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.12.1","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.15","ts-jest":"^29.0.3","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.26.0","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.2","eslint-plugin-sort-imports-es6-autofix":"^0.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.5_1673224836210_0.4654407208800162","host":"s3://npm-registry-packages"}},"1.2.10":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.10","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.10","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"dc6096f5be861ba81773cc6688c829ebfd170c7b","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.10.tgz","fileCount":20,"integrity":"sha512-/voKqhN43TrMwqZEP2UKGuMoYUwelCFTwC/zptfTWPHQX8z4JDO0ondPxcsjFhnCuzGv4ijeMb4/bbMfQ4eqWA==","signatures":[{"sig":"MEQCIG24q4U2ugGLd3Dx+zBWd2VIfieqDnXcPDSG9Ux7GPYtAiBD3U9/zTPpec4NpqgnPv7BFkZ9Rg7R58hvRio4wtAzNQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":137760,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvKHRACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmowZg//RK3ao6lRkoHg+9S0dOVYvf1Ln7TqZ6fSLU2RNWFWBgPq5Ao5\r\nz8X4WFmWJWuSt7LmHT9HwYWymYsGEWmUJPc0yyiEr8KbTO8Fcb3JAJZnuGZd\r\nyWIsRmChqgPYGnhPa+Id0cTnjCffHS7hR/0fq+oZIbzDDJfVBueKwchAyJVM\r\n7sWdbhY38kEX2u4CPNjlxVBzTUiLTpW9gT1zLM0Nt5Vc9hvnBtF0JW9VcfVX\r\na9yPA/LHtsC86WtJwsckD71qm7A6JLzWgB5O9GEzpTgb7bvMBUkijOBYMKUa\r\nmcKu6iYpejF6rBFb2reo+i61zMpY9+kRyDPxVmebQnaDNvHakV4sb04mbP+C\r\n+wFt6XJhqbRe5yK7CryAO4xQU7tiKUYTI1pXCJAzZeCsDolq93H74Q3sO4/Z\r\nIgSvzdxCqTX8L8T8iNLkNus8la5BnizHW7sEgq83tzG13435KIrlAnDBx+pl\r\nJFLl/jWsgj5opihvnFYHhSezjtrQr7Vt9aa2YzhG+sfaE8A5uQUuRo4oXsbv\r\nUyfi1v0dnC/qQzvACvW+ZD7Ghl6s5jgpplZzTgC8Rv2f1dNXI1QoxSvT5iAA\r\nemrmCEzoQMGkhFKvVDt8q9rS3c2d6a78XaF9Vjjt8Feh6nXWHaaEzA6XeHr9\r\nnDf/YaMQGw1bAGSqTvi6NpQ50O+XCjX8VhI=\r\n=aD3O\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"39398823ed7081dc5481fc054777bf6f322653b0","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo No Tests Defined","build":"tsc","monitor":"tsc --watch","release":"npm run semantic-release","lint:fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.12.1","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.3.5","@aws-sdk/util-dynamodb":"^3.87.0","@aws-sdk/client-dynamodb":"^3.87.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.32.0","typescript":"^4.6.4","semantic-release":"^20.0.2","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.26.0","@semantic-release/git":"^10.0.1","eslint-config-loopback":"^13.1.0","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","@typescript-eslint/eslint-plugin":"^4.33.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.10_1673306577280_0.5010601930869738","host":"s3://npm-registry-packages"}},"2.0.0-alpha.7":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.7","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.7","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"1e45799db07fd59d0e4cf7d64f0a84d439de3201","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.7.tgz","fileCount":64,"integrity":"sha512-RC9tXlsuhqUue1eTRWsZH2bNwM5YXc0Qbb5vd1xH+Pt9huYcocBRsfWhz7YVyI0hX3qfy187dyU319GJFbEOvg==","signatures":[{"sig":"MEQCIDfN0C6ZdMNn30eBr9XVBFnOfpa/44wfJLHGhvTGIsTSAiBw1k0HflkTlOf9UXrgR91/ogFbSa5uO3oBvVUHdP3T1g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":165808,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjxuGHACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqc1RAAif1l8FD88jXU2UYUoYKNc4mtFx3q54D3XDXBe6BSQbWOLIV2\r\nTvq69UHGvdNG4UvEnDJeN3NZaXbPJOyNkOz9qb+l7HuotPIjsx4W2SDOyPnX\r\nkaoLIDxSgSAL2q/Eg1mBE60p7kDXX4K49tgPWTXHhLKga/qQN4vxeByLS396\r\np6hJmQlyqmOaMh6dj91PtKfuVVp3smJv/LAw5MxG6Pxz+tSXD/omT7K9lkoK\r\n0fIN8o99aoz418aLAnRGlnQSG5NZazqbTpSpAoRyxoSHJOoYX3lKFYKFAYys\r\nhVcQAgpn7BF7RcrcOg3oKQFb4k5F0lTS3g7iFSeWHuTAJuEEWESDdNElpQ9L\r\ngZqhssScFCGXzSCrcJSaEKk+s7e5BLHMsywkyuZskqoWymT/5okv7nPgheIT\r\nXGndwe239wUL865E5qz/aHjMP8Ouz29Al+2fTPyFpT6HuE497dhIM5nqRWOH\r\nmLE4MTa6cYNEZ1EFBMDcy+t8OB66o1vnOK790Q+QfB9n0mgkOFFiIbtjozky\r\nY93BbRz7kKDfaobcfpwlyJn67l2LR8mf8bytgk2+bgYwZhxgOF4939RNvmV6\r\n6dWJm3vIQHU1kZVD7CcvjQRrdtsXL5TAqp3k1a2lMafHh36wlMP8yrRpqlpI\r\nqSRS9yjAcAmz+cXHsqopqFwJcnfzf15CRzk=\r\n=zUNr\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"5cfc328cb7e34c168b878b7dfda5553d040663f6","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.13.0","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.17","ts-jest":"^29.0.5","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.7_1673978247394_0.9250031882357803","host":"s3://npm-registry-packages"}},"2.0.0-alpha.8":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.8","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.8","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"2f2029baf4f67154b0fd283cc7d7da996751a9c5","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.8.tgz","fileCount":64,"integrity":"sha512-35PtBsETG40rciMZFEYdjuLHrjYtZgUd5aTdGJGwE6SzMl9PKsSj+akeb9tCoCREab3R0OcFABbTrnNZujEnXA==","signatures":[{"sig":"MEYCIQDB6JeQp7mNnLdEOptAIozWl1rqjkhhvZbWy79gzp4OOAIhAJmMh5Z/1Lqtlj5RyNUQCB6rKS0zf88Lu1SAQXTxu0lI","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":165808,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjxuW2ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqQ6w/+JKHEKh21rsqAkNsEJmebM6R+gWup/Dv8Eedx7OQw9FpHa/Dv\r\nmm6+flKjNWfAmNLp0nKM88cReqQbj44XPNJciCzlKE/wfjEOd+cyB6q19d4H\r\nGHwtWdKAtx2SAcIM8VJS30LF3pTtq/YPiHTeYwQGlPC4fu2b2P7gfhfCU6HC\r\noMYiah3jU04HkrY1glK8U/gxV+XhuskPF030qL+cz2kHfc2W2dZwvSXORpwP\r\nLiHXhv6gma+H3UWmExgjJE0ek4noHXuKph+U6P2RbR4BgHpa/QR+IUsmM38M\r\nvfdCA77ronO0Qt3oyml84RHVNdzmM7BcUFWDCjUOML/zdatwZgjXprIxCy3J\r\not/VJjQULPJ2TIN1ha/RfiZiAleipZN1JiYqk4jBdhDA0Y8xXEnMN84TBJyj\r\nN3vp9QXgTZw/IZCnhd/PUK6beygqhzpJ9Y3kFrfgtL1/D/eI/Ppoh42m8Ovl\r\n2qrkOPr/Sp/HNXMv9eWE1DtfKiN9TrDk1Gu9XYNUy1rBbHFMJ7WBa1fcQbrU\r\nAJ19mNCeL9nZEbtRQ8YJDWiWq8ifyDl6r7LOrjijbnggWRIs/ZoribbU7GbH\r\nkKI8htLgT9c7QpfrQbN+SDIQUyNQdWSQdd+eKkAosXRpDDH2630kB3eGX7cH\r\ns87GV20vBl11y5aCLhCsWN9go5cvRfH9m3E=\r\n=15DZ\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"172c126238ae808d05923b3da7da5314e9265c8a","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.13.0","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.17","ts-jest":"^29.0.5","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.8_1673979318315_0.293941452836574","host":"s3://npm-registry-packages"}},"2.0.0-alpha.9":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.9","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.9","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"916eb525859880ede9298c79092cda0eb2446f22","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.9.tgz","fileCount":64,"integrity":"sha512-9S6GS2pozl3t5ByqmqiOCU9ATzLiCL6vFk+nYkd0GpsovkQ5a128BZhKevwrLxASVaISE6QayCILqTYE2GLzDQ==","signatures":[{"sig":"MEYCIQCRTxaB3osxBrlcIsb1KjzOo73TUW9o8XnTYydo7SLyGAIhAOso+CMmd2dVyhNi9QCCeBR5hG2qSd8d+fheiLoKRbCN","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":168059,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj88UFACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrWcg//fVdIYTECHKIMWaTtWZaE0s7T0oTKOqFnweA1dIOc/6T3eYbG\r\npyUWGXX0bAZhEeciQ/yhmtfpt2Bocqc1pm861GATH/09k1TaRS3EVkp8TR1/\r\nCQQVlFI18+GUhnwyyOOtUGSMGahfggGFqc/zCN2qtJdLn+ZPBwNHXUkip+SB\r\n5QNxWa29lWVDdHnBTe3CZSbcmQeI+BLdkucXeygU6cEojKwtGUnHI1CaJ5GD\r\n+/KlPMk4k63PyLDAPTHAghFsn/OfG15PA/CnSkYyAgJ5vaB2RbQ93jbTFq3D\r\nTt6LPstsz/HsIwKEBaahe/y2ae/ZcOMlqj4Q9rdtmVxvSRr8WkEPWu0sImOn\r\nzYPYlzTEa9hRqOUSn5ffwK9u+IuQgXtMuwLMcSprdWXVhG8FGMRhDNF3aX7x\r\nZYXWCqA9Or6kStiBlQbIUkisOZFLDa03PUYfcvugyNHnpVqJ2Pq8EqPM6B4N\r\nZGHhWIWBqXVwA9C9UhnmOSerb24nAFOE9RDuRdohEXuib/mLJfhwmwRX+2Zf\r\np1TdayyxqnyrbbFoUoI1Z5HSqrljhKdzNXEoixOwx5gK2CzADviN/BS4GKKP\r\nPD5Eutsf6uqbntRPE+3OUcLco/+XlBT9/2uWMEIGwaxH7i5KGKm0S6/9PD5o\r\n/HrLrZiKecqfWhydkvGXX4RaAVK0CLzgK1M=\r\n=PuuR\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"7d8e7eabcbd83e7cd03acf1f744a6292fd428836","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.14.0","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.17","ts-jest":"^29.0.5","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.9_1676920068835_0.8933748179102106","host":"s3://npm-registry-packages"}},"2.0.0-alpha.10":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.10","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.10","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"6c9da1d91fb349f78bc8a252405155afc69e6f55","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.10.tgz","fileCount":64,"integrity":"sha512-YKceicRZx4WEBKUFZ3kYVcAAn/qGMWpVeF1YYRRindLq+UaGRW7LHQO8EwVsMQMYhWXrqeTbmYUJal9EneDDvQ==","signatures":[{"sig":"MEUCIQD3RfjuLbx2+qhGHMQbFI3d/n/tCOVTnXNDKKWC4b7hawIgEJROxZr5bmDfO8LU1NLDNCGJvOh7gvqpqOWfY+EjgIo=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":167987,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj9AC9ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpe5w/+Ls/miw0qmZUZh31pa6eeiZ4gPJGEYNwPQpS8lSfiY1TAcPzq\r\nvjLuMTk7P0e2J0rUNOO6hXcnhtRqC6106tC5Npnbo7wH5rL8ATYP4Q5J2IzN\r\nALHh2CruqFxdU5UEuJl3QNWmPpaAPoy6qfWutykQ2hcCd7dDlbfB53bB0Vl8\r\nfeOyTP9mIgm0rOgtbdf7kWMSOCtWutZwmcUzpDNlSJk+XXK5YKawZAUmT59q\r\nvelAn4hCyxhhDysAR10ISnbc8K+gpJ3qNI5S/SKM6T1OHUHKQukYHSoVgMkA\r\nM/5eStWJQ3nJZPaObvZC3tPYRUwHwTEZPCmMZmePilJvvl1vsRi6EE05RSbi\r\navdhUak8pH7BxnyOvDCi02NhiPYdgHiw1IPPCfWkJbAi/kRmDLiwer85jAUv\r\nxm2Vo8P5CmxDeW424wdhTuujgoFun6aTvCqHdmbFar6pX+L1Z5BomjB12xmA\r\n29SeKL7wzdrt8xSRmEymfXEv03zWsm3dfJEHprOO2HB38H5Pmdpsw4oO1Dz3\r\nPJAinE7pwXH0FQikVUX7G/7ttSLFVLIZeSWtV9/k/gL4kJE41VUFiUGmdf4E\r\nFIxUxRA4PnG/8lb2tkyRuctB/Ugq5b3+YDu7ksBSz8KnKZ7wL6dzUqI9Dl6D\r\nr42Yd8kLNVMpu50R+d8d3xnMU7iphE021Yw=\r\n=bUuu\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"af3d293711ee99b0cb7d51b2be83d9b1ee2b7ad5","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.14.0","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.17","ts-jest":"^29.0.5","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.10_1676935357677_0.8091564082577432","host":"s3://npm-registry-packages"}},"2.0.0-alpha.11":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.11","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.11","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"6cd43bb578a6f5cdd7701634486341a1dc6f242b","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.11.tgz","fileCount":64,"integrity":"sha512-hjmYfSeaS9M0s+BX0/ad2UrblYbj0asYBJ1JPQ0uOQlYkIxmZXq/wFJNZZqLHoY0Z+SeYh7YuMrMTb26gHAvcQ==","signatures":[{"sig":"MEQCIBdfL4PJdQKoD1nW5r8Z67J4rRCnFJwcTtY2aLgS4TshAiBFkth1G2umS1ZkJG7O2wSWzIbniUFRWjqVcV0MNbyTdQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":167987,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkB7/5ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqADA/+KLn33JIPWOIWkiXHUeca+vn8C2nURdQAwARRqXsXXMjKAPwx\r\nRw+T7DoYIV20/ZhDZD6OkAaHc9OBlO48xRMGovucgPpFyLmB50yXmrVLTcLh\r\nI+HOZsKJL0KTIgwUxTxEGXEgO+1kT7BIFZlbx9WW5QEhju/tpkWSYi9mfV+j\r\nZ06vRJATXCb3fa+mkEoa6sOBrEL7d4NeBryMxX4OH6tBwllDlXagA8PAejlz\r\nZLy8RtJ6ST6gsG+0dz8aICggdC5naE/ZARWnCkJ69urPs3q7U0tgAYHSDwX5\r\nIAKdNyVDJPH8KtyocfJCxZjJTOWIMlIO9k+QeaBPY0HPnVwJrRVGPM9Giysx\r\n/e6yTCJ5nKKrtChCuXBZzgwpgmwU+7iFKxlNYvNVRCMIgCIbf0fwl0OJ5yKO\r\nxPUv6X36bHBe1NJeN2rzhqS+7R7pKzOxLpsXcCdCIuXPVmqIXN9zubKjsxbg\r\n9OTX6ZFidr5IjI1WHOY2VZ76aUI+swmxAAl+/r8Qs0xG/B+g8Hj/zdddHxRN\r\n6Iuv3brLjri2MB8xNzR3UamuRODBJiHK2ksM0kaUB8knY2bKoZn2O8vHPBzc\r\nQlJfKUMzWvlWKZ6QpxcbIWU1PKkJQUIlG2NqNZEGs6qqcar0mBJlm6H4Vp4/\r\n3UqOLOeb8lErEaQz+fvWuQtFChcsVlhMLak=\r\n=L2e+\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"e726e04761f040a74f73882f76127ecab6552ddd","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.14.2","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.17","ts-jest":"^29.0.5","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.11_1678229497500_0.7271987250642373","host":"s3://npm-registry-packages"}},"2.0.0-alpha.12":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.12","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.12","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"fbac75c7493c0f9a59a370990dcf6c9849a42fb6","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.12.tgz","fileCount":64,"integrity":"sha512-Q55ZVecnzDZzsMSaWnE449YbZRk8fObqZJ5bi76j4SBx+v0eXaV0UVmSV/u04hPDGcTl5hUUIHenVacKYEVsPQ==","signatures":[{"sig":"MEUCIQCNGoQ8fErwpi9PiDITilaVO8nsbXhPiGLfHIjuREmsiAIgFaZN5WgJFmGfcB6DlNlUhkswQoc5/FKAQc0zGKHQkgw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":171930,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkE03BACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoLgQ/+ON2duN/sFaIvFHQcnfUJbXKGfK15DpOqNcYtVmP/XVroBmVu\r\ncnTG94dl3zwuaEIWZ/yjeqaP197HCClZ7pvSariA/DOajzzNmnR8kZW9DZ53\r\nq5IrGIjXfqRusM7Yo6mgupMO24WUEIH4Le0cuWIwl1CBuYL2R28BxdCR6ozt\r\ngD9ohATh8IppO+PW1h9XsgEi8uoXvs0u1cZcXIzx7JeVAet3szNVP+F+yDAs\r\n65NPvsOwUNAosesLXViWckrUH2nTd6W+29+CuCmbqQZLfQ3REGneGsDrwDVt\r\nbM3iHcXEECx2nd5dEIFNpme+zBWB8yHEGpnXQztHQT/bFxLus1qXQGarA1nX\r\nv5KxTXS7kg2my94FAUifUARyLiytTZlhc78E9OFUU96ZCKJjRBdBdgDdF3g5\r\nQ5MymqMHTEHfBJt0ofgHx7ZanDPAtWcoiFAme1UGoLEsRVFF/G6cEJrDCjeL\r\noWRofI+fIgnWmPjd47QxtcuhJMXusgGOfYF/7LR1aWwq8gwOErS5TvQ4XSC0\r\nuzVPnhzTOylXiMkKnH1wh8Q/6pq890A3jXyELYuGFusoGAlobtKnDnUHHz4V\r\nZFzn+CX2loHWuOLAH/x4OO0mqn4Jec1C5FfpSO3IVDnfW8SLabJlzS3Zx4OQ\r\nKGLR+yCSD0faVNGf7k8qNYjX8BvQa36ND6E=\r\n=PH59\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"f021425e3ec0e5adb9c63bd9b7bcb373aa18faba","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.17","ts-jest":"^29.0.5","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.12_1678986689407_0.25318510752194556","host":"s3://npm-registry-packages"}},"2.0.0-alpha.13":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.13","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.13","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"5d87795ec6d9f3ac55d3ca0854db437809a644aa","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.13.tgz","fileCount":64,"integrity":"sha512-He2vm0gxjzx/22kpxIRBxLIZqbJISCzcE29iq4brapwu1fkgyefvzZ8iw6/x1rRbYcROl+MCKOP5vo7/VlK4Gw==","signatures":[{"sig":"MEUCIQDSDFIJjSjiQ3W4fR56JLm8gnDbj9bZCAl/2700S0D92gIgAp/Jx8BbH95qEjMdnjw4QLzyZNZpcl5Z6NmAWu5vGHI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":171889,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkFnaiACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoIww//UoSMAjx8I+Z2X9h0jysxYHlX1HcyGDCi+gHYtfI51+IM9QZK\r\nAbjsIUZjHgWAJSCYdAU4Kret0YPoTHmbO5XyZmx9gOGpObj2wrDujaZiMDJ6\r\nm78mrDp7N6BSbL231XZt/w5SkY/21DByg2lPYHdntWSycSpeoYDTJfij2mnU\r\nnBs34X8PNn9ax3LXWktW1qRy/H0HjMUWV16Msbu7fhwe6XxBtnjx4QoTwdbm\r\ndH9RHpdBKBXOPE3cBbBd/pBtiQRsCdStyjUUyf0NT88Hr5ucualXZd1kJx37\r\nhENRmQFujYY3XuVdEMvHu4yID9hrwHKP7UnhhmpiqJDCZhU6yAowzIAfJoWE\r\nLGoRgDkW40gCnwpHFURCoEWeJTQFCIx7uribCykrXqAPgDdF4weiecsyzppf\r\ngkr0D/YwdzWb9YvbfF0o0PHS6+gFWEWr3RUU4pxPeex4Qoejb9JVBXtmmxy8\r\nSbFAv0vmM1ZoLhkLcUXmJAMDoBtL1FPuYZdVWfaD/MaXMKWo7F/va+cK/D0O\r\n7Py7YooSHr8e1IgNA/5JaUnnxJxknctJDbyV6fkttwP0yiydgDXqZobdUld9\r\nSXWhpvcm/TfqyyL5rggVjgQLGAgprNJxeZHGHRdzFOOp8r12U1faiuINDboF\r\nwpQ4GXE/IRUVcR/gkxhMeCa090rJBrOMoZs=\r\n=9WGk\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"874853a8569f3c212966d2acdfa8b33d32a3000b","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.2.1","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.245.0","@aws-sdk/client-dynamodb":"^3.245.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.3.1","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.16.17","ts-jest":"^29.0.5","ts-node":"^9.0.0","typedoc":"^0.23.24","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.4","@types/jest":"^27.5.2","@types/node":"^18.11.18","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.16","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^4.33.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.0","@typescript-eslint/eslint-plugin":"^4.33.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.6.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.13_1679193762575_0.857621552915486","host":"s3://npm-registry-packages"}},"2.0.0-alpha.14":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.14","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.14","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"a0575293c0233464f8642bf5368a1ecd1c0a93ea","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.14.tgz","fileCount":64,"integrity":"sha512-90z/Hsj0P5gJxj1c7ZbMKjrunzveeRtcOQbFrRGAaqvAAC8uzDi0F/rlJCKkEK+VYvAmEvy8dm05eTcqViLgqg==","signatures":[{"sig":"MEUCIQD4MSlRlE4VFUSG3OiBeDPtLzSNSJqekikNt0fF+f3z1QIgcRxb1xG7ICLNG1hX1wD2hnfPYuEExcJSn2WTosLq7ik=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":171888,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkF0HqACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqkIQ//ft/XLIvZBbPK5wW4zYptPsa2dpOJn5/3zTASjZ3j/z6y+Yd4\r\nu/GXMf8c8paHyeaDwdh1EUL6IgZhGsWRs9d2edCUxa0YnDF56mmwwEiI7z/8\r\nQsH/S0bBPCc6N1/oci69sgi3nvXsaoaleE2+souGyw6Dcc6rZvPssX5DrL0O\r\nDrRM4Neg2ak4C9Mw6y7dMriSi7KowFJbAl7pWZUD+vo90UgTCxDyL11isdkO\r\nOzzVPefZ8aKeKw2iEXbTXafBP9rtywlu1vX3t+ye4gWp34rtprW+HKhVxcr3\r\nUpSBZ9uEZixKtGKSuIQr6MU5RYf5i3Al27624UmU4IaXqXv/RZFlcz5cpWM1\r\nk78QS4dYGd7DxlcM3kLk82xDYsh4nOBUCmSKDAcK5zWE/M6ahTGfHCVarOrT\r\n6jHYuVmUQKnu0E6toXn/iFS8X5oXfwIAFtF/rDc9Ic7hFOPng0TVaHHK8WX1\r\nYQxJgs630Waqk8q41vq1it+i7EP0DWGHNPtuQI8wDq9oAXrHDNHgVx++UZxS\r\natJFxNZi/BJs1AvT9zlZLd+a18uUhtt6iEB5dp2vewzj3Mf07xEi0dTiMh2u\r\nMrdhAh5ZUq1X/qsV5keqrN/jhs1RNmx+AnWB1J+1wcT7Rq3/KQtSQ253Giki\r\npFwHvPu5+FtySeoIWVW7hgGW6qb0RWJd7XM=\r\n=eMnw\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"c261c894124fb2b3e747ca0052e21d4e74f0415e","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.294.0","@aws-sdk/client-dynamodb":"^3.294.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.14_1679245801966_0.12156981380938414","host":"s3://npm-registry-packages"}},"2.0.0-alpha.15":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.15","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.15","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"d7806d2618674ee82bd19c9a8d1314a44ac61c00","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.15.tgz","fileCount":64,"integrity":"sha512-7Vs2OlLLBzRKRFvfRqHAOKFwzUoJcJOJ12ksuQHk+IwebjbVU8ZSHJJXPqKflYTuiYvqrChOB8FQFMJ4nSpFGQ==","signatures":[{"sig":"MEQCIEay1nI6tCpBBPVeTbICvLTJ1aXN44zKzkcmCfDWGhq+AiAo8WCBvgqnd2toqgyJ1c7PdbCLX4NXTS3yrIiFW+yQbw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":171861,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkF1lbACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpXpQ//YbiEp3fKWJY1Af5VfzPrPK2tmiXJ6nS7gcUb7KjOa84DfGh9\r\n5hJMt8wvTsXwrSbr4gx7tds3AcB6gfXB27/2RsZi/T7dhbdP4Pnxk1ugpPWd\r\nyun+3vN/IfUkvar0Kr2HR538vL1qRJ+FGjJCEd4ID9obD+/r1i2Hs0rDtb5h\r\n6wIo2R1HqBxbdobOVeYd6G1mL20lut9r7heMhw1d9NoS75GVAh0Uqo1TJ+OW\r\ndBbmZm7BJPjWRrpoESiywxbGRtaXuKW9sImQKwJ33IVcjpveCahRYyaB9YFU\r\nU7+Ve3S7kcQMRNDeUm/NckwHqPKGA+VfHWZjtabks6V4JN40xtvcS70oz95a\r\nhVRbZA2a3qyF5oNU7LVmjAX4GT+DylU76kiW2Bsl4X29CraxcSBXiY1x93nB\r\nW/IbgLgOOqs5rcNqsPBH6ZCSy7wf1bxfalwl3gml5a6gBEBDAxPvaZe0hRap\r\nLgCc96ztgA4nx471EashF+cRofEmWuoFUn4JJFCXHLrbQ13n9awlATrcRrI7\r\nQTOWSWocUeM/dMPmwRhBxyyhTqIGbthwG8JiPsDa9y7SgkUbYyBIoQW1aaFP\r\nEPRVeU0V7gXKSJ5dDmYuwlL3iy08CxTcd3mu3j5JDJC1sPth5whJm+YzihZE\r\nRMZVBs/Hjb06KP4l1bSCUIkGXSqbqINiV0w=\r\n=7dfC\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"3ccc8356889611cdb5fd1a984d8447be238c2ac7","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.294.0","@aws-sdk/client-dynamodb":"^3.294.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.15_1679251803437_0.5988214470182167","host":"s3://npm-registry-packages"}},"2.0.0-alpha.16":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.16","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.16","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"4b28c4fb99c03fa8af17e19754c6ce47969e6b6f","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.16.tgz","fileCount":64,"integrity":"sha512-gvZfUuFRW5QEUa1s+JCAYqhK/GM89ZHIoexwu1G2DS/Fjt3M5sWht/dkm9sA4wcXTzoj+61MORFh1dmaEqGNEg==","signatures":[{"sig":"MEYCIQDY497rqRXfY3f6Ka7giNN60S4CAi39xBp1b/3dKYiLmwIhAJm+tXg1fzNYOEwuq+y4u7006BEes69THSH/A7k0omVK","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":171861,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkF6xLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp5ThAAiOc0HfNvM63NuHzAzJhU4Bwgfq6W0l8mCRo5zfkZXrPKKLIh\r\n2+YnUgec29Lr+Uz0dTCukmWrtWB31X3gxyb1Qte8FQZZVIHUb8aFq8YAQc27\r\nqnKMhuQj8MbfuFp7UkRsMc/7FflW7AGJWTncKbmqTFrJpSkXJEi59apO6v2Z\r\nFjWIgFWUt4iBMBbH904FSn0icaAdcDm4vzLPAo7JOBNkd/F28gTLXoE2vnfE\r\nYF9+CNQEd1i3sUS70/mrgaTROD4HhgcDfCi80lmitUixeTxwIbGEaWnJSIp9\r\n1GR3HnpRqaVerrrks7f348a17H5kY2tz29tf5Syi1/KBUJf6tP2UivyWkoil\r\nJpdLORWod5uURGuWF0e5hm6F90ifClgRaZWoAsnklMmzFplzB4qv+8t7NnCF\r\nNhTKOFXbwMtsnlZbvU/b+eCoHk/YudykvL/SyEPwJ02kKpiakdwQKA52HW8D\r\nO4h2Vq7lOA0XRboeU6CEo4JGSckvttC5OhCc9AHSQb4YArot0eV3JHw//bJd\r\nF+Of4s6B8HuhMIOZcMSCzuxeSlhcUlrrr6iMqML2/vJFpAW0ME6Dj4ib3dFe\r\n/Wy+o5bqfdRdAfa1dbJ1Bj24HHF3IwQe/ZlsZRkAhym+850g1rX8BaM066z2\r\nHCv3dQOVEIuH0e1d6SNOl9pa6rXOnNXF+Yc=\r\n=Nk/l\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"edacc71e3ebcf5141c00d85ae7580f2f6b33f455","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.294.0","@aws-sdk/client-dynamodb":"^3.294.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.16_1679273035311_0.9020814587211279","host":"s3://npm-registry-packages"}},"2.0.0-alpha.17":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.17","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.17","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"9a52266499137f4aae15cc3428e13d814e064bf1","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.17.tgz","fileCount":64,"integrity":"sha512-oDHFvG6UWPTfsyr8taoO6Jj2LgaA3Ty3GdiOtDn2gXwZWl8xx0SWa1cLImzn6TS9uA9pV9NlI0T8skMEIOMnsQ==","signatures":[{"sig":"MEQCIAKwGhJ7qjPCQ6veoVyrfjFT/c81PdepU+eZrHh/ZLZUAiAj+AVl13PchmTOMhf4DbPQoIn4zWHAwt6356xUN6cD/Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":171888,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkF8nYACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp9ug//a/1UVvQOwikZ8MlHOuKVHFgQSQNXXCuX6e7h2zOb5M3g3HB0\r\n/dQFEVWZfU7BNN9gU5mkaMuYH477BKDoNAeHIvrIor0AHkoeyGd0SzzEGJ68\r\nOhUp8PAmjOWY236bvmGWidy8VUfvi+puop3is1rfyqCjHWcNaDon+cKh0MtM\r\n2Qs9G7CN7yqle25U3W7JDkjVA6TpTPSAKSQszMVhOoEIWseMPkD8+RplF3pu\r\ns/OFizxllCwDuI/Sc9/eAQc6RaigQO8g7cbfCP9rDTxJPlx5ldmF93N5Mt7l\r\n5ukHjQ41fWjrPNfkOhlyxnJOcODSS5p5Ny9BATyCm8DF3icF8ApzZFkIvE2U\r\nvqm2X03b/DwLAHqpvYSUAqESVPzGOPZpICyQmHu/OyFDyP/izNd1gs0/jobR\r\nSDwTfpXUUbW7155TUcwFuX+QXjuLjdEkY/pEE3PmnJhQNqJ0lhLMA7f2zi24\r\ne7HAPBtn5XR04LYWzmGQGJFYbRkCipJStzauy5AmZOXOq9soWjvU1ZcymZ8f\r\nQCM4OgdO8H50bK3/XvLzncJOcUowVlStYGTrCFns0dFC8Gx14cuqlMVg6mhU\r\nP+83pJ+DQsj4vWdDRfdXlmzDy/EwNQru/NmzumHz1yGTD9L9roqAquiTVUX2\r\ngn+r5JdZLg0ej83ENiAak0AOKBYmOfFTGQg=\r\n=HM6C\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"60c37e1d4526c51973e28cbcf5af688552ed6b93","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.294.0","@aws-sdk/client-dynamodb":"^3.294.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.17_1679280600175_0.6807214083677491","host":"s3://npm-registry-packages"}},"2.0.0-alpha.18":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.18","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.18","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"533474fdb3ec3851ba7c86fe9a1e63aa46f68831","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.18.tgz","fileCount":64,"integrity":"sha512-0BewMv7fFpL39r1aTCZN+yFrlpXmX4I6fF7LpCdKKHO3L3cfZ4RemBlZD5NEjpvJe0GioQWyhmlMOJWvjbImCA==","signatures":[{"sig":"MEQCIFrHEoA9UHyDmLAf5HT9bKyn2+25lKQqqBgS9jLWWO/6AiA0RI56LDmwkpmA4MDeWq965iSbww+hG1yWSengKDv0xw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":185217,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkG2ceACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo8xQ/7BIttbxY8bDIhsVVHcwy8uQaF1HjJAUxVibdZ+REZjMqMaAr4\r\niOM5cfD/+Y0VoRT2dFLeY8c4mwNcvftQAVRY7oOHgd4oFxdhK5vG/p7hhyt/\r\n9R/raT5nNJlPDfooYM4Qc1IyQZx6sgOh8SAub2RPVFSOdKB78IfCqDIWLvC/\r\nRlVSaGsLZa4hW9Dqo/6PBIbjz4m490EFsYkySSa6KA5INEPntINvEPXUgWH9\r\nwgF6gE4pIcbK3B9vO3+b2o0oHfvkt6ZefOxiv0seBNZQRoDWMID4HsbhfQ9R\r\nIOCCo1+k+X+j0m3HN5cqHOtC00LCvBMfvgtm67+64/51ke3FyV7gqe/2uaKt\r\nuFFkSsAtAkAVWs5QwaQ76mzvyVzxmwOZE2uUWWPFMKl1FSULPgoIsAVPlpW0\r\n1M21kGwmLnCUDzs0b+X2HOJEF/QeWGwaBetZ3RukfIHaVFaRf4hfQ8Tyw/AX\r\nAKNa9bkesqgFfniTP1GPbrxypC4yvDquZHLKOD/KF0OVhR61M4Z11tScpHgW\r\nIGhvhjncK6M35WLCxYXENwChe1aDcyoOe+/KPkVURCDlLUI9a46mQ0R8WZrN\r\nR7b/OmZlZqzCavTLU9PbTp5PiEB10t+nXfA1Fbv+AJOYIjwn1AslnQeWCs5M\r\nlkMBHOn+AkVqFNwx1MtcTOBncbBuS1O1l8I=\r\n=e543\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"c42af2e3cb58f03a194e42110017c8dae20fabc6","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"^3.294.0","@aws-sdk/client-dynamodb":"^3.294.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.18_1679517469990_0.34568483063903077","host":"s3://npm-registry-packages"}},"2.0.0-alpha.19":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.19","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.19","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"d2f7168aad2000e368012ea7d9daf79d7f54e04d","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.19.tgz","fileCount":68,"integrity":"sha512-+PMmN+U7vvoJrei2Y0Rru56Gso96n+p1RXakti4hzBpALt+BHN25NYGJBwTFBtwwl7wfMbqkghn6zbDtPHGhEw==","signatures":[{"sig":"MEYCIQCtMTBtOpV4LzffGyScJFQd/A1dgCMY/bkZ/95bea8/zQIhAJxFZif+4bCRty7kv3kK1XxUZZD3K5Wp9meBvKMAPNPP","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":190248,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkHKjuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo9aQ/+NydayUNdB4hXMDRFV+qeqgfWO7Hbjk/6QDmbunTnD/TSXWWO\r\nXVXA9hUtvgn6ihO32AUsANW96aN2B3n4LcFyuVDrHHa0D1JWvXHQSb2wK6cy\r\nLX8ur+VY0ATX7sugtYC7hOmhatl8zL3XK8evsMDtg01lDCDyDo/FpCaE+026\r\nzYd3vcLU3KwTtWKJmTl1Ua7yqSfRZxmdP6RxO9HEWfLW+Kn0ZX4ndeI96uOo\r\nwR0XUfri8j+AuCOqWeE/aTP/QfLSDOoijSrTOcpcNwWEBUzXt1poLAR5FtKn\r\neL33cScKTyfyaqZP1zOKQ++SGTqiPKsW+UYkvR9vdAXEOW6EffXIJuF4Fn/t\r\n/2W/GeU8zjB/60hI9TwMtfSgzgEzlPofeR/nUdwsFhZ0ALL8eLqg2hNbaS4i\r\nwwQZPsews8zYuJh8bCTC9Ym/zKyxTjTF51/ZEESG9YNhlLPY25Ic9xhZ487D\r\ntPPKG2XxVuSzw1bh4Wh2/Jj2Kprcf+lkfgr8HNS/lZf1US/a7ihXQ3sueK9c\r\n1xDVaVnpMmIYLr9mYOVXnYbV5W9yZ7MMQcMWdsMyN29HkYa6O5hoOV/4d2Wc\r\nN4zq/zjF83GXqj/llzC/jLfNV1nBaVHE2QCq1O5OTNl+tgZF9xvwSzRo0YCB\r\nmFLC9k1xHix6ARwHAKBJc6CCiRnFo1rerG4=\r\n=zuyk\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"7c719395a2c98a829e0260493fd59c868f4ba950","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.19_1679599853880_0.8116911202789623","host":"s3://npm-registry-packages"}},"2.0.0-alpha.20":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.20","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.20","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"aa03a2ea87b4391961fc27136bf6f3813aaa9dd3","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.20.tgz","fileCount":68,"integrity":"sha512-bDRYwzevB0NH15vFixfPgXFLFTOipeywTYdO4YwJnFj1TcV5tLVsRS4jUVPNyl4DeJ8aXx6JcxAmG7sZZD7Glw==","signatures":[{"sig":"MEYCIQDIOG7KOusFLvolWf4eQGE0+mEwEnOuA10viR1xfFILaAIhAJL2byULvBKRgRHAjTYjfOqd+wkKk3f0fR+zl7bXTfs5","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":190982,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkHMSpACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqmnA/9Gx/CqfiR++nQ4hnnvEbGJtQReZ8VcEaoVr4s7H4k0GsJVlhh\r\n44Ezx3JKSloUkP5PsBBcl0IgRmpXRmK8gnBC92/e2emqgS4ISCJTJ/fckS88\r\nYJ3IyHWkyErHixxld4Mb1LOQXhxUI3zxljDwIJUzMAKn9cbRwsQ32iwOAyGB\r\n+5Ue9/UtTQAN3AiFln+4X8yi32XCzOxWODr8VWydE3y86N8jiA921+13mlHW\r\nOT9iUx3lLAhVNqu2Efa0DxZeYfBzusWAEBPzFdn49Dx7HuBinpH8hR9YFOF+\r\npi3SdaaQShXMCqUoVF31Kopdmzk0F7S9pZFZ0FNTMqjoAnW7NCXeaIB9i+W5\r\nwvb5eXs9Y9xpXWus5CdYSGuP9pj9k/q7ZNDUfcw+ZbjTXX/tomRUfW2RfqpV\r\nWRDuWJLRvdIIFiIVaY7tJDzFgSYBfMZ9JtHxlUc1JbNoqdL5N1fH3v0cLRLO\r\nAgCh4yrLnyStpyqJehE4bZBSd73hSDBshq+7toMTqN+5bUH6vuhnzCRnsklm\r\nODPrnIMjUjJrMPpaWPCQ6NGa22T5fz3qw/EFSu6SsHdmjwy3FIiffnomSwj1\r\nnxlSqPf6NmugcHqSPh2hjuAjjEFuOZkCw8mHEzznFoZR5FR0uBDZ83nI2zim\r\nwZeDJ+KrBWgw1RXfnK18H0tss/t5GcVOkYs=\r\n=u33v\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"5cb547715e731f22041d0c309a595acc8d9c7aae","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.20_1679606953366_0.9715564662018434","host":"s3://npm-registry-packages"}},"1.2.10-beta.2":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.10-beta.2","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.10-beta.2","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"d070393114780bdc59fdab71596f7da156eaf765","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.10-beta.2.tgz","fileCount":20,"integrity":"sha512-VXIdv+ZOR2Wz9l/Co9j92Wlal1Wd8Za35NADmqo75mokENE5caq87xMHBZSgFCC45gTuChbZPyCDL8oc5j1zOg==","signatures":[{"sig":"MEYCIQDClXqO+Di5M3wmZ07uxVjrU9eNJxXjXICvXN3FVmS/IgIhAOIggJ7JvxjVZFoOLdWnlD1Q+ZdqibTtm9iKHxJoGxkQ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":136330,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkHMbbACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoL6w/7B5afvmiaa9xh5IUI/3Zv+2fZntMS3QXS+wad5GOIQ7ft6Scw\r\nyYy5QDf9T+BFvRHcuwVnZ2QBF6ZMnSK5eTvuXNj6vQFGW6miAdvHcMO/+Xt2\r\n0+mLz0YCXjsr7yHFw5mLf6DxK2gycms58uWMMtxA4Tg4VrEVkaLz+Zdzt1Xx\r\n52cFchkXStC9sGPOKIgb+YKN/QsMoZ6yXnw0Iwkz4WDYmQqAhotduJcSFymh\r\nh50v5a9JOSJ9zgf+3xiAoo3i79/WLM+KlCJAvefzwSIiAwsuocn49AjqZHfA\r\nDhvYzTFk0nduqdb7P6W2VGdi2YkSsMfWwew4oBGrJJr6d+NZw8k2AYaHEWoh\r\nPlEQ2msoNUySJXhDcMb9m17HamC1kmfVOv2TcgaAVJQPoOAYXL7aqQonyRxI\r\nhm6WDxrUlwMN2mp4HWRJCmd5HdRnDKbATjlax6ofJgn9hFb8DzhX0KK6by02\r\nzg1vPkwFoa3oBQZBxYyRFeWV9mmbb+DAofcvlf6666f6PQzMFEcV3yImPQ+r\r\nX/l4RHCWxWw9yZL2jJgypG0ImPGcW672w2o+NApR8P+t76P1aEZo81xfzSSR\r\nAWdGYyV20eQecrWqyvAyUNSlIO7FF8eTuE7xbi3UVgLTC16wfisXrj5yL5Gb\r\n2CV9Hzbgi2O1mR025le91G9xl34vyiaK5hI=\r\n=8kXs\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a single DynamoDB table. The Class needs to define the two minimal DynamoDB dependencies - the Hash Key (unique ID, also called the Partition Key) and the Range Key (optional, the sort order for the table - also called the Sort key). DynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n### Example DynamoDbItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    static BaseTableName() : string {\r\n     return 'MyDataStructures';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    public BaseTableName() : string {\r\n     return MyClass.BaseTableName();\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    { CreateTableIfNotExists: true, Class: MyDataStructure },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(MyDataStructure, item.id);\r\n} catch (err) { ... }\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(MyDataStructure, item.id, undefined, { Required: false });\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **master**\r\n3. Update (merge) into **master**\r\n4. Merge **release** => **master** (in order to pick the last version number deployed)\r\n     * *this may have already been done but it's a safety check*\r\n5. Create a PR to merge **master** => **release**\r\n\r\n*Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **release** branch __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)*\r\n","gitHead":"2f098a8af00ad0523b687cf5a90688718e6e98b7","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo No Tests Defined","build":"tsc","monitor":"tsc --watch","release":"npm run semantic-release","lint:fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188.0","@aws-sdk/client-dynamodb":"3.188.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"eslint":"^7.32.0","typescript":"^4.9.5","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","eslint-config-loopback":"^13.1.0","@typescript-eslint/parser":"^5.56.0","@semantic-release/changelog":"^6.0.2","@typescript-eslint/eslint-plugin":"^5.56.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.10-beta.2_1679607515278_0.6149994577215527","host":"s3://npm-registry-packages"}},"1.2.10-beta.3":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.10-beta.3","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.10-beta.3","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"f1aa72813ccdc7bf737a75f21aaf9896f499066c","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.10-beta.3.tgz","fileCount":20,"integrity":"sha512-5wHVNSu72T0MnfNKDyAc0QddQEeGl9fsQI4tuCugPm2KoST0MwQ555c4nwTcAVk6A5uPvo4mkjT/kckLmEsZvA==","signatures":[{"sig":"MEQCIBX5ZnQRjHRa3He8n6VI3gHcnx8QDcdcBs2wfIJaB3WjAiAJKUz82DylVavmbGkqZ4KHjV71ikJ3tIx7/bqEyP425Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":136642,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkHMdJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo2Jg/+N0T09YdSgJBBMKJjU/spvjrwKygzL66MWSaUQF/D3kGktRXS\r\nOGB+oisPjqADE54YApH4fjMcYlvMaNvRAQzAedBs0HjLcEw6wDCWFNNTBwm3\r\ncPu8xfJ4qH4Sb5SFZEsyMA7/1InPFerTAvdwnJtmB4OjfKaKVkut377VUGEz\r\nqtdnqAoqCt3jrzvY74nlCRCJKf6D/RbJA7hSf2IfkzmHR8FXpA5ehOUhlvNZ\r\nq5BrjTxHdOytWOXeDGlQFBtHEWjUH/OhtKC50jAtt4u3HSXvC0v48qAuWkxV\r\nJALRo4Jo5NgWMi57eNjK4IOvC6Nnx+Fh+pSLywY3wi18bYbu5LeDA2KPrsfe\r\n+qlsWx6i/+wt4KU46G6Ke8WZcapCUC0RT8LkbMyjC//QXiEbfU8zxEMHbcXN\r\n9X7+AS0jgQItrCNIH54UK9ytmdFuTt9vauK6b786T+pSxBYEBH+JPQa8ZO8m\r\nAszt/1qJIYXsVKuW8Pe5ZUFEHCd/2Fh5B0kKUk+99Waxs+l7JDj097d/R8yn\r\nnkCsQajoDuOzFOxKKmQ0okSDOBxrBUiSAPwB2ilnVqBDsBttp6DOK4suklkx\r\nAXLqr0UIF2FKrjzWXtWwDxrE+Uo2JJAIWcWrIJ4e2ob9nTRL9DlcQEopUJZ8\r\nf3yYZiTmukW55aZ1ZrGZ5UKwGN+xPNIqQOU=\r\n=AfY8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a single DynamoDB table. The Class needs to define the two minimal DynamoDB dependencies - the Hash Key (unique ID, also called the Partition Key) and the Range Key (optional, the sort order for the table - also called the Sort key). DynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n### Example DynamoDbItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    static BaseTableName() : string {\r\n     return 'MyDataStructures';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    public BaseTableName() : string {\r\n     return MyClass.BaseTableName();\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    { CreateTableIfNotExists: true, Class: MyDataStructure },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(MyDataStructure, item.id);\r\n} catch (err) { ... }\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(MyDataStructure, item.id, undefined, { Required: false });\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **master**\r\n3. Update (merge) into **master**\r\n4. Merge **release** => **master** (in order to pick the last version number deployed)\r\n     * *this may have already been done but it's a safety check*\r\n5. Create a PR to merge **master** => **release**\r\n\r\n*Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **release** branch __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)*\r\n","gitHead":"651495f072fe8a57a0347ce59af1fd4ad013e346","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo No Tests Defined","build":"tsc","monitor":"tsc --watch","release":"npm run semantic-release","lint:fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188.0","@aws-sdk/client-dynamodb":"3.188.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"eslint":"^7.32.0","typescript":"^4.9.5","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","eslint-config-loopback":"^13.1.0","@typescript-eslint/parser":"^5.56.0","@semantic-release/changelog":"^6.0.2","@typescript-eslint/eslint-plugin":"^5.56.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.10-beta.3_1679607624871_0.8866786842662449","host":"s3://npm-registry-packages"}},"1.2.11":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.11","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.11","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"4b06bc5bcb5ad127153093d7ef504b61e2d63e53","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.11.tgz","fileCount":20,"integrity":"sha512-giL2WcQ5z+z4i92jWwBtoY6cn84VLh3HUCoJPu2HC3d2++mfXAkYheN1wbY7PPvYVvAYKOuDUlVKMcAqa6iMxg==","signatures":[{"sig":"MEUCIHBFWv1yb0AmzisSQpF0h2HCjYYgcQa86vWKe6KDOKspAiEA8HSso+9UNR21fpFLhW6oiZTwmHh/LAcEX0ZS1nMtt2s=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":138315,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkHMf1ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrOpA//SWQGMrym51uA+41A4e0NsegwxSmS2ILxixtvGCqGkvaayWqC\r\nIgqrggj2tqAc3uxMudGc3ZSpXRGwYp/jkBLNtzRi5GbmlzpEofW0mGFrYCEV\r\nqbPaGZg2YAgFmHHRADZr1JB8TEdEJpvQyQ++JtPInROECU7Zjp3y+8w6BVJ/\r\ndSl45YBOsGxjQGasKVUgRdxUPQrMMg7fQq7R7Y0xO16HGaQeYzEqMq0P5+03\r\nAP8csqG77quHhYgYE1f007AP6ZKhGaRsPNkfGQlwOOfCHVQcnMbBNFI6DDFx\r\nJCIRw4+R1viUe/Xu8bV8NFpiXZdGg18M+26g4HCXiL3N9DpYQ155nzLVM2Fb\r\ngkAjD2d6i9+gKZPRKn6bkzgetcCvBuO+LIjOgTlgOw26ex9LJVK023m3e5nY\r\n4KibxFJ2dw03HdtcB/Rs6XLoLMJO2b/jQcHHKHuRy+YA5RpE3JDdjDQvjFzR\r\nYr+YHTuC/6MkVlNAtbrGQjgL+4Fyp29IXBn5yZn/uWkO41E5Gq4CPJqFs6Lf\r\nKLSR3g1YzIHqt8GqUzWizzcQInKxuYwwBoL8+FR+40cLfh/t7/oqGzQZw2YS\r\nBDUi8PM2w46ZPWthaMCBk0y6wCWks2oaaXS4c+GrfctpTZ7g9ZoqKPaeef+8\r\nYbezQfKjdRiKS/9JjNswij8SE5NqSjXbyh4=\r\n=IzLj\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"0564b3e314c02f9d891ecca4f9e1ab926b8ed938","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo No Tests Defined","build":"tsc","monitor":"tsc --watch","release":"npm run semantic-release","lint:fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188.0","@aws-sdk/client-dynamodb":"3.188.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.32.0","typescript":"^4.9.5","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","eslint-config-loopback":"^13.1.0","@typescript-eslint/parser":"^5.56.0","@semantic-release/changelog":"^6.0.2","@typescript-eslint/eslint-plugin":"^5.56.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.11_1679607797019_0.7218308018528861","host":"s3://npm-registry-packages"}},"2.0.0-alpha.21":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.21","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.21","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"103f893da193b764852487bc1a862b72984dee6f","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.21.tgz","fileCount":68,"integrity":"sha512-kaOMiw8ziXjKZfTxdA+JCR+EdiXHDDWYGPx4MWYhCdosApLeX+P5XoauBnXCOVAXS9A8LikrAT/Iosf6G8K+Qg==","signatures":[{"sig":"MEUCIQD+ZRrwtaLXAjgNJLud7GWfUDldwJXsA8I7Kxhth6aprAIgJQ9dKXvaTEBInbNZc3bP0B4CI3NO8XkWpMWCb7itQt0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":203267,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkHebNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmptig/+KOsyztBjEbgywvq3P4pA1upZK/lNem7YpUHv5d0UZ1Gx1cOA\r\n5eZe+F/sEmQg9uePEq/z2ki+XX034oV/WTmF1A/FFCHwZuDovGsnumX4TCZ8\r\n0/aZx6rLyeDdmsQzQlT1xT2xfUTw9yFbcIEamcQYywWGVgGGOGYTHOld9Ut3\r\nkX1PaDACkdggTCjKCmPfafB4h+8AMJcruftR+HYUrRg6ag/LV5aZEokw/Zxl\r\nj2u9sPx0BFjvT2tnY0Tw+CdSmgdqvMPbhJyyA2FDVHAuN0yjlWD+kMR03PhG\r\nMPqQ4CjMK7+CBrp/EbWCIvX2SlLzFvmCBrfU50KDEH6k1ReHmol26GOFOZbH\r\n7xsKyxT2Trdb5B6z+z5DrTXX5JYJUH+UHYjoF2G/HBWx37JZ6/QZRx8DqMC0\r\n4S0PpHenrS9dADXrXOQUI1Or/WO5ZwFcY3vRutug+UiaOFhstYo5QzZYNe9V\r\nadxT/s6ehHT1823ltBpwSSUneRFQuSKf4v7mBw4I0AqELiFa00YnkmYGXp6h\r\ngCh8XorNmqd1ct5IvwVjFzV2fD1AaCN2xmHAQEERT4wQxlZKBTZ4OYwqoTYy\r\n/GNVMvT+BNHek8emEkFtoUez3ZjJ1bOkKtRF5EXGxqcGp0+S3DTmhEoBuQG6\r\nIDa9irC/ON29dF9tCyTv6vNpbJcd/3SJHKs=\r\n=en2z\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"584f660efe060d72f17f459b9661d4d9506bc23f","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.21_1679681229078_0.8449186019545847","host":"s3://npm-registry-packages"}},"2.0.0-alpha.22":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.22","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.22","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"8fd43786ede221cd647af2d192966c5219038693","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.22.tgz","fileCount":68,"integrity":"sha512-ZSf/s5rka+iy167gs8GiJf+ac5MNsy221aOdKqLiUPJ+rDgqh3EKTOWylhHcKhlbslDBbh1ZuDPKe5CN3g8Y6g==","signatures":[{"sig":"MEQCIFp1Sc9YxvmvKw9Ja6Jg6pCJ3v68J/daqG+kwSOlzxIuAiBujUEBKHAc+J0RMp07adIFYorfLY0N44oKUoOw/8QR9g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":206556,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkH1UNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo0QhAAhJbPdV7yDVw4YS3CB3LqPBiJFd+vEY/tpQCkf2gH44dPGXfQ\r\noXqILOr5ETIxqXOjIJhtX0oJHhus5cqGf1/Rm/xeEA5V5whVV9i8z5DTrpXc\r\nNBsE6JYaAgwTIohEEGbsHes111itdleY23cu68kKF0HXkx3vjSxWZgmWMtAt\r\nOG1WCecfn/8hP0PXqP7WuiOliH4Kf1NBqYUY8PE6P4T1a+i5UzWpsU+sh32k\r\ngm+9Wf25Y5HTQ5fwdgcHHZ/MOR3pzEuSLwy17DPGwNhbuNcAUn6lKnKBsaDy\r\n5cn7ueUGsbe0dZSdbgGwhR/EhaEfLmzAuCWovSv0FCoRiHED8E5tReis7l4c\r\nIK7m28uiMLkVSFTcUT0MwRRQrmKo5aI1W0vFQeWMDbWWOVYhjggYy0apEYtG\r\nnj5jtCQWgaoiwahm6QVCF08k0uDhZj819pTX5m2va3JicGHxTlaRU/sFsK7t\r\ng7AIS/+H0E6FT2xksX5bxc9UxW3L7bR0+pCga6qxofYZ7GL5ifs0XboRFWFp\r\n/tRFlI2XEAJ0EToWb5Hq5BpNOSy1v/W3fWiigjMvHr8t1DrFFA718MjW53Z6\r\nXjpwF12WC/A+elDCs0Rw8An2anLYXZ2oblkqT5yylEKxsVyxV1hXtR0A0VGb\r\nxkba3c/D1pFP0RQIKjPTo6R3bQFnuWvGA3w=\r\n=iWWW\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"7d8dc6f2157a359f002842bb76f506c8203a4e5b","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.22_1679774989423_0.6886756724029428","host":"s3://npm-registry-packages"}},"2.0.0-alpha.23":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.23","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.23","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"3ef359fae737e371e07602968e9406cc06b75f2f","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.23.tgz","fileCount":68,"integrity":"sha512-5j0f/6itKHUL+ntjvk0eyp1Y96Tg1MZsI7aAUfca4hcE2H6DQGJZzDQVVcpI8uwEHmKDEQVqHUETDB0t+TOF+w==","signatures":[{"sig":"MEUCIQD5OvAlFSLnxvct+EleawFzxlkUoxlkRvAy1z+A5dEkMAIgG6mmqpjOe0mOY5ovnL7LiBcmw9L06Dyxm4rlEgNYdzI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":207239,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkH1jeACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmriAg//RfO8RGjT2P9h6df0a0pTz2glxmQHN7KP36Bpf4H6QnYMwaVp\r\n8UE9FfPDqVC/+KqrIZRb2btvEEMBM8zBogQrEmqh9fJqnZHqfxjATXfjJkXm\r\nZax4FSLm8kXNUj/M8qGds5I+IqcLA2lRDmP1u3IV6p8h0IhJU0Hsp0gW8Ma4\r\nSjrQ8hS3QE4P1faREQgUYboRxtSVcqDSKrtz2TQkGT4ufYYr0KoLrbzglRQ1\r\noutt/HBfuP/Q7pdonUsjq13OT6PAk1vCCj9jm/at86KFNMzpj8wg5loLZVwh\r\nq150rSW3dMVIsekj4AAZo1ZQoUp61auLm870ZpmiZ+pNyGhnrmD2UGUBdc91\r\ntWiM8/y6ZBA+XQzLA0t1S6zUsrw3cvK7WqdwastGmRonrGttyNnhhJIHXYMp\r\n90I87fdN3wP80cQPdDauzmT+KI1+rhLxn7+qBUS+yROpvGCeDr1JzMINT6Os\r\nyv3BAivu8Bw4SzxA1n2UtcpGsviO7F4e3NQmNiOZKzWJSDt+l+zk1oR3Q3mc\r\nts53L6z3GRFMLbREoRnO6+C9fO5y5m+NgR8DxErEP+1LJCqYViTPDWq/+1Yl\r\nO2+5d+iy/oZBvmRLQfxT6xxQJWWISlFaR/fTwAXuWD9WiLndR24I3767lGVg\r\nzUmo8itlmn424r1MlW3MgUzRf6ygi0lZZCQ=\r\n=zNe8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"1fabc8557f11f362660f979dc429f36e4191f116","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.23_1679775966349_0.21867031677297755","host":"s3://npm-registry-packages"}},"2.0.0-alpha.24":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.24","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.24","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"2a8f7b522f2fb174bc5fbaf53bcaae1af2f689f2","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.24.tgz","fileCount":68,"integrity":"sha512-0ieQbOQ4fzl3YD8I6g4nJQYjwPz5fIzSmEB9WslQEfgKwZv/ncyClijal6FN5fqcbUbyF2KpUUiX0eMAqEqAjA==","signatures":[{"sig":"MEUCIFQKaYWr+IxNJTPyNyztAQFyisIMc3526Q99wTwJhTMbAiEAuTMk8GXUWAgPddvjGt1y1cVhNDpNJQ4YfMqsf/FqGlY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":207466,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkH3yUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrilQ//fLPR2UNutZ4pG0XRrg/2ekE1C5M8KqjxRzhzkWgyEw19RbUK\r\nAfofDxC9Sl20pNkUdCS03qvwCuEqEEMHZZuZ56hY19fQCipS6c1/zRMDIKnk\r\nmoSR/KCXTLppawGYPZp7S/1sYB6PXJy7bI6koe91GubJIrSNRy0y7AmgK8j/\r\nDoPw02tA2wQMH4jZLKwZz7TqsgNk0n9jzj4r/ZHbInsFqfs3FpT9A3x/IoPT\r\nZE4sS2zXon0oxYSFlNl8C4SVUvg2cXvJHfLAqk7g6GsqmRnihNBqi2J5P1LS\r\n6DpXOV3V6oLBFEw1LsVg4sGBwZ9mv+Ug4SvDFeR5g6UpTyCt+Y5to79Mfi+5\r\nXOON7MfptuYBsxcHw8/z8T8fCwakuWoSz5EibpLwBX2EMpNXdBqGctjmtQPQ\r\niMbRSR18SpnDa99p0UnzbU61fez1XGfpvIH/OgrTleWJl1BJwlN0eqibaFWX\r\nNJB7R/UG8uhRINxgelgrlJ+SybWONBWZnnpEHVqi6Od9tVGVfQaOeiQ2TTgN\r\nn6BRgVvSbr1wb3aAVkUOP+/n8IptY6ff2vdhgjTLCWNoJgnleTzaGZ3/iRfz\r\nfrpIekYXPd2z0I+K/mbegpTntl66zQTtnFiVFefKJH8evtu8qCJ5QtFdNrPI\r\n/CiijqSv6m8Ev1V1wEJO3ZLPAVgojwo3XVw=\r\n=EUsx\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"08259d26efe07df688d9aa486470c3f66c5c1182","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.24_1679785108258_0.12269235019598601","host":"s3://npm-registry-packages"}},"2.0.0-alpha.25":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.25","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.25","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"e53a9c529049f43945cfa4871c502f8a54cc42a2","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.25.tgz","fileCount":68,"integrity":"sha512-3en/bcyuegxlNDktbtzWexyfjXCRhuMhVj1TpLEPTqGkWkCGWjDVZbCpr7GiJcKabM4dHp8aBvpMTzbLTjA2Qg==","signatures":[{"sig":"MEUCIFuO+GfJO/xEETKUsRavGj0ZXzIWbW6kawpXY+y/e8RBAiEA7tl0njEUUAkXzEaYuI+sWRF4bTktBWSZEsSugASIITI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":207713,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkIecLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqPKQ//a/60K2silUFskvllknF1g/mgnfHVeaYHuMYWe5Swldkz0Ni+\r\nFqiPREmmCzx9ATFAppjd1BpujwT4X+ds5xYEXWVxGzTLJ2wh86NXYfSwaeV+\r\nr4UAOPUMM3end0XysHYmUaBE69Q8u/mVTRgCJ7YPcbHsVE86pQCfxUBZlF1u\r\ngftxrYyZFim4YvlHQQg9FlbmTSJtQ6z5ulMKFTyXa7YvTiqsL5xaYjg708Pa\r\n27ccqwAwutiYjtuzacgtOHAICquO36Xq8nczTuZ8gB7JUOull/QtydLWWLKm\r\nr2uwYVeyI3t6C5DLM3Cwxsi5Y/wdcjZHPYQW775/7bySeLMvI7rOXhgNdip1\r\n28Dh12YReIn6fFNbfPuld0jDAHfKvBDxp/pTO8TTJI4cHtfD8baeuiTRJEN+\r\nv6EBMwa0opkksX7D4IOOg76LUH4zKK8wG0elPDM53dPx9E5nKrInxjP0j2QR\r\nMbB5aI+BIYTe/aI3SrM0duapAjfC3HwPZEppcebttz+5s2OcqVRO1MXP8t/Q\r\n5jJhkwwHlioDZgH9YSfOpGyt70h6uG/FF6nZWt54ox6iCb9H3AxY9Az6c0dy\r\n0r2ein6vl5gm8ugy26cpeelP12BubnPUIFCloMzDzoMJR/XCGUoe8GiWeYlB\r\nHMlnwvRjn+1ViOIHgssapLLhbX6GO0er0K8=\r\n=5UjB\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"42c2a7a9aa33cf1595be95dbb466105ebf45dee0","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.12","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.27","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.3","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.55.0","@semantic-release/changelog":"^6.0.2","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.55.0","eslint-import-resolver-typescript":"^3.5.3","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.25_1679943435394_0.7538364692092832","host":"s3://npm-registry-packages"}},"2.0.0-alpha.26":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.26","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.26","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"df3f142403f8a91705855ff641ba7bfaffecbff1","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.26.tgz","fileCount":68,"integrity":"sha512-KkqfTLm/f5PCPrE+grakMREUjyU0Vd1kMWJC9PD2CqN6KAmQYeEjDwMq/YMjh9feLbsxOxXfMEUc/Of4vlPflg==","signatures":[{"sig":"MEQCIEjYjG5sFikzhzNyqcxwUSwNF1VGOpPKMOy0n1W2a0JLAiBh4fpMFPToTPiFw1e7TxlXXUCzQDNamCM/tqUjt/eKJg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":208615,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkJKFLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoAIhAAmrdKiDfO0YVeHyb39SA4mOFYls3ZbsRol38MtDofXIemkV1x\r\nI4ml3xcGfB8wmG8FE6IG3LoiemboIINKSUAdOa8M7z0JSbaUcCWv6hpcxDOY\r\n97qXehKAHZ89iKfsd/Ei7rDMuTR5GuoKFWOG6dEP3rTSiuXWHPBo7FVt5Ksz\r\n4h24VyuP3B9TCHGGADpPRLEeEftbdDstf+56S7hoFDzx19+eJkZ/NiZC21WM\r\n2R25hOWDgbdtIWehlnVmYrFbhvwXxCZGkgDGOcp2QWqX7Z7JW1WKyAyBE8EY\r\nEkAcJTK/0azPxlEdLrukwrlnIiZxldj6uvPjmKNQXmrjLhs/hwRRGGmAZrcx\r\niNpxVjYIl2zDS1fnth+Oygcpa0+QyfjAzrdNIpIbmR7hzrNhxTVeNQ+sc3g4\r\nV3PUdNNStzWxXT6KPyRa18rJA58uKivSd2HbKrnupmprhA5AszJcDnbeKnrG\r\nQShfvpXr6bCl1eGxLDJKlWTYex9glpunpsthu34Mj4ylgPG1LWzHn8JZlmiH\r\niiZ8mNcF2Ab2eCmQR09XyzCH69EBDdIIj0u2jXjmRCUk0/2FaEwrIxEblcbh\r\n/UjKaTvyxZqbT3VihkqbweT8P9CZpMpVODnsm5La7UxY1y/clJJOBhXsMOWp\r\n5C4dDwWNOSCacItKD0bqyX77KMB+O+ejALg=\r\n=dy6F\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"89e98440d3a0e2bcd721585415c023e26efda20b","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.15.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.4.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.14","ts-jest":"^29.0.5","ts-node":"^9.1.1","typedoc":"^0.23.28","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.15.11","@types/luxon":"^3.2.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.2","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.0.0","typedoc-plugin-mdn-links":"^2.0.2","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.57.0","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^2.1.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.57.0","eslint-import-resolver-typescript":"^3.5.4","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.26_1680122186826_0.9249919657654961","host":"s3://npm-registry-packages"}},"2.0.0-alpha.27":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.27","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.27","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"c300392ad03812fc6a25afa4381065d80026ddd5","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.27.tgz","fileCount":68,"integrity":"sha512-RxNKTvZT0/kLcJ/pu7E/Cxb0uhol8FojfsJkz0JyavY2tRi4FdaiHTsQC8jaXnkTU0OFc5N/aabXwabK2/0N3w==","signatures":[{"sig":"MEYCIQDh6RV9xpMax8/Zwkh3yDFfnlLWltMfJDt6bZtib6gtvwIhAMAD8QskEw7jlCkNHvDhBWWgESA23Ry2FS1JohvqIpxz","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":216150},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"87ec4edcec7f9af939313b58b4dcb764149d2062","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.5.0","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","async":"^3.2.4","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.19","ts-jest":"^29.1.0","ts-node":"^9.1.1","typedoc":"^0.24.7","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.16","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.59.7","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^2.2.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.59.7","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.27_1685203457174_0.2800027482765117","host":"s3://npm-registry-packages"}},"2.0.0-alpha.28":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.28","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.28","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"24823c5e4c4f22ea36458117f730121958aa854e","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.28.tgz","fileCount":68,"integrity":"sha512-t8tFCIt8qiKUcLj2p57c2c6jAFMuIBgvfWdI6y/OUhu2pcGGI/zLHj1tpleRNXL5CKWs/DndbfQJ56UxoOi5Ww==","signatures":[{"sig":"MEUCIHO/s66hAkTgqPx6PGMdpqKO7omltSUPe7qa1EVDJ8N0AiEArGfSNWauf4QoJHQcaO4IOpGF/NKAR97rU3iQMQ+EZkc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":215555},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"cd7f59bf94455cc5875e463373e7d3b4fac60043","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.5.0","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","async":"^3.2.4","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.19","ts-jest":"^29.1.0","ts-node":"^9.1.1","typedoc":"^0.24.7","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.16","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.59.7","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^2.2.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.59.7","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.28_1685209000465_0.4604385746749855","host":"s3://npm-registry-packages"}},"2.0.0-alpha.29":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.29","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.29","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"6b8be104d2d3a019996cfe287f12920051c71b59","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.29.tgz","fileCount":68,"integrity":"sha512-lqnpX0bdm3kKWThA2v179d+D7gJ608xi/NlNYTfJaKQKtOrceeM3aGxEbLFgbuE3WWx6Q5a0cE5lFEnhEyRaCA==","signatures":[{"sig":"MEYCIQC30rtNOwDp525pYN4vpreo2NhZkf3GSSnTcJulhGxnbgIhAOHCVVvX4804D2oT40uINDRrm8fLOeg7cVjfL94FmAjV","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":215406},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"ec1b5f616abebb99e9cc8504d771dce6626756e5","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.5.0","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","async":"^3.2.4","dotenv":"^16.0.3","eslint":"^7.32.0","esbuild":"^0.17.19","ts-jest":"^29.1.0","ts-node":"^9.1.1","typedoc":"^0.24.7","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.16","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.59.7","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^2.2.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.59.7","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.29_1685374685771_0.06537827457887668","host":"s3://npm-registry-packages"}},"2.0.0-alpha.30":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.30","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.30","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"1656734e3d0865fc9f5f7a8c7010a60e123fcdcd","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.30.tgz","fileCount":68,"integrity":"sha512-fYypRdTZLbrrDu/H6aJw4V4oJ1iYQbb8OImYlYxo2XM2cwaK4Ek3A7Izf3C0AojILQ2X9/TgAM9Y70auvM6sGQ==","signatures":[{"sig":"MEUCIQCqeBy6eqxKkxEAxIazzpfjbofV6GRuTYSrcZkBGmGfrwIgeNQ+ZfLPECoVvGGGsmlLHeGGX+tCzZM0uMZrm1za45k=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":218513},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"69b54e59c1c84faaab762a864dc3a4a47024c718","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.0","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.5.0","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.5.0","async":"^3.2.4","dotenv":"^16.1.4","eslint":"^7.32.0","esbuild":"^0.18.0","ts-jest":"^29.1.0","ts-node":"^9.1.1","typedoc":"^0.24.8","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.17","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.59.9","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^2.2.0","eslint-plugin-import-newlines":"^1.3.1","@typescript-eslint/eslint-plugin":"^5.59.9","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.30_1686499312799_0.796392041674264","host":"s3://npm-registry-packages"}},"2.0.0-alpha.31":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.31","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.31","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"99b3cc0f6e1b44e258ce5a491fe44e6576bf2d14","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.31.tgz","fileCount":68,"integrity":"sha512-TaoL2HXH3BZ9TR5AlCvOGxJKAK6Yu/eTyPURNn9YHAFCokR4XX3mRoeJjiffOjbiJrVpqnbsuBdKYRgTNI1cFQ==","signatures":[{"sig":"MEUCIQCQJTc2aCmZKxvlYN2PDg8hBDKjap+Y8h3r08SiErL6pgIgQICV3MTwYszgD17Y9jmHZJsOV7+/XW3b0tnU3rlH5Ec=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":220454},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"a97b6d1d7ba3c7aaa71f3edbbc9b0053ecd36f61","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.1","dependencies":{"luxon":"^3.3.0","lambda-log":"^3.1.0","aws-xray-sdk":"^3.5.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.6.1","async":"^3.2.4","dotenv":"^16.3.1","eslint":"^7.32.0","esbuild":"^0.18.15","ts-jest":"^29.1.1","ts-node":"^9.1.1","typedoc":"^0.24.8","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.19","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","@types/lambda-log":"^2.2.1","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.62.0","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^2.2.0","eslint-plugin-import-newlines":"^1.3.4","@typescript-eslint/eslint-plugin":"^5.62.0","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.31_1689866714924_0.5419364956885706","host":"s3://npm-registry-packages"}},"2.0.0-alpha.32":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.32","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.32","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"d439063f9849c6fc4e926d7681046bb8c7a70472","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.32.tgz","fileCount":68,"integrity":"sha512-5h+Su1UDXbBuGTtyVRsrvZ3mPfT/DixImdd55hlHFL5D4ZJNLR5vKRnATuNIAJoHvk2iijHTYaJJFM1yZkaaGw==","signatures":[{"sig":"MEUCIGxg5oPSUyp6ITjWHBld5jgCxM0GQBd7PUER8rlk4hyNAiEA84vIGtBCHUA6H0ar5YFzLuZGWZmmbXZSOmfBseS0W5U=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":219812},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"86f421026b1877670bd599a317432c326e7729c1","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.1","dependencies":{"luxon":"^3.3.0","aws-xray-sdk":"^3.5.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.6.1","async":"^3.2.4","dotenv":"^16.3.1","eslint":"^7.32.0","esbuild":"^0.18.15","ts-jest":"^29.1.1","ts-node":"^9.1.1","typedoc":"^0.24.8","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.19","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.62.0","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^2.2.0","eslint-plugin-import-newlines":"^1.3.4","@typescript-eslint/eslint-plugin":"^5.62.0","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.32_1689867327898_0.9552479830036795","host":"s3://npm-registry-packages"}},"2.0.0-alpha.33":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.33","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.33","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"7a587144326b1c6c58d040d7ae019e636c71ff7e","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.33.tgz","fileCount":68,"integrity":"sha512-mLpq8piRxxyaVUJmSMKAbW5cc3ZsSBZgHBsgsyDzlT6EDRyYaeIr6LhzJoNAb4Dpu/SMP/q1oJ5DvsoUBcGJIw==","signatures":[{"sig":"MEUCIA8Gh1qU72AQ7ghN3zCJOo+FIj3rCI+V3VvgxjclkMFkAiEAwEF8kqyNMs3Yp6IFr2tB0RTIuMy4+n7eMDXLuu91DAI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":233841},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDBItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(\r\n    MyDataStructure,\r\n    {\r\n        HashKey: item.id,\r\n        Required: false,\r\n    }\r\n);\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"5fda5c6ef8fa5c7b14d2f8148da43eae364562ff","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png --footerTypedocVersion --footerLastModified","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.1","dependencies":{"luxon":"^3.3.0","aws-xray-sdk":"^3.5.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.6.1","async":"^3.2.4","dotenv":"^16.3.1","eslint":"^7.32.0","esbuild":"^0.18.15","ts-jest":"^29.1.1","ts-node":"^9.1.1","typedoc":"^0.24.8","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.19","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-jsdoc":"^46.4.4","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.62.0","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^2.2.0","eslint-plugin-import-newlines":"^1.3.4","@typescript-eslint/eslint-plugin":"^5.62.0","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.33_1689883452830_0.012192027340059086","host":"s3://npm-registry-packages"}},"2.0.0-alpha.34":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-alpha.34","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-alpha.34","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"65599e94afac950fc68a750b0edc31cd1f7b6899","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-alpha.34.tgz","fileCount":68,"integrity":"sha512-ACEC5T7Qmakky4+wQDyMg5DhWuP3RcjqH6xwWBA9n8VVrGYz3FWmSp9BciOJ0GJS+eKJ0OO1/v0cTiItJ/oRUA==","signatures":[{"sig":"MEYCIQDfJej94BSB6Jr192eoJLnMs4H0+UTmeP51V5FHPmsoHwIhAInQ+VQNqlZo+Id+Pg8J9kfjFkQNmqejgcWN8RbCRwgm","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":234960},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\n_**TLDR;** it's a wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs and all the nuances of DynamoDB._\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID. It supports medium-complexity use cases with Global or Local Secondary Indexes.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nIf you have some specific needs for nuances DynamoDB usage, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly. You can access the underlying DynamoDB client in the wrapper for mixed-use scenarios.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented so review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Documentation\r\n\r\nThis library is fully documented with JSDoc comments.\r\n\r\n**You can generate nice, browsable, documentation by running `npm run docs`.**\r\n\r\n---\r\n\r\n## MAJOR CHANGES IN v2\r\n\r\nv2 is a **BREAKING** change in the library and it is not easy to convert a v1 project to use v2.\r\n\r\nNotable changes in v2 which you will need to know if you have experience on the v1 library:\r\n\r\n* `IDynamoDBItem.IdFieldName() -> HashKeyName()`\r\n* `IDynamoDBItem.RangeFieldName() -> RangeKeyName()`\r\n* All functions in the `DynamoDBClientWrapper` have been changed to take `options` instead of individual arguments in order to make the functions easier to update in the future without breaking existing code\r\n* `CreatedAt` and `UpdatedAt` values are now `TimestampISO` strings instead of `number` values to make them easier to read when you are viewing the data in DynamoDB\r\n* `DyanmoDBItem.BaseTableName()` provides a default implementation that uses your Class name with an `s` on the end\r\n* `Scan` and `Query` now support returning the last evaluated key so that you can call them again starting from that point (along with `Limit` this is, effectively, pagination)\r\n* `PointInTimeRecovery` is enabled on new Tables by _default_ (this allows you to roll-back a table to a previous state if you mess up the data)\r\n* `ContributerInsights` are available to be enabled on Tables (based upon the config you pass to the `DynamoDBClientWrapper` constructor) but are _not enabled by default_.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport interface IMyDataStructure {\r\n    id: string;\r\n}\r\nexport class MyDataStructure extends DynamoDBItem implements IMyDataStructure {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(data?: Partial<IMyDataStructure>) {\r\n        super();\r\n        const {\r\n            id,\r\n        } = data ?? {};\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public HashKeyName(): keyof IMyDataStructure {\r\n        return 'id';\r\n    }\r\n    public RangeKeyName(): keyof IMyDataStructure | undefined {\r\n        return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper({ TablePrefix: TABLE_PREFIX });\r\nconst item: MyDataStructure = new MyDataStructure({ id: '12345' });\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n\r\n// Alternate Usage: Required - if true, an exception will be thrown for an item that isn't found\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        {\r\n            HashKey: item.id,\r\n            Required: true,\r\n        }\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"fe2c057e6c7ab11afd1fa2a24f65843f371979c3","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.1","dependencies":{"luxon":"^3.3.0","aws-xray-sdk":"^3.5.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.6.1","async":"^3.2.4","dotenv":"^16.3.1","eslint":"^7.32.0","esbuild":"^0.18.15","ts-jest":"^29.1.1","ts-node":"^9.1.1","typedoc":"^0.24.8","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.19","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-jsdoc":"^46.4.4","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.62.0","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^3.1.0","eslint-plugin-import-newlines":"^1.3.4","@typescript-eslint/eslint-plugin":"^5.62.0","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-alpha.34_1689885990471_0.5657808917094096","host":"s3://npm-registry-packages"}},"2.0.0-beta.1":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0-beta.1","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0-beta.1","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"b697606fa4c942623af52f7969c577111fed25df","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0-beta.1.tgz","fileCount":68,"integrity":"sha512-0V0zXaPeiqoIEm6nVnE0u3xpFCC+qOfD+/u4ssASWJpgtDe6hHx7skfgsmvUkn92o/ziPKc8gUVEX+p6S8FPmw==","signatures":[{"sig":"MEYCIQCPrh+sT1+gdz2susaSAi3/iaXxkIRi8ybvo33qKVqoswIhAN1JujPn2ei320dDkM4grG76NtXhbSaLskjrZQqRwquA","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":248075},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\n_**TLDR;** it's a wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs and all the nuances of DynamoDB._\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID. It supports medium-complexity use cases with Global or Local Secondary Indexes.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nIf you have some specific needs for nuances DynamoDB usage, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly. You can access the underlying DynamoDB client in the wrapper for mixed-use scenarios.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented so review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Documentation\r\n\r\nThis library is fully documented with JSDoc comments.\r\n\r\n**You can generate nice, browsable, documentation by running `npm run docs`.**\r\n\r\n---\r\n\r\n## MAJOR CHANGES IN v2\r\n\r\nv2 is a **BREAKING** change in the library and it is not easy to convert a v1 project to use v2.\r\n\r\nNotable changes in v2 which you will need to know if you have experience on the v1 library:\r\n\r\n* `IDynamoDBItem.IdFieldName() -> HashKeyName()`\r\n* `IDynamoDBItem.RangeFieldName() -> RangeKeyName()`\r\n* All functions in the `DynamoDBClientWrapper` have been changed to take `options` instead of individual arguments in order to make the functions easier to update in the future without breaking existing code\r\n* `CreatedAt` and `UpdatedAt` values are now `TimestampISO` strings instead of `number` values to make them easier to read when you are viewing the data in DynamoDB\r\n* `DyanmoDBItem.BaseTableName()` provides a default implementation that uses your Class name with an `s` on the end\r\n* `Scan` and `Query` now support returning the last evaluated key so that you can call them again starting from that point (along with `Limit` this is, effectively, pagination)\r\n* `PointInTimeRecovery` is enabled on new Tables by _default_ (this allows you to roll-back a table to a previous state if you mess up the data)\r\n* `ContributerInsights` are available to be enabled on Tables (based upon the config you pass to the `DynamoDBClientWrapper` constructor) but are _not enabled by default_.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport interface IMyDataStructure {\r\n    id: string;\r\n}\r\nexport class MyDataStructure extends DynamoDBItem implements IMyDataStructure {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(data?: Partial<IMyDataStructure>) {\r\n        super();\r\n        const {\r\n            id,\r\n        } = data ?? {};\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public HashKeyName(): keyof IMyDataStructure {\r\n        return 'id';\r\n    }\r\n    public RangeKeyName(): keyof IMyDataStructure | undefined {\r\n        return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper({ TablePrefix: TABLE_PREFIX });\r\nconst item: MyDataStructure = new MyDataStructure({ id: '12345' });\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n\r\n// Alternate Usage: Required - if true, an exception will be thrown for an item that isn't found\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        {\r\n            HashKey: item.id,\r\n            Required: true,\r\n        }\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"e7621796be4591813b40bed17de031b40ee2ea72","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.1","dependencies":{"luxon":"^3.3.0","aws-xray-sdk":"^3.5.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.6.1","async":"^3.2.4","dotenv":"^16.3.1","eslint":"^7.32.0","esbuild":"^0.18.15","ts-jest":"^29.1.1","ts-node":"^9.1.1","typedoc":"^0.24.8","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.19","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-jsdoc":"^46.4.4","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.62.0","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^3.1.0","eslint-plugin-import-newlines":"^1.3.4","@typescript-eslint/eslint-plugin":"^5.62.0","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0-beta.1_1689887452776_0.21645275479292758","host":"s3://npm-registry-packages"}},"2.0.0":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.0","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.0","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"f291247df669043a05600d843f5f7f2f72a4cc3f","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.0.tgz","fileCount":68,"integrity":"sha512-tguCueHcDJhFRAjLy0ZFg0vF4fm7wrGrSl4d/sixZN0maFP4tqsFy9iXUgeAg49N6TPuEU8e1HpQ1Fh4roN5Sw==","signatures":[{"sig":"MEQCIB5yUmAYTlk+G//Hu/E9T6VUczAXhDd+alhGiRGBGU0lAiBA24u4QkZAfM0Aot3WaKKwAzXwKqZ3OqwUt1WowTj54Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":247595},"main":"dist/index.js","types":"dist/index.d.ts","readme":"# aws-util-dynamodb\r\n\r\n_**TLDR;** it's a wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs and all the nuances of DynamoDB._\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID. It supports medium-complexity use cases with Global or Local Secondary Indexes.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nIf you have some specific needs for nuances DynamoDB usage, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly. You can access the underlying DynamoDB client in the wrapper for mixed-use scenarios.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented so review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n---\r\n\r\n## Documentation\r\n\r\nThis library is fully documented with JSDoc comments.\r\n\r\n**You can generate nice, browsable, documentation by running `npm run docs`.**\r\n\r\n---\r\n\r\n## MAJOR CHANGES IN v2\r\n\r\nv2 is a **BREAKING** change in the library and it is not easy to convert a v1 project to use v2.\r\n\r\nNotable changes in v2 which you will need to know if you have experience on the v1 library:\r\n\r\n* `IDynamoDBItem.IdFieldName() -> HashKeyName()`\r\n* `IDynamoDBItem.RangeFieldName() -> RangeKeyName()`\r\n* All functions in the `DynamoDBClientWrapper` have been changed to take `options` instead of individual arguments in order to make the functions easier to update in the future without breaking existing code\r\n* `CreatedAt` and `UpdatedAt` values are now `TimestampISO` strings instead of `number` values to make them easier to read when you are viewing the data in DynamoDB\r\n* `DyanmoDBItem.BaseTableName()` provides a default implementation that uses your Class name with an `s` on the end\r\n* `Scan` and `Query` now support returning the last evaluated key so that you can call them again starting from that point (along with `Limit` this is, effectively, pagination)\r\n* `PointInTimeRecovery` is enabled on new Tables by _default_ (this allows you to roll-back a table to a previous state if you mess up the data)\r\n* `ContributerInsights` are available to be enabled on Tables (based upon the config you pass to the `DynamoDBClientWrapper` constructor) but are _not enabled by default_.\r\n\r\n---\r\n\r\n## Terminology\r\n\r\nDynamoDB uses different terminology for the same two key fields on a table. This library _attempts_ to be consistent but the documentation and field names in this library _may_ still have different references for the same two key fields.\r\n\r\n* `HASH` key - a.k.a. `PARTITION` key or the `ID` field for a table. Any references to any of those terms refer to the same field. Each table **MUST** define exactly one field to be used as the `HASH` key and that field **MUST** be unique across all items in the table.\r\n* `RANGE` key - a.k.a. `SORT` key for the table. A table **MAY** define a `RANGE` key and if it does, items in each `PARTITION` (i.e. for each unique `HASH` key value) are stored in sorted order based upon this field (which defines the order you will get items back when querying).\r\n\r\n---\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a _single_ DynamoDB table.\r\n\r\nThe Class needs to define the two minimal DynamoDB dependencies:\r\n\r\n* the **Hash Key** (unique ID, also called the Partition Key)\r\n* the **Range Key** (_optional_, the sort order for the table - also called the Sort key)\r\n\r\nDynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDBItem`, `DynamoDBExpiringItem`, `DynamoDBVersionedItem` or `DynamoDBExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDBItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n---\r\n\r\n## AWS IAM Permissions\r\n\r\nThis weaves togeather various DynamoDB API calls and actions in order to simplify the Developer Experience. This includes using sensible default values and best practises for Tables and features which are not \"the most basic Table\". One key impact of this is that default actions require additional DynamoDB permissions above and beyond the core permissions that most DynamoDB documentation will describe. It's probably you will get permissions errors while using this library and should reference the below permissions to add to your Lambda function code.\r\n\r\n* `ConditionCheckItem` - required when using versioning on your items\r\n* `DescribeContinuousBackups` - required to wait for Point-in-time Recovery to be activated on the table and indexes\r\n* `DescribeTable` - required for debug output and logging\r\n* `ListTables` - required to check if a Table exists before creating a new one\r\n* `UpdateContinuousBackups` - required for the default Table configuration which enables [Point-in-time recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html)\r\n* `UpdateContributorInsights` - required for metrics/monitoring enabled by default on Tables\r\n* `UpdateTimeToLive` - required when using an expiring item to set the TTL field on the table\r\n\r\nIf you scope your Lambda permissions to the namespace of the tables for your specific project (e.g. `arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ProjectAlias}.${Environment}.*`) then you can use `\"Actions\": [ \"dynamodb:*\" ]` but doing that without restricting the scope tables your functions are permitted to access is (a) a security risk and (b) a high risk of a bug destroying data in the wrong tables.\r\n\r\n---\r\n\r\n## !!! IMPORTANT CAVEAT !!!\r\n\r\nThe [DynamoDBClientWrapper](./src/DynamoDBClientWrapper.ts)'s _InitializeTable_ function uses Generics to accept and derivative type of [DynamoDBItem](./src/models/DynamoDBItem.ts). Using a Generic prevents accessing static class members. The **BaseTableName** implementation in your extension of `DynamoDBItem` _MUST_ return the same value on _for all instances of your class_. In particular, for the _default_ instance created when the wrapper creates an instance of your class using the default constructor. This is a limitation of using Generics in TypeScript.\r\n\r\n---\r\n\r\n## Unit/Integration Testing\r\n\r\nAdditional information on testing can be found [here](./tests/README.md).\r\n\r\n---\r\n\r\n## Example Usage\r\n\r\n### Example: DynamoDBItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDBItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport interface IMyDataStructure {\r\n    id: string;\r\n}\r\nexport class MyDataStructure extends DynamoDBItem implements IMyDataStructure {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(data?: Partial<IMyDataStructure>) {\r\n        super();\r\n        const {\r\n            id,\r\n        } = data ?? {};\r\n        this.id = id || '';\r\n    }\r\n\r\n    // #region IDynamoDBBaseItem\r\n    public HashKeyName(): keyof IMyDataStructure {\r\n        return 'id';\r\n    }\r\n    public RangeKeyName(): keyof IMyDataStructure | undefined {\r\n        return undefined;\r\n    }\r\n    // #endregion IDynamoDBBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Basic Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDBClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDBClientWrapper = new DynamoDBClientWrapper({ TablePrefix: TABLE_PREFIX });\r\nconst item: MyDataStructure = new MyDataStructure({ id: '12345' });\r\nawait db.PutItem(\r\n    item,\r\n    {\r\n        CreateTableIfNotExists: true,\r\n        Class: MyDataStructure,\r\n    },\r\n);\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        { HashKey: item.id },\r\n    );\r\n\r\n// Alternate Usage: Required - if true, an exception will be thrown for an item that isn't found\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(\r\n        MyDataStructure,\r\n        {\r\n            HashKey: item.id,\r\n            Required: true,\r\n        }\r\n    );\r\n} catch (err) {\r\n    // err instanceof ItemNotFoundError\r\n}\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **alpha**\r\n3. Merge into **alpha** and a new release on the **alpha** channel will be created for you to test\r\n4. Create a PR to merge **alpha** --> **staging**\r\n5. Merge into **staging** and a new release on the **beta** channel will be created for you to offer for wider testing feedback\r\n6. Create a PR to merge **staging** --> **production**\r\n\r\n_Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **alpha**, **staging** (beta channel) and **production** branches __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)_\r\n","gitHead":"4a8f7e808ef15c197f99663396dbcaad0283ea85","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.1","dependencies":{"luxon":"^3.3.0","aws-xray-sdk":"^3.5.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.6.1","async":"^3.2.4","dotenv":"^16.3.1","eslint":"^7.32.0","esbuild":"^0.18.15","ts-jest":"^29.1.1","ts-node":"^9.1.1","typedoc":"^0.24.8","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.19","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-jsdoc":"^46.4.4","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.62.0","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^3.1.0","eslint-plugin-import-newlines":"^1.3.4","@typescript-eslint/eslint-plugin":"^5.62.0","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.0_1689889839029_0.7637347786234086","host":"s3://npm-registry-packages"}},"2.0.1":{"name":"@arcticleaf/aws-util-dynamodb","version":"2.0.1","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@2.0.1","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"2bf94189c48acf26b1c7cf116c41b32ad97f2451","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-2.0.1.tgz","fileCount":68,"integrity":"sha512-P3hysJo40KFKcN/nPJ3SqFMwOg2GH5/MazKr7QQzy+AJ8crtO7Ab4lEhQ4Rc9wAFfqktVjZUeXdZKh0pa3iBXQ==","signatures":[{"sig":"MEUCIQCt4kcSODpYj/C7HFP4grR3pK9SZPyOXyFk1btJDjZrYAIgATcmCq/XocXa/dTUCcA6tfr4IpL4664udjuuoShNN7I=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":236336},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"ca9482435c90d685f291c61c26144b2d9f669b69","scripts":{"docs":"typedoc --favicon https://www.arcticleaf.io/hubfs/al-logo-favicon-1.png","lint":"eslint --ext .js,.ts .","test":"jest","build":"tsc","compile":"npm run lint-fix && tsc","monitor":"rm tsconfig.tsbuildinfo; tsc --watch","release":"semantic-release","test:ci":"jest --ci --passWithNoTests --testPathIgnorePatterns=/local/","lint:fix":"eslint --ext .js,.ts . --fix","test:local":"cross-env DOTENV_CONFIG_PATH=.jest/env.local jest --passWithNoTests --coverage","test:watch":"jest --watchAll","dynamodb:up":"docker compose -f .jest/docker-compose.yml up -d dynamodb-local","dynamodb:down":"docker compose -f .jest/docker-compose.yml stop dynamodb-local","test:local:dynamodb":"cross-env DOTENV_CONFIG_PATH=.jest/env.dynamodb-local jest --passWithNoTests --coverage"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"8.19.4","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.16.1","dependencies":{"luxon":"^3.3.0","aws-xray-sdk":"^3.5.1","@aws-sdk/util-dynamodb":"3.188","@aws-sdk/client-dynamodb":"3.188"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.1","async":"^3.2.4","dotenv":"^16.3.1","eslint":"^7.32.0","esbuild":"^0.18.15","ts-jest":"^29.1.1","ts-node":"^9.1.1","typedoc":"^0.24.8","cross-env":"^7.0.3","jest-junit":"^15.0.0","typescript":"^4.9.5","@types/jest":"^27.5.2","@types/node":"^18.16.19","lorem-ipsum":"^2.0.8","@types/async":"^3.2.20","@types/luxon":"^3.3.0","semantic-release":"^19.0.5","eslint-plugin-jest":"^26.9.0","source-map-support":"^0.5.21","eslint-plugin-jsdoc":"^46.4.4","eslint-plugin-import":"^2.27.5","@semantic-release/git":"^10.0.1","typedoc-plugin-extras":"^2.3.3","eslint-config-loopback":"^13.1.0","typedoc-plugin-coverage":"^2.1.0","typedoc-plugin-mdn-links":"^3.0.3","@types/source-map-support":"^0.5.6","@typescript-eslint/parser":"^5.62.0","@semantic-release/changelog":"^6.0.3","typedoc-plugin-replace-text":"^3.1.0","eslint-plugin-import-newlines":"^1.3.4","@typescript-eslint/eslint-plugin":"^5.62.0","eslint-import-resolver-typescript":"^3.5.5","eslint-plugin-sort-imports-es6-autofix":"^0.6.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.8.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_2.0.1_1689890983513_0.3805618145264451","host":"s3://npm-registry-packages"}},"1.2.12":{"name":"@arcticleaf/aws-util-dynamodb","version":"1.2.12","keywords":["aws","dynamodb"],"author":{"name":"Arctic Leaf Inc."},"license":"MIT","_id":"@arcticleaf/aws-util-dynamodb@1.2.12","maintainers":[{"name":"braydengirard_ali","email":"brayden.girard@arcticleaf.io"},{"name":"support-arcticleaf","email":"support@arcticleaf.io"},{"name":"stevekanter","email":"steve.kanter@arcticleaf.io"},{"name":"jeffbacon.arcticleaf","email":"jeff.bacon+npm@arcticleaf.io"}],"homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"dist":{"shasum":"805dbda4f5dad44d2b85297e060fa06e422be7c0","tarball":"https://registry.npmjs.org/@arcticleaf/aws-util-dynamodb/-/aws-util-dynamodb-1.2.12.tgz","fileCount":20,"integrity":"sha512-ndbteux30cPnYRE1Vuzasiff/mEQ4u70y8vICUfBUxACk/eBSnRQIdvOq0liLk1j+DFXMny0i36jjHKLNCiq6Q==","signatures":[{"sig":"MEUCIQDfE7MYhHZpmmHs45P3P7zpcDGKWAQif2cKJoDCtT5JXQIgXlsu99GQhIyav2d37kuYV1uoITDmRUTtgbgAmnd3+ME=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":139607},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"7162987a541cf19ae29c4acb774bfc618c24c3cd","scripts":{"lint":"eslint --ext .js,.ts .","test":"echo No Tests Defined","build":"tsc","monitor":"tsc --watch","release":"npm run semantic-release","lint:fix":"eslint --ext .js,.ts . --fix","semantic-release":"semantic-release"},"_npmUser":{"name":"support-arcticleaf","email":"support@arcticleaf.io"},"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"_npmVersion":"10.2.3","description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","directories":{},"_nodeVersion":"18.19.0","dependencies":{"lambda-log":"^3.1.0","aws-xray-sdk":"^3.5.3","@aws-sdk/util-dynamodb":"3.362.0","@aws-sdk/client-dynamodb":"3.362.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^8.56.0","typescript":"^5.3.3","semantic-release":"^19.0.5","@types/lambda-log":"^3.0.3","eslint-plugin-import":"^2.29.1","@semantic-release/git":"^10.0.1","eslint-config-loopback":"^13.1.0","@typescript-eslint/parser":"^6.21.0","@semantic-release/changelog":"^6.0.3","@typescript-eslint/eslint-plugin":"^6.21.0","@amanda-mitchell/semantic-release-npm-multiple":"^3.9.0"},"_npmOperationalInternal":{"tmp":"tmp/aws-util-dynamodb_1.2.12_1707428316271_0.3814059887096912","host":"s3://npm-registry-packages"}}},"time":{"created":"2021-10-29T22:45:05.538Z","modified":"2025-01-20T21:04:48.776Z","1.2.4":"2021-10-29T22:45:05.756Z","1.2.5":"2021-10-29T23:05:19.205Z","1.2.6":"2021-12-13T20:42:40.977Z","1.2.7":"2021-12-22T15:35:02.451Z","1.2.8":"2022-05-12T01:26:55.459Z","1.2.9":"2022-12-14T15:49:50.160Z","2.0.0-alpha.1":"2023-01-08T18:19:46.965Z","2.0.0-alpha.2":"2023-01-08T18:27:43.799Z","2.0.0-alpha.3":"2023-01-09T00:04:35.817Z","2.0.0-alpha.4":"2023-01-09T00:09:44.941Z","2.0.0-alpha.5":"2023-01-09T00:40:36.411Z","1.2.10":"2023-01-09T23:22:57.534Z","2.0.0-alpha.7":"2023-01-17T17:57:27.518Z","2.0.0-alpha.8":"2023-01-17T18:15:18.521Z","2.0.0-alpha.9":"2023-02-20T19:07:48.990Z","2.0.0-alpha.10":"2023-02-20T23:22:37.874Z","2.0.0-alpha.11":"2023-03-07T22:51:37.675Z","2.0.0-alpha.12":"2023-03-16T17:11:29.618Z","2.0.0-alpha.13":"2023-03-19T02:42:42.762Z","2.0.0-alpha.14":"2023-03-19T17:10:02.223Z","2.0.0-alpha.15":"2023-03-19T18:50:03.676Z","2.0.0-alpha.16":"2023-03-20T00:43:55.472Z","2.0.0-alpha.17":"2023-03-20T02:50:00.320Z","2.0.0-alpha.18":"2023-03-22T20:37:50.340Z","2.0.0-alpha.19":"2023-03-23T19:30:54.035Z","2.0.0-alpha.20":"2023-03-23T21:29:13.578Z","1.2.10-beta.2":"2023-03-23T21:38:35.453Z","1.2.10-beta.3":"2023-03-23T21:40:25.042Z","1.2.11":"2023-03-23T21:43:17.178Z","2.0.0-alpha.21":"2023-03-24T18:07:09.269Z","2.0.0-alpha.22":"2023-03-25T20:09:49.690Z","2.0.0-alpha.23":"2023-03-25T20:26:06.508Z","2.0.0-alpha.24":"2023-03-25T22:58:28.405Z","2.0.0-alpha.25":"2023-03-27T18:57:15.583Z","2.0.0-alpha.26":"2023-03-29T20:36:27.004Z","2.0.0-alpha.27":"2023-05-27T16:04:17.385Z","2.0.0-alpha.28":"2023-05-27T17:36:40.652Z","2.0.0-alpha.29":"2023-05-29T15:38:05.991Z","2.0.0-alpha.30":"2023-06-11T16:01:53.016Z","2.0.0-alpha.31":"2023-07-20T15:25:15.105Z","2.0.0-alpha.32":"2023-07-20T15:35:28.029Z","2.0.0-alpha.33":"2023-07-20T20:04:13.022Z","2.0.0-alpha.34":"2023-07-20T20:46:30.712Z","2.0.0-beta.1":"2023-07-20T21:10:53.041Z","2.0.0":"2023-07-20T21:50:39.206Z","2.0.1":"2023-07-20T22:09:43.781Z","1.2.12":"2024-02-08T21:38:36.429Z"},"bugs":{"url":"https://github.com/arcticleaf/dynamodbutil-npm-module/issues"},"author":{"name":"Arctic Leaf Inc."},"license":"MIT","homepage":"https://github.com/arcticleaf/dynamodbutil-npm-module#readme","keywords":["aws","dynamodb"],"repository":{"url":"git+https://github.com/arcticleaf/dynamodbutil-npm-module.git","type":"git"},"description":"Utilities for using DynamoDB without having to know all the API and implementation specifics of DynamoDB","maintainers":[{"email":"brayden.girard@arcticleaf.io","name":"braydengirard_ali"},{"email":"jeff.bacon+npm@arcticleaf.io","name":"jeffbacon.arcticleaf"},{"email":"steve.kanter@arcticleaf.io","name":"stevekanter"},{"email":"support@arcticleaf.io","name":"support-arcticleaf"},{"email":"leonardo.nunes@arcticleaf.io","name":"leosouzanunes"}],"readme":"# aws-util-dynamodb\r\n\r\nTLDR; Wrapper around DynamoDB to allow for more generic use of DynamoDB without having to know how to use all the APIs.\r\n\r\nThis library implements a wrapper class around the DynamoDBClient from the AWS SDK. It uses a few interfaces and base classes which you need to implement or extend on your own data models to allow the data models (Classes) to include the structural information needed to build a DynamoDB table to store objects of that Class type in.\r\n\r\nIt is most useful for the core use case of DynamoDB - fast, easy JSON object storage for objects which are referenced by ID.\r\nIf you have more complex use cases with Global or Local Secondary Indexes, or need to do custom serialization/deserialization of data from your Class structure, you may need to use the DynamoDB APIs directly.\r\n\r\nFor most uses of simple objects, this wrapper should provide an easier developer user experience.\r\n\r\nMany advanced use cases are supported via additional types in the library and the options for each function call. They are well documented to review the docs and read the DynamoDB documentation for context on them and when they are useful.\r\n\r\n## Usage\r\n\r\nFor this library, each Class you want to store in DynamoDB maps to a single DynamoDB table. The Class needs to define the two minimal DynamoDB dependencies - the Hash Key (unique ID, also called the Partition Key) and the Range Key (optional, the sort order for the table - also called the Sort key). DynamoDB maps Javascript data types into a native DynamoDB format. For each attribute (a.k.a. column or field) in your Class, DynamoDB needs to know which of it's internal data types to use to store that data.\r\n\r\nFortunately, there are utilities which will convert between the standard Javascript types (string, number, boolean) and DynamoDB data types - this is called 'marshalling' and 'unmarshalling' (a.k.a. serializing / deserializing).\r\n\r\nThe only two fields which must be manually mapped to DynamoDB data types are the fields used as the Hash Key and Range Key. This is because DynamoDB needs to know those data types to create the table schema before you can insert an object into it.\r\n\r\nThe `dynamodb-types` file contains Interfaces as well as extendable base implementations for Classes to help ease this data structuring.\r\nIt's recommended you extend from `DynamoDbItem`, `DynamoDbExpiringItem`, `DynamoDbVersionedItem` or `DynamoDbExpiringVersionedItem` depending on what combination of Expiration and/or Versioning support you want to leverage for you object (or neither, in the case of `DynamoDbItem`).\r\n\r\nYou can read the DynamoDB documentation for more info about Expiring and Versioned items but they are basically what they sounds like. DynamoDB will automatically delete Expiring items after a specified expiry date (one of the fields on the item, TTL) and Versioned items provide write-synchronization if you want to be sure the item hasn't changed in DynamoDB between the time you read it and write to it (useful when running multiple read/write operations in parallel on the table).\r\n\r\n### Example DynamoDbItem Implementation\r\n\r\n```javascript\r\nimport { DynamoDbItem } from '@arcticleaf/aws-util-dynamodb';\r\nexport class MyDataStructure extends DynamoDbItem {\r\n\r\n    // THIS MUST BE A STRING TYPE\r\n    public id: string;\r\n    // --> add any properties here that define your data structure\r\n\r\n    /**\r\n     * A default constructor is REQUIRED for deserialization from DynamoDB\r\n     * (in deserialization, first the default object is created, then\r\n     * properties are assigned)\r\n     */\r\n    constructor(id?: string) {\r\n        super();\r\n        this.id = id || '';\r\n    }\r\n\r\n    static BaseTableName() : string {\r\n     return 'MyDataStructures';\r\n    }\r\n\r\n    // #region IDynamoDbBaseItem\r\n    public IdFieldName() : string {\r\n     return 'id';\r\n    }\r\n    public RangeFieldName() : string | undefined {\r\n     return undefined;\r\n    }\r\n    public BaseTableName() : string {\r\n     return MyClass.BaseTableName();\r\n    }\r\n    // #endregion IDynamoDbBaseItem\r\n\r\n}\r\n```\r\n\r\n### Example Usage\r\n\r\n```javascript\r\n// define TABLE_PREFIX in CloudFormation as `${ProjectName}.${Environment}` to make permissions scoping easier\r\nconst TABLE_PREFIX: string = `${process.env.TABLE_PREFIX || 'localhost'}`;\r\n// DynamoDbClientWrapper constructor takes options as well\r\n// you probably want to set a custom Logger in it\r\nconst db: DynamoDbClientWrapper = new DynamoDbClientWrapper(TABLE_PREFIX);\r\nconst item: MyDataStructure = new MyDataStructure('12345');\r\nawait db.PutItem(\r\n    item,\r\n    { CreateTableIfNotExists: true, Class: MyDataStructure },\r\n);\r\ntry {\r\n    const retrieved: MyDataStructure | undefined = await db.GetItem(MyDataStructure, item.id);\r\n} catch (err) { ... }\r\n// Alternate Usage: Required - if false, undefined will be returned if the item is not found instead of throwing an exception\r\nconst retrieved: MyDataStructure | undefined = await db.GetItem(MyDataStructure, item.id, undefined, { Required: false });\r\n```\r\n\r\n## Release Process\r\n\r\n1. Make commits that have `fix:` as the prefix on the commit message in order for your fix to trigger a micro version update upon release\r\n2. Commit changes to your branch and then create a PR to merge your branch into **master**\r\n3. Update (merge) into **master**\r\n4. Merge **release** => **master** (in order to pick the last version number deployed)\r\n     * *this may have already been done but it's a safety check*\r\n5. Create a PR to merge **master** => **release**\r\n\r\n*Note: this project uses the [semantic-release](https://github.com/semantic-release/semantic-release#readme) system. New releases are automatically created from the **release** branch __ONLY__ if there are commit comments prefixed with `fix:` (micro version bump), `feat:` (minor version bump), `perf:` (major version bump)*\r\n","readmeFilename":"README.md"}