declapract-typescript-ehmpathy 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/declapract.declare.yml +4 -0
- package/dist/examples/todo.md +1 -0
- package/dist/getVariables.ts +27 -0
- package/dist/practices/cicd-deploy-package/bad-practices/old-names/.github/workflows/publish_on_tag.yml.declapract.ts +3 -0
- package/dist/practices/cicd-deploy-package/best-practice/.declapract.readme.md +2 -0
- package/dist/practices/cicd-deploy-package/best-practice/.github/workflows/publish-on-tag.yml +36 -0
- package/dist/practices/cicd-deploy-service/bad-practices/old-names/.github/workflows/deploy_dev_on_main.yml.declapract.ts +3 -0
- package/dist/practices/cicd-deploy-service/bad-practices/old-names/.github/workflows/deploy_dev_on_master.yml.declapract.ts +3 -0
- package/dist/practices/cicd-deploy-service/bad-practices/old-names/.github/workflows/deploy_on_tag.yml.declapract.ts +3 -0
- package/dist/practices/cicd-deploy-service/bad-practices/old-names/.github/workflows/deploy_prod_on_tag.yml.declapract.ts +3 -0
- package/dist/practices/cicd-deploy-service/best-practice/.declapract.readme.md +4 -0
- package/dist/practices/cicd-deploy-service/best-practice/.github/workflows/deploy-dev-on-main.yml +59 -0
- package/dist/practices/cicd-deploy-service/best-practice/.github/workflows/deploy-prod-on-tag.yml +74 -0
- package/dist/practices/cicd-integrate/bad-practices/old-names/.github/workflows/ci-on-commit.yml.declapract.ts +3 -0
- package/dist/practices/cicd-integrate/bad-practices/old-names/.github/workflows/ci_on_commit.yml.declapract.ts +3 -0
- package/dist/practices/cicd-integrate/bad-practices/old-names/.github/workflows/test_on_commit.yml.declapract.ts +3 -0
- package/dist/practices/cicd-integrate/best-practice/.declapract.readme.md +3 -0
- package/dist/practices/cicd-integrate/best-practice/.github/workflows/pr-release-on-main.yml +17 -0
- package/dist/practices/cicd-integrate/best-practice/.github/workflows/test-on-commit.yml +285 -0
- package/dist/practices/config/bad-practices/configs-contain-wrong-account-id/config/dev.json.declapract.ts +9 -0
- package/dist/practices/config/bad-practices/configs-contain-wrong-account-id/config/prod.json.declapract.ts +9 -0
- package/dist/practices/config/bad-practices/configs-contain-wrong-account-id/config/test.json.declapract.ts +9 -0
- package/dist/practices/config/bad-practices/divergent-config-shapes/.declapract.readme.md +8 -0
- package/dist/practices/config/bad-practices/divergent-config-shapes/config/dev.json.declapract.ts +37 -0
- package/dist/practices/config/bad-practices/divergent-config-shapes/config/prod.json.declapract.ts +37 -0
- package/dist/practices/config/bad-practices/in-util-dir-directly/.declapract.readme.md +1 -0
- package/dist/practices/config/bad-practices/in-util-dir-directly/src/<star><star>/<star>.ts.declapract.ts +16 -0
- package/dist/practices/config/bad-practices/in-util-dir-directly/src/utils/config.integration.test.ts.declapract.ts +3 -0
- package/dist/practices/config/bad-practices/in-util-dir-directly/src/utils/config.ts.declapract.ts +3 -0
- package/dist/practices/config/bad-practices/promise-config/src/<star><star>/<star>.ts.declapract.ts +19 -0
- package/dist/practices/config/best-practice/config/dev.json +3 -0
- package/dist/practices/config/best-practice/config/dev.json.declapract.ts +3 -0
- package/dist/practices/config/best-practice/config/prod.json +3 -0
- package/dist/practices/config/best-practice/config/prod.json.declapract.ts +3 -0
- package/dist/practices/config/best-practice/config/test.json +3 -0
- package/dist/practices/config/best-practice/config/test.json.declapract.ts +3 -0
- package/dist/practices/config/best-practice/nontyped_modules/config-with-paramstore.d.ts +1 -0
- package/dist/practices/config/best-practice/package.json +5 -0
- package/dist/practices/config/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/config/best-practice/provision/aws/product/parameter-store.tf +3 -0
- package/dist/practices/config/best-practice/provision/aws/product/parameter-store.tf.declapract.ts +16 -0
- package/dist/practices/config/best-practice/provision/aws/product/variables.tf +3 -0
- package/dist/practices/config/best-practice/provision/aws/product/variables.tf.declapract.ts +3 -0
- package/dist/practices/config/best-practice/src/utils/config/Config.ts +1 -0
- package/dist/practices/config/best-practice/src/utils/config/Config.ts.declapract.ts +7 -0
- package/dist/practices/config/best-practice/src/utils/config/getConfig.integration.test.ts +8 -0
- package/dist/practices/config/best-practice/src/utils/config/getConfig.ts +8 -0
- package/dist/practices/config/best-practice/src/utils/environment.ts +3 -0
- package/dist/practices/config/best-practice/src/utils/environment.ts.declapract.ts +3 -0
- package/dist/practices/conventional-commits/best-practice/.declapract.readme.md +5 -0
- package/dist/practices/conventional-commits/best-practice/.husky/commit-msg +4 -0
- package/dist/practices/conventional-commits/best-practice/commitlint.config.js +4 -0
- package/dist/practices/conventional-commits/best-practice/package.json +17 -0
- package/dist/practices/conventional-commits/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/dates-and-times/bad-practices/moment/.declapract.readme.md +9 -0
- package/dist/practices/dates-and-times/bad-practices/moment/package.json.declapract.ts +12 -0
- package/dist/practices/dates-and-times/best-practice/.declapract.readme.md +1 -0
- package/dist/practices/dates-and-times/best-practice/package.json +5 -0
- package/dist/practices/dates-and-times/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/directory-structure-src/bad-practices/model-dir/.declapract.readme.md +2 -0
- package/dist/practices/directory-structure-src/bad-practices/model-dir/src/<star><star>/<star>.ts.declapract.ts +44 -0
- package/dist/practices/directory-structure-src/bad-practices/model-dir/src/model/<star><star>/<star>.ts.declapract.ts +16 -0
- package/dist/practices/directory-structure-src/bad-practices/services-dir/.declapract.readme.md +5 -0
- package/dist/practices/directory-structure-src/bad-practices/services-dir/src/services/<star><star>/<star>.ts.declapract.ts +3 -0
- package/dist/practices/directory-structure-src/best-practice/.declapract.readme.md +32 -0
- package/dist/practices/directory-structure-src/best-practice/src/contract/<star><star>/<star>.ts.declapract.ts +4 -0
- package/dist/practices/directory-structure-src/best-practice/src/data/clients/<star><star>/<star>.ts.declapract.ts +3 -0
- package/dist/practices/directory-structure-src/best-practice/src/data/dao/<star><star>/<star>.ts.declapract.ts +3 -0
- package/dist/practices/directory-structure-src/best-practice/src/domain/constants.ts.declapract.ts +15 -0
- package/dist/practices/directory-structure-src/best-practice/src/domain/index.ts.declapract.ts +3 -0
- package/dist/practices/directory-structure-src/best-practice/src/domain/objects/index.ts.declapract.ts +4 -0
- package/dist/practices/directory-structure-src/best-practice/src/logic/<star><star>/<star>.ts.declapract.ts +4 -0
- package/dist/practices/domain/bad-practices/schematic-joi-model/src/domain/<star><star>/<star>.ts.declapract.ts +16 -0
- package/dist/practices/domain/best-practice/package.json +7 -0
- package/dist/practices/domain/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/domain/best-practice/src/domain/objects/index.ts.declapract.ts +4 -0
- package/dist/practices/environments/best-practice/.declapract.readme.md +30 -0
- package/dist/practices/environments/best-practice/provision/aws/environments/dev/main.tf.declapract.ts +3 -0
- package/dist/practices/environments/best-practice/provision/aws/environments/prod/main.tf.declapract.ts +3 -0
- package/dist/practices/environments/best-practice/provision/aws/environments/test/main.tf.declapract.ts +3 -0
- package/dist/practices/environments/best-practice/src/utils/environment.ts +35 -0
- package/dist/practices/errors/best-practice/src/utils/errors/UnexpectedCodePathError.ts +14 -0
- package/dist/practices/format/best-practice/package.json +6 -0
- package/dist/practices/format/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/git/best-practice/.gitignore.declapract.ts +29 -0
- package/dist/practices/lambda-clients/bad-practices/lambda-service-client-package/.declapract.readme.md +1 -0
- package/dist/practices/lambda-clients/bad-practices/lambda-service-client-package/package.json +5 -0
- package/dist/practices/lambda-clients/bad-practices/lambda-service-client-package/package.json.declapract.ts +16 -0
- package/dist/practices/lambda-clients/best-practice/package.json +5 -0
- package/dist/practices/lambda-clients/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/lambda-clients/best-practice/src/data/clients/<star>.ts +1 -0
- package/dist/practices/lambda-clients/best-practice/src/data/clients/<star>.ts.declapract.ts +3 -0
- package/dist/practices/lambda-handlers/best-practice/package.json +9 -0
- package/dist/practices/lambda-handlers/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/lambda-handlers/best-practice/src/contract/handlers/<star><star>/<star>.declapract.ts +3 -0
- package/dist/practices/linting/best-practice/.eslintrc.js +44 -0
- package/dist/practices/linting/best-practice/package.json +16 -0
- package/dist/practices/linting/best-practice/package.json.declapract.ts +4 -0
- package/dist/practices/logging/best-practice/package.json +5 -0
- package/dist/practices/logging/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/logging/best-practice/src/utils/logger.ts +3 -0
- package/dist/practices/node/bad-practices/license/package.json.declapract.ts +22 -0
- package/dist/practices/node/best-practice/.nvmrc +1 -0
- package/dist/practices/node/best-practice/package.json +11 -0
- package/dist/practices/node/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/node/best-practice/readme.md +1 -0
- package/dist/practices/node/best-practice/readme.md.declapract.ts +3 -0
- package/dist/practices/nonpublished-modules/.declapract.readme.md +5 -0
- package/dist/practices/nonpublished-modules/bad-practices/ahbode-standard-lambda-handler/.declapract.readme.md +1 -0
- package/dist/practices/nonpublished-modules/bad-practices/ahbode-standard-lambda-handler/src/__nonpublished_modules__/ahbode-standard-lambda-handler/<star><star>/<star>.ts.declapract.ts +3 -0
- package/dist/practices/nonpublished-modules/bad-practices/ahbode-standard-lambda-handler/src/contract/handlers/<star>.integration.test.ts +1 -0
- package/dist/practices/nonpublished-modules/bad-practices/ahbode-standard-lambda-handler/src/contract/handlers/<star>.integration.test.ts.declapract.ts +15 -0
- package/dist/practices/nonpublished-modules/bad-practices/ahbode-standard-lambda-handler/src/contract/handlers/<star>.ts +1 -0
- package/dist/practices/nonpublished-modules/bad-practices/ahbode-standard-lambda-handler/src/contract/handlers/<star>.ts.declapract.ts +13 -0
- package/dist/practices/nonpublished-modules/bad-practices/deep-omit/.declapract.readme.md +1 -0
- package/dist/practices/nonpublished-modules/bad-practices/deep-omit/src/__nonpublished_modules__/deep-omit/<star><star>/<star>.ts.declapract.ts +3 -0
- package/dist/practices/nonpublished-modules/bad-practices/deep-omit/src/data/dao/<star><star>/<star>.integration.test.ts +1 -0
- package/dist/practices/nonpublished-modules/bad-practices/deep-omit/src/data/dao/<star><star>/<star>.integration.test.ts.declapract.ts +18 -0
- package/dist/practices/nonpublished-modules/bad-practices/simple-dynamodb-client/.declapract.readme.md +1 -0
- package/dist/practices/nonpublished-modules/bad-practices/simple-dynamodb-client/src/__nonpublished_modules__/simple-dynamodb-client/<star><star>/<star>.ts.declapract.ts +3 -0
- package/dist/practices/package-json-order/best-practice/.declapract.readme.md +3 -0
- package/dist/practices/package-json-order/best-practice/package.json.declapract.ts +171 -0
- package/dist/practices/persist-with-dynamodb/best-practice/package.json +5 -0
- package/dist/practices/persist-with-dynamodb/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/database.sql.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/extensions.sql.declapract.ts +13 -0
- package/dist/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/schema.sql.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/user.cicd.sql.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/user.datalakedb.sql.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/readme.md +5 -0
- package/dist/practices/persist-with-rds/bad-practices/old-config-file-names/codegen.sql.yml.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/bad-practices/schema-entities-dir/.declapract.readme.md +1 -0
- package/dist/practices/persist-with-rds/bad-practices/schema-entities-dir/provision/schema/entities/<star>.ts.declapract.ts +12 -0
- package/dist/practices/persist-with-rds/bad-practices/schema-entities-dir/provision/schema/sql/entities.yml.declapract.ts +13 -0
- package/dist/practices/persist-with-rds/best-practice/.declapract.readme.md +6 -0
- package/dist/practices/persist-with-rds/best-practice/codegen.sql.dao.yml +18 -0
- package/dist/practices/persist-with-rds/best-practice/codegen.sql.dao.yml.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/best-practice/codegen.sql.schema.yml +6 -0
- package/dist/practices/persist-with-rds/best-practice/codegen.sql.types.yml +15 -0
- package/dist/practices/persist-with-rds/best-practice/config/dev.json +20 -0
- package/dist/practices/persist-with-rds/best-practice/config/dev.json.declapract.ts +15 -0
- package/dist/practices/persist-with-rds/best-practice/config/prod.json +20 -0
- package/dist/practices/persist-with-rds/best-practice/config/prod.json.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/best-practice/config/test.json +20 -0
- package/dist/practices/persist-with-rds/best-practice/config/test.json.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/best-practice/package.json +27 -0
- package/dist/practices/persist-with-rds/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/best-practice/provision/aws/product/parameter-store.tf +24 -0
- package/dist/practices/persist-with-rds/best-practice/provision/aws/product/parameter-store.tf.declapract.ts +18 -0
- package/dist/practices/persist-with-rds/best-practice/provision/docker/integration_test_db/build-image.dockerfile +7 -0
- package/dist/practices/persist-with-rds/best-practice/provision/docker/integration_test_db/docker-compose.yml +13 -0
- package/dist/practices/persist-with-rds/best-practice/provision/docker/integration_test_db/init/.gitignore +3 -0
- package/dist/practices/persist-with-rds/best-practice/provision/docker/integration_test_db/init/readme.md +3 -0
- package/dist/practices/persist-with-rds/best-practice/provision/docker/integration_test_db/wait-for-postgres.sh +15 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/connection.config.js +23 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/control.yml +7 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/deploy.database.sh +71 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.database.sql +10 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.extensions.sql +16 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.extensions.sql.declapract.ts +37 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.schema.sql +11 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.user.cicd.sql +14 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.user.datalakedb.sql +12 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/default_transaction_isolation.sql +6 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/user.service.sql +16 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init.yml +9 -0
- package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init.yml.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/best-practice/src/utils/config/getConfig.ts +2 -0
- package/dist/practices/persist-with-rds/best-practice/src/utils/config/getConfig.ts.declapract.ts +3 -0
- package/dist/practices/persist-with-rds/best-practice/src/utils/database/getDatabaseConnection.integration.test.ts +10 -0
- package/dist/practices/persist-with-rds/best-practice/src/utils/database/getDatabaseConnection.ts +65 -0
- package/dist/practices/persist-with-rds/best-practice/src/utils/database/withDatabaseConnection.ts +38 -0
- package/dist/practices/persist-with-rds/best-practice/src/utils/database/withDatabaseTransaction.ts +20 -0
- package/dist/practices/prettier/bad-practices/format-script/package.json.declapract.ts +26 -0
- package/dist/practices/prettier/best-practice/.prettierignore +1 -0
- package/dist/practices/prettier/best-practice/package.json +10 -0
- package/dist/practices/prettier/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/prettier/best-practice/prettier.config.js +9 -0
- package/dist/practices/runtime-type-checking/bad-practices/joi-types/package.json +5 -0
- package/dist/practices/runtime-type-checking/bad-practices/joi-types/package.json.declapract.ts +18 -0
- package/dist/practices/runtime-type-checking/bad-practices/old-joi-syntax-valid-input-cant-be-array/.declapract.readme.md +1 -0
- package/dist/practices/runtime-type-checking/bad-practices/old-joi-syntax-valid-input-cant-be-array/src/<star><star>/<star>.ts.declapract.ts +15 -0
- package/dist/practices/runtime-type-checking/best-practice/package.json +5 -0
- package/dist/practices/runtime-type-checking/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/serverless/bad-practices/generic-deploy-script/package.json +8 -0
- package/dist/practices/serverless/bad-practices/generic-deploy-script/package.json.declapract.ts +23 -0
- package/dist/practices/serverless/bad-practices/old-sls-plugins/package.json +6 -0
- package/dist/practices/serverless/bad-practices/old-sls-plugins/package.json.declapract.ts +19 -0
- package/dist/practices/serverless/best-practice/package.json +11 -0
- package/dist/practices/serverless/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/serverless/best-practice/serverless.yml +70 -0
- package/dist/practices/serverless/best-practice/serverless.yml.declapract.ts +26 -0
- package/dist/practices/terraform/bad-practices/terraform-dir/.declapract.readme.md +8 -0
- package/dist/practices/terraform/bad-practices/terraform-dir/provision/terraform/<star><star>/.gitignore.declapract.ts +12 -0
- package/dist/practices/terraform/bad-practices/terraform-dir/provision/terraform/<star><star>/<star>.hcl.declapract.ts +12 -0
- package/dist/practices/terraform/bad-practices/terraform-dir/provision/terraform/<star><star>/<star>.tf.declapract.ts +12 -0
- package/dist/practices/terraform/best-practice/.terraform-version +1 -0
- package/dist/practices/terraform/best-practice/package.json +6 -0
- package/dist/practices/terraform/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/terraform/best-practice/provision/aws/environments/dev/main.tf +18 -0
- package/dist/practices/terraform/best-practice/provision/aws/environments/dev/versions.tf +9 -0
- package/dist/practices/terraform/best-practice/provision/aws/environments/prod/main.tf +18 -0
- package/dist/practices/terraform/best-practice/provision/aws/environments/prod/versions.tf +9 -0
- package/dist/practices/terraform/best-practice/provision/aws/environments/test/main.tf +18 -0
- package/dist/practices/terraform/best-practice/provision/aws/environments/test/versions.tf +9 -0
- package/dist/practices/terraform/best-practice/provision/aws/product/variables.tf +14 -0
- package/dist/practices/terraform/best-practice/provision/github/environment/import-existing-repo.sh +12 -0
- package/dist/practices/terraform/best-practice/provision/github/environment/main.tf +20 -0
- package/dist/practices/terraform/best-practice/provision/github/environment/versions.tf +9 -0
- package/dist/practices/terraform/best-practice/provision/github/product/repository.tf +70 -0
- package/dist/practices/testing/bad-practices/mocks/.declapract.readme.md +8 -0
- package/dist/practices/testing/bad-practices/mocks/<star><star>/__mock__/<star>.js +3 -0
- package/dist/practices/testing/bad-practices/mocks/<star><star>/__mock__/<star>.ts +3 -0
- package/dist/practices/testing/bad-practices/old-acceptance-test-utils/acceptance/_utils/getDataFromLastOpenBracketAtStartOfLine.ts.declapract.ts +3 -0
- package/dist/practices/testing/bad-practices/old-acceptance-test-utils/acceptance/_utils/invokeLambda.ts.declapract.ts +3 -0
- package/dist/practices/testing/bad-practices/old-acceptance-test-utils/acceptance/lambdas/<star>.ts.declapract.ts +44 -0
- package/dist/practices/testing/bad-practices/old-acceptance-test-utils-2/acceptance/__test_utils__/environment.ts.declapract.ts +3 -0
- package/dist/practices/testing/bad-practices/old-acceptance-test-utils-2/acceptance/lambdas/<star>.ts.declapract.ts +22 -0
- package/dist/practices/testing/bad-practices/old-acceptance-test-utils-3/acceptance/_utils/environment.ts.declapract.ts +3 -0
- package/dist/practices/testing/bad-practices/old-acceptance-test-utils-3/acceptance/lambdas/<star>.ts.declapract.ts +18 -0
- package/dist/practices/testing/bad-practices/old-extension-pattern/.declapract.readme.md +3 -0
- package/dist/practices/testing/bad-practices/old-extension-pattern/<star><star>/<star>.test.acceptance.ts.declapract.ts +11 -0
- package/dist/practices/testing/bad-practices/old-extension-pattern/<star><star>/<star>.test.integration.ts.declapract.ts +11 -0
- package/dist/practices/testing/best-practice/.declapract.readme.md +45 -0
- package/dist/practices/testing/best-practice/acceptance/<star><star>/<star>.acceptance.test.ts.declapract.ts +3 -0
- package/dist/practices/testing/best-practice/acceptance/environment.ts +5 -0
- package/dist/practices/testing/best-practice/acceptance/lambdas/<star>.acceptance.test.ts.declapract.ts +32 -0
- package/dist/practices/testing/best-practice/jest.acceptance.config.js +15 -0
- package/dist/practices/testing/best-practice/jest.acceptance.env.js +2 -0
- package/dist/practices/testing/best-practice/jest.config.js +1 -0
- package/dist/practices/testing/best-practice/jest.integration.config.js +10 -0
- package/dist/practices/testing/best-practice/jest.integration.env.js +13 -0
- package/dist/practices/testing/best-practice/jest.unit.config.js +15 -0
- package/dist/practices/testing/best-practice/jest.unit.env.js +16 -0
- package/dist/practices/testing/best-practice/package.json +16 -0
- package/dist/practices/testing/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/testing/best-practice/src/<star><star>/<star>.integration.test.ts.declapract.ts +3 -0
- package/dist/practices/testing/best-practice/src/<star><star>/<star>.test.ts.declapract.ts +3 -0
- package/dist/practices/testing/best-practice/src/utils/environment.ts +3 -0
- package/dist/practices/testing/best-practice/src/utils/environment.ts.declapract.ts +3 -0
- package/dist/practices/testing/defineFunctionNameFromTestFileName.ts +11 -0
- package/dist/practices/typescript/best-practice/.declapract.readme.md +10 -0
- package/dist/practices/typescript/best-practice/package.json +12 -0
- package/dist/practices/typescript/best-practice/package.json.declapract.ts +3 -0
- package/dist/practices/typescript/best-practice/tsconfig.build.json +17 -0
- package/dist/practices/typescript/best-practice/tsconfig.json +18 -0
- package/dist/practices/uuid/bad-practices/npm-uuidv4/.declapract.readme.md +1 -0
- package/dist/practices/uuid/bad-practices/npm-uuidv4/package.json.declapract.ts +17 -0
- package/dist/practices/uuid/best-practice/.declapract.readme.md +1 -0
- package/dist/practices/uuid/best-practice/package.json +8 -0
- package/dist/practices/uuid/best-practice/package.json.declapract.ts +3 -0
- package/dist/useCases.yml +48 -0
- package/package.json +96 -0
- package/readme.md +39 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FileCheckType, FileFixFunction } from 'declapract';
|
|
2
|
+
|
|
3
|
+
export const check = FileCheckType.CONTAINS;
|
|
4
|
+
|
|
5
|
+
export const fix: FileFixFunction = (contents, context) => {
|
|
6
|
+
if (!contents) return { contents: context.declaredFileContents }; // init as declared if file dne
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
contents: JSON.stringify(
|
|
10
|
+
{ ...JSON.parse(contents), ...JSON.parse(context.declaredFileContents!) },
|
|
11
|
+
null,
|
|
12
|
+
2,
|
|
13
|
+
),
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"database": {
|
|
3
|
+
"admin": {
|
|
4
|
+
"host": "@declapract{variable.databaseClusterHost.prod}",
|
|
5
|
+
"port": 5432,
|
|
6
|
+
"database": "@declapract{variable.databaseName}",
|
|
7
|
+
"schema": "@declapract{variable.databaseName}",
|
|
8
|
+
"username": "@declapract{variable.databaseUserName.cicdUser}",
|
|
9
|
+
"password": "__PARAM__"
|
|
10
|
+
},
|
|
11
|
+
"service": {
|
|
12
|
+
"host": "@declapract{variable.databaseClusterHost.prod}",
|
|
13
|
+
"port": 5432,
|
|
14
|
+
"database": "@declapract{variable.databaseName}",
|
|
15
|
+
"schema": "@declapract{variable.databaseName}",
|
|
16
|
+
"username": "@declapract{variable.databaseUserName.serviceUser}",
|
|
17
|
+
"password": "__PARAM__"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"database": {
|
|
3
|
+
"admin": {
|
|
4
|
+
"host": "localhost",
|
|
5
|
+
"port": 7821,
|
|
6
|
+
"database": "@declapract{variable.databaseName}",
|
|
7
|
+
"schema": "@declapract{variable.databaseName}",
|
|
8
|
+
"username": "@declapract{variable.databaseUserName.cicdUser}",
|
|
9
|
+
"password": "__CHANG3_ME__"
|
|
10
|
+
},
|
|
11
|
+
"service": {
|
|
12
|
+
"host": "localhost",
|
|
13
|
+
"port": 7821,
|
|
14
|
+
"database": "@declapract{variable.databaseName}",
|
|
15
|
+
"schema": "@declapract{variable.databaseName}",
|
|
16
|
+
"username": "@declapract{variable.databaseUserName.serviceUser}",
|
|
17
|
+
"password": "__CHANG3_ME__"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"pg": "@declapract{check.minVersion('8.3.0')}",
|
|
4
|
+
"yesql": "@declapract{check.minVersion('4.1.3')}"
|
|
5
|
+
},
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"sql-code-generator": "@declapract{check.minVersion('0.9.0')}",
|
|
8
|
+
"sql-dao-generator": "@declapract{check.minVersion('0.2.0')}",
|
|
9
|
+
"sql-schema-control": "@declapract{check.minVersion('0.7.3')}",
|
|
10
|
+
"sql-schema-generator": "@declapract{check.minVersion('0.21.1')}",
|
|
11
|
+
"@types/yesql": "@declapract{check.minVersion('3.2.2')}",
|
|
12
|
+
"@types/pg": "@declapract{check.minVersion('7.14.3')}"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"generate:dao": "npx sql-dao-generator generate && npm run fix:format",
|
|
16
|
+
"generate:schema": "npx sql-schema-generator generate -c codegen.sql.schema.yml",
|
|
17
|
+
"generate:types-from-sql": "npx sql-code-generator generate -c codegen.sql.types.yml",
|
|
18
|
+
"provision:docker:prepare": "cp provision/schema/sql/init/.extensions.sql provision/docker/integration_test_db/init/extensions.sql && cp provision/schema/sql/init/.schema.sql provision/docker/integration_test_db/init/schema.sql && cp provision/schema/sql/init/.user.cicd.sql provision/docker/integration_test_db/init/user.cicd.sql",
|
|
19
|
+
"provision:docker:up": "docker-compose -f ./provision/docker/integration_test_db/docker-compose.yml up -d --force-recreate --build --renew-anon-volumes",
|
|
20
|
+
"provision:docker:await": "docker-compose -f ./provision/docker/integration_test_db/docker-compose.yml exec -T postgres /root/wait-for-postgres.sh",
|
|
21
|
+
"provision:docker:down": "docker-compose -f ./provision/docker/integration_test_db/docker-compose.yml down",
|
|
22
|
+
"provision:schema:plan": "npx sql-schema-control plan -c provision/schema/control.yml",
|
|
23
|
+
"provision:schema:apply": "npx sql-schema-control apply -c provision/schema/control.yml",
|
|
24
|
+
"provision:schema:sync": "npx sql-schema-control sync -c provision/schema/control.yml",
|
|
25
|
+
"provision:integration-test-db": "npm run provision:docker:prepare && npm run provision:docker:up && npm run provision:docker:await && npm run provision:schema:plan && npm run provision:schema:apply && npm run provision:schema:plan"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/dist/practices/persist-with-rds/best-practice/provision/aws/product/parameter-store.tf
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
resource "aws_ssm_parameter" "secret_database_admin_password" {
|
|
2
|
+
name = "${local.parameter_store_namespace}.database.admin.password"
|
|
3
|
+
type = "SecureString"
|
|
4
|
+
value = "__IGNORED__" # "ignored" since we dont want to check in secrets to version control (terraform.lifecycle.ignore_changes -> value isn't overwritten)
|
|
5
|
+
tags = local.tags
|
|
6
|
+
count = var.environment == "prod" ? 1 : 0 # only needed in prod env, in other envs its hardcoded in config.${env}.json since it's not sensitive
|
|
7
|
+
lifecycle {
|
|
8
|
+
ignore_changes = [
|
|
9
|
+
value # we only need the real value on the first initialization, afterwards, users shouldn't have this
|
|
10
|
+
]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
resource "aws_ssm_parameter" "secret_database_service_password" {
|
|
14
|
+
name = "${local.parameter_store_namespace}.database.service.password"
|
|
15
|
+
type = "SecureString"
|
|
16
|
+
value = "__IGNORED__" # "ignored" since we dont want to check in secrets to version control (terraform.lifecycle.ignore_changes -> value isn't overwritten)
|
|
17
|
+
tags = local.tags
|
|
18
|
+
count = var.environment == "prod" ? 1 : 0 # only needed in prod env, in other envs its hardcoded in config.${env}.json since it's not sensitive
|
|
19
|
+
lifecycle {
|
|
20
|
+
ignore_changes = [
|
|
21
|
+
value # we only need the real value on the first initialization, afterwards, users shouldn't have this
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FileCheckType, FileFixFunction } from 'declapract';
|
|
2
|
+
|
|
3
|
+
export const check = FileCheckType.CONTAINS; // i.e., check that the contents of the file contains what's declared (default is equals)
|
|
4
|
+
|
|
5
|
+
export const fix: FileFixFunction = (contents, context) => {
|
|
6
|
+
if (!contents) return { contents: context.declaredFileContents };
|
|
7
|
+
return {
|
|
8
|
+
contents: contents
|
|
9
|
+
.replace(
|
|
10
|
+
/value\s+\= var\.secret_database_\w+_password/g,
|
|
11
|
+
`value = "__IGNORED__" # "ignored" since we dont want to check in secrets to version control (terraform.lifecycle.ignore_changes -> value isn't overwritten)`,
|
|
12
|
+
)
|
|
13
|
+
.replace(
|
|
14
|
+
/local\.tags\n\s+lifecycle/g,
|
|
15
|
+
`local.tags\n count = var.environment == "prod" ? 1 : 0 # only needed in prod env, in other envs its hardcoded in config.\${env}.json since it's not sensitive\n lifecycle`,
|
|
16
|
+
),
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
version: '3'
|
|
2
|
+
services:
|
|
3
|
+
postgres:
|
|
4
|
+
build:
|
|
5
|
+
context: .
|
|
6
|
+
dockerfile: build-image.dockerfile
|
|
7
|
+
container_name: @declapract{variable.databaseName}
|
|
8
|
+
command: postgres -c 'max_connections=500'
|
|
9
|
+
ports:
|
|
10
|
+
- 7821:5432
|
|
11
|
+
environment:
|
|
12
|
+
POSTGRES_PASSWORD: a-secure-password # default user is `postgres`
|
|
13
|
+
POSTGRES_DB: @declapract{variable.databaseName} # creates the database for us automatically
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# wait until postgres is really available
|
|
3
|
+
maxcounter=45
|
|
4
|
+
|
|
5
|
+
echo "waiting for postgres server to begin accepting connections..."
|
|
6
|
+
counter=1
|
|
7
|
+
while ! psql "dbname=$POSTGRES_DB host=localhost user=postgres password=$POSTGRES_PASSWORD port=5432" -c '\l' > /dev/null 2>&1; do
|
|
8
|
+
sleep 1
|
|
9
|
+
counter=`expr $counter + 1`
|
|
10
|
+
if [ $counter -gt $maxcounter ]; then
|
|
11
|
+
>&2 echo "we have been waiting for postgres too long already; failing"
|
|
12
|
+
exit 1
|
|
13
|
+
fi;
|
|
14
|
+
done
|
|
15
|
+
echo "connected to postgres instance successfuly"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const Config = require('config-with-paramstore').default;
|
|
2
|
+
|
|
3
|
+
const configInstance = new Config();
|
|
4
|
+
const getConfig = async () =>
|
|
5
|
+
configInstance.get(process.env.DEPLOYMENT_STAGE || undefined);
|
|
6
|
+
|
|
7
|
+
const promiseSchemaControlConfig = async () => {
|
|
8
|
+
const config = await getConfig();
|
|
9
|
+
const dbConfig = config.database.admin; // NOTE: schema control must have DDL privileges
|
|
10
|
+
const schemaControlConfig = {
|
|
11
|
+
host: dbConfig.host,
|
|
12
|
+
port: dbConfig.port,
|
|
13
|
+
database: dbConfig.schema, // i.e., db = schema
|
|
14
|
+
schema: dbConfig.schema,
|
|
15
|
+
username: dbConfig.username,
|
|
16
|
+
password: dbConfig.password,
|
|
17
|
+
};
|
|
18
|
+
return schemaControlConfig;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
promiseConfig: promiseSchemaControlConfig,
|
|
23
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#####################################################
|
|
2
|
+
## initilize the database in a live cluster
|
|
3
|
+
## - in other words, it does all of the things that docker does for us when we spin up a cluster without the db already
|
|
4
|
+
## - i.e.,
|
|
5
|
+
## - create the database
|
|
6
|
+
## - install the extensions
|
|
7
|
+
## - creates the schema
|
|
8
|
+
## - creates the cicd user
|
|
9
|
+
## - grants the cicd user ownership of the db
|
|
10
|
+
## - note:
|
|
11
|
+
## - requires pg admin access
|
|
12
|
+
## - requires _you_ to change the passwords in prod manually
|
|
13
|
+
##
|
|
14
|
+
## usage example:
|
|
15
|
+
## ```sh
|
|
16
|
+
## ./provision/schema/deploy.database.sh dev $(op get item @declapract{variable.organizationName}db.dev.postgres | jq -r .details.password)
|
|
17
|
+
## ```
|
|
18
|
+
#####################################################
|
|
19
|
+
|
|
20
|
+
# check that user has defined the environment that they want this key created for correctly
|
|
21
|
+
ENVIRONMENT=$1;
|
|
22
|
+
if [ "$ENVIRONMENT" != "prod" ] && [ "$ENVIRONMENT" != "dev" ]; then
|
|
23
|
+
echo "\nerror: Environment, the first argument, must be specified as either 'prod' or 'dev'. You specified '$ENVIRONMENT'";
|
|
24
|
+
exit 1;
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# check that user is authed into correct account
|
|
28
|
+
AWS_ACCOUNT_ID=$(aws sts get-caller-identity | jq -r '.Account');
|
|
29
|
+
EXPECTED_AWS_ACCOUNT_ID=$([ "$ENVIRONMENT" = 'prod' ] && echo "@declapract{variable.awsAccountId.prod}" || echo "@declapract{variable.awsAccountId.dev}");
|
|
30
|
+
if [ "$AWS_ACCOUNT_ID" != "$EXPECTED_AWS_ACCOUNT_ID" ]; then
|
|
31
|
+
echo "\nerror: the AWS_ACCOUNT that you are signed into is not correct for the environment you specified. You are authed into account '$AWS_ACCOUNT_ID' but the correct account id for '$ENVIRONMENT' IS '$EXPECTED_AWS_ACCOUNT_ID'";
|
|
32
|
+
exit 1;
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# check that pg admin password was specified
|
|
36
|
+
POSTGRES_ADMIN_PASSWORD="$2"
|
|
37
|
+
if [ -z $POSTGRES_ADMIN_PASSWORD ]; then
|
|
38
|
+
echo "\nerror: POSTGRES_ADMIN_PASSWORD must be defined as second arg";
|
|
39
|
+
exit 1;
|
|
40
|
+
fi;
|
|
41
|
+
|
|
42
|
+
# define the postgres connecition string
|
|
43
|
+
CLUSTER_HOST=$([ "$ENVIRONMENT" = 'prod' ] && echo "@declapract{variable.databaseClusterHost.prod}" || echo "@declapract{variable.databaseClusterHost.dev}");
|
|
44
|
+
CLUSTER_CONNECTION_STRING=postgresql://postgres:$POSTGRES_ADMIN_PASSWORD@$CLUSTER_HOST:5432
|
|
45
|
+
ROOT_DB_CONNECTION_STRING=$CLUSTER_CONNECTION_STRING/postgres
|
|
46
|
+
SVC_DB_CONNECTION_STRING=$CLUSTER_CONNECTION_STRING/@declapract{variable.databaseName}
|
|
47
|
+
|
|
48
|
+
# define path to the init sqls
|
|
49
|
+
SRC_PATH=$(readlink --canonicalize "$0");
|
|
50
|
+
SRC_DIR=$(dirname $SRC_PATH);
|
|
51
|
+
INIT_SQLS_DIR=$SRC_DIR/sql/init;
|
|
52
|
+
|
|
53
|
+
# run the create database command on root db
|
|
54
|
+
echo "\n 🔨 creating the database..."
|
|
55
|
+
psql $ROOT_DB_CONNECTION_STRING -f $INIT_SQLS_DIR/.database.sql
|
|
56
|
+
|
|
57
|
+
echo "\n 🔨 installing the extensions..."
|
|
58
|
+
psql $SVC_DB_CONNECTION_STRING -f $INIT_SQLS_DIR/.extensions.sql
|
|
59
|
+
|
|
60
|
+
echo "\n 🔨 creating the schema..."
|
|
61
|
+
psql $SVC_DB_CONNECTION_STRING -f $INIT_SQLS_DIR/.schema.sql
|
|
62
|
+
|
|
63
|
+
echo "\n 🔨 creating the cicd user..."
|
|
64
|
+
psql $SVC_DB_CONNECTION_STRING -f $INIT_SQLS_DIR/.user.cicd.sql
|
|
65
|
+
|
|
66
|
+
if [ "$ENVIRONMENT" = "prod" ]; then
|
|
67
|
+
echo "\n 🔨 granting reads to the datalakedb user..." # only in prod env; we dont want dev's testing data in our datalake
|
|
68
|
+
psql $SVC_DB_CONNECTION_STRING -f $INIT_SQLS_DIR/.user.datalakedb.sql
|
|
69
|
+
fi;
|
|
70
|
+
|
|
71
|
+
echo "\n 🎉 done"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* this command creates the database that the service will use
|
|
3
|
+
* - this not managed by sql-schema-control
|
|
4
|
+
* - requires superuser privileges
|
|
5
|
+
* - sql-schema-control needs a db to run _in_
|
|
6
|
+
* - this is applied
|
|
7
|
+
* - automatically for integration-test db
|
|
8
|
+
* - by the deployment script for live deployments
|
|
9
|
+
*/
|
|
10
|
+
CREATE DATABASE @declapract{variable.databaseName};
|
package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.extensions.sql
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* postgres databases use extensions to increase functionality
|
|
3
|
+
* - we have a minimum set of extensions that are required for sql-schema-generator
|
|
4
|
+
* - services may also include their own extensions if they want additional functionality
|
|
5
|
+
* - this is not managed by sql-schema-control
|
|
6
|
+
* - requires superuser privileges, cicd user only has db_owner privileges
|
|
7
|
+
* - this is applied
|
|
8
|
+
* - automatically for integration-test db (through `provision/docker/.../init/` directory, with files cp'd by npm provision scripts)
|
|
9
|
+
* - by the deployment script for live deployments
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
-- extensions required for all sql-schema-generator resources:
|
|
13
|
+
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
14
|
+
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
15
|
+
|
|
16
|
+
-- extensions required for custom use cases in this service:
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { FileCheckType, FileFixFunction } from 'declapract';
|
|
2
|
+
|
|
3
|
+
const grabCreateExtensionLinesFromContents = (contents: string) =>
|
|
4
|
+
contents
|
|
5
|
+
.split('\n')
|
|
6
|
+
.filter((line) => line.startsWith('CREATE EXTENSION IF NOT EXISTS'));
|
|
7
|
+
|
|
8
|
+
export const check = FileCheckType.CONTAINS;
|
|
9
|
+
|
|
10
|
+
export const fix: FileFixFunction = (contents, context) => {
|
|
11
|
+
// if the file doesn't exist, create what we want to see - with an additional example of how it can be extended
|
|
12
|
+
if (!contents)
|
|
13
|
+
return {
|
|
14
|
+
contents: `${context.declaredFileContents!.trim()}\n-- CREATE EXTENSION IF NOT EXISTS ...`,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// if the file does exist, then find all the custom create extension lines
|
|
18
|
+
const requiredCreateExtensionLines = grabCreateExtensionLinesFromContents(
|
|
19
|
+
context.declaredFileContents!,
|
|
20
|
+
);
|
|
21
|
+
const foundCreateExtensionLines =
|
|
22
|
+
grabCreateExtensionLinesFromContents(contents);
|
|
23
|
+
const foundCustomCreateExtensionLines = foundCreateExtensionLines.filter(
|
|
24
|
+
(foundCreateExtensionLine) =>
|
|
25
|
+
!requiredCreateExtensionLines.some((requiredCreateExtensionLine) =>
|
|
26
|
+
foundCreateExtensionLine.includes(requiredCreateExtensionLine),
|
|
27
|
+
), // if this found create-extension statement is not a required one, then its custom
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// and set the contents equal to what we want to see + their custom ones
|
|
31
|
+
return {
|
|
32
|
+
contents: [
|
|
33
|
+
context.declaredFileContents!.trim(),
|
|
34
|
+
...foundCustomCreateExtensionLines,
|
|
35
|
+
].join('\n'),
|
|
36
|
+
};
|
|
37
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* this command creates the schema that the service + sql-schema-control will use
|
|
3
|
+
* - this command must be run inside of the database that was created for this service
|
|
4
|
+
* - this creates a schema with the same name as the database
|
|
5
|
+
* - this not managed by sql-schema-control
|
|
6
|
+
* - sql-schema-control needs a schema to run _in_
|
|
7
|
+
* - this is applied
|
|
8
|
+
* - automatically for integration-test db
|
|
9
|
+
* - by the deployment script for live deployments
|
|
10
|
+
*/
|
|
11
|
+
CREATE SCHEMA @declapract{variable.databaseName};
|
package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.user.cicd.sql
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* creates a cicd user, with total control over the database and the schema, to be used by sql-schema-control
|
|
3
|
+
* - full control required since it'll be managing all resources for this db
|
|
4
|
+
* - this not managed by sql-schema-control
|
|
5
|
+
* - requires superuser privileges
|
|
6
|
+
* - sql-schema-control needs a user to run _under_
|
|
7
|
+
* - this is applied
|
|
8
|
+
* - automatically for integration-test db
|
|
9
|
+
* - by the deployment script for live deployments
|
|
10
|
+
*/
|
|
11
|
+
CREATE USER @declapract{variable.databaseUserName.cicdUser} WITH PASSWORD '__CHANG3_ME__'; -- create cicd user
|
|
12
|
+
ALTER DATABASE @declapract{variable.databaseName} OWNER TO @declapract{variable.databaseUserName.cicdUser}; -- make the cicd user the owner of the database
|
|
13
|
+
ALTER SCHEMA @declapract{variable.databaseName} OWNER TO @declapract{variable.databaseUserName.cicdUser}; -- make the cicd user the owner of the schema, too
|
|
14
|
+
ALTER USER @declapract{variable.databaseUserName.cicdUser} WITH CREATEROLE; -- allow the cicd user to create other users
|
package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/.user.datalakedb.sql
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grants read access to `datalakedb_federated_query_reader` so that we can query this db from redshift
|
|
3
|
+
* - this not managed by sql-schema-control
|
|
4
|
+
* - since it does not apply in integration test environment (since that user wont exist there)
|
|
5
|
+
* - this is applied
|
|
6
|
+
* - by the deployment script for live deployments
|
|
7
|
+
*/
|
|
8
|
+
GRANT USAGE ON SCHEMA @declapract{variable.databaseName} TO datalakedb_federated_query_reader;
|
|
9
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA @declapract{variable.databaseName} TO datalakedb_federated_query_reader;
|
|
10
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA @declapract{variable.databaseName} GRANT SELECT ON TABLES TO datalakedb_federated_query_reader;
|
|
11
|
+
|
|
12
|
+
-- don't forget to hop into the datalakedb and add the ext_@declapract{variable.databaseName}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* we want `read-committed` as the default txn isolation level on our databases
|
|
3
|
+
* - its _required_ to support high concurrency operations for the upserts generated by `sql-schema-generator`
|
|
4
|
+
* - this is done automatically by sql-schema-control under the cicd user
|
|
5
|
+
*/
|
|
6
|
+
ALTER DATABASE @declapract{variable.databaseName} SET DEFAULT_TRANSACTION_ISOLATION TO 'read committed';
|
package/dist/practices/persist-with-rds/best-practice/provision/schema/sql/init/user.service.sql
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* the service user has maximally restricted permissions
|
|
3
|
+
* - this is the user that the service will be using to interact with the database
|
|
4
|
+
* - insert only, baby!
|
|
5
|
+
*/
|
|
6
|
+
CREATE USER @declapract{variable.databaseUserName.serviceUser} WITH PASSWORD '__CHANG3_ME__';
|
|
7
|
+
-- ALTER USER @declapract{variable.databaseUserName.serviceUser} WITH PASSWORD '__actual_password__';
|
|
8
|
+
|
|
9
|
+
-- grant usage
|
|
10
|
+
GRANT USAGE ON SCHEMA @declapract{variable.databaseName} TO @declapract{variable.databaseUserName.serviceUser};
|
|
11
|
+
|
|
12
|
+
-- grant specific privileges to resources in the schema, for all created now and onward (i.e., all)
|
|
13
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA @declapract{variable.databaseName} GRANT SELECT, INSERT, UPDATE ON TABLES TO @declapract{variable.databaseUserName.serviceUser};
|
|
14
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA @declapract{variable.databaseName} GRANT EXECUTE ON FUNCTIONS TO @declapract{variable.databaseUserName.serviceUser};
|
|
15
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA @declapract{variable.databaseName} GRANT USAGE, SELECT ON SEQUENCES TO @declapract{variable.databaseUserName.serviceUser};
|
|
16
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getDatabaseConnection } from './getDatabaseConnection';
|
|
2
|
+
|
|
3
|
+
describe('getDatabaseConnection', () => {
|
|
4
|
+
it('should be able to connect and execute a query', async () => {
|
|
5
|
+
const dbConnection = await getDatabaseConnection();
|
|
6
|
+
const result = await dbConnection.query({ sql: 'select 1' });
|
|
7
|
+
expect(result.rows.length).toEqual(1);
|
|
8
|
+
await dbConnection.end();
|
|
9
|
+
});
|
|
10
|
+
});
|
package/dist/practices/persist-with-rds/best-practice/src/utils/database/getDatabaseConnection.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import pg, { Client, QueryResult } from 'pg';
|
|
2
|
+
|
|
3
|
+
import { getConfig } from '../config/getConfig';
|
|
4
|
+
|
|
5
|
+
// https://github.com/brianc/node-postgres/pull/353#issuecomment-283709264
|
|
6
|
+
pg.types.setTypeParser(20, (value) => parseInt(value, 10)); // cast bigints to numbers; by default, pg returns bigints as strings, since max val of bigint is bigger than max safe value in js
|
|
7
|
+
pg.types.setTypeParser(1700, (value) => parseFloat(value)); // cast numerics to numbers; by default, pg returns numerics as strings
|
|
8
|
+
|
|
9
|
+
export interface DatabaseConnection {
|
|
10
|
+
query: (args: { sql: string; values?: any[] }) => Promise<QueryResult<any>>;
|
|
11
|
+
end: () => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class DatabaseQueryError extends Error {
|
|
15
|
+
constructor({
|
|
16
|
+
sql,
|
|
17
|
+
values,
|
|
18
|
+
caught,
|
|
19
|
+
}: {
|
|
20
|
+
sql: string;
|
|
21
|
+
values?: any[];
|
|
22
|
+
caught: Error;
|
|
23
|
+
}) {
|
|
24
|
+
const message = `
|
|
25
|
+
caught error querying database: ${caught.message}
|
|
26
|
+
|
|
27
|
+
sql:
|
|
28
|
+
${sql.trim()}
|
|
29
|
+
|
|
30
|
+
values:
|
|
31
|
+
${JSON.stringify(values)}
|
|
32
|
+
`.trim();
|
|
33
|
+
super(message);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const getDatabaseConnection = async (): Promise<DatabaseConnection> => {
|
|
38
|
+
const config = await getConfig();
|
|
39
|
+
const dbConfig = config.database.service;
|
|
40
|
+
const client = new Client({
|
|
41
|
+
host: dbConfig.host,
|
|
42
|
+
user: dbConfig.username,
|
|
43
|
+
password: dbConfig.password,
|
|
44
|
+
database: dbConfig.schema,
|
|
45
|
+
port: dbConfig.port,
|
|
46
|
+
});
|
|
47
|
+
await client.connect();
|
|
48
|
+
await client.query(`SET search_path TO ${dbConfig.schema}, public;`); // https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-
|
|
49
|
+
const dbConnection = {
|
|
50
|
+
query: ({ sql, values }: { sql: string; values?: (string | number)[] }) =>
|
|
51
|
+
client.query(sql, values),
|
|
52
|
+
end: () => client.end(),
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
query: (args: { sql: string; values?: any[] }) =>
|
|
56
|
+
dbConnection.query(args).catch((error) => {
|
|
57
|
+
throw new DatabaseQueryError({
|
|
58
|
+
sql: args.sql,
|
|
59
|
+
values: args.values ?? [],
|
|
60
|
+
caught: error,
|
|
61
|
+
});
|
|
62
|
+
}),
|
|
63
|
+
end: () => dbConnection.end(),
|
|
64
|
+
};
|
|
65
|
+
};
|
package/dist/practices/persist-with-rds/best-practice/src/utils/database/withDatabaseConnection.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DatabaseConnection,
|
|
3
|
+
getDatabaseConnection,
|
|
4
|
+
} from './getDatabaseConnection';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* wraps the input function and gives it a managed database connection
|
|
8
|
+
*
|
|
9
|
+
* managed meaning: it is opened when it is passed in and it is closed when the logic finishes running or throws an error.
|
|
10
|
+
*
|
|
11
|
+
* example usage:
|
|
12
|
+
* ```
|
|
13
|
+
* const findById = withDatabaseConnection(({ id, dbConnection }: { id: string; dbConnection: DatabaseConnection }) => {
|
|
14
|
+
* // do logic with dbConnection
|
|
15
|
+
* });
|
|
16
|
+
* // ...
|
|
17
|
+
* await findById({ id: 821 }); // note how we dont have to pass in the dbConnection
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const withDatabaseConnection = <
|
|
21
|
+
P extends { dbConnection: DatabaseConnection },
|
|
22
|
+
R,
|
|
23
|
+
>(
|
|
24
|
+
logic: (args: P) => R | Promise<R>,
|
|
25
|
+
) => {
|
|
26
|
+
return async (args: Omit<P, 'dbConnection'>) => {
|
|
27
|
+
// open the db connection
|
|
28
|
+
const dbConnection = await getDatabaseConnection();
|
|
29
|
+
|
|
30
|
+
// try and run the logic with db connection
|
|
31
|
+
try {
|
|
32
|
+
return await logic({ ...args, dbConnection } as P); // as P because: https://github.com/microsoft/TypeScript/issues/35858
|
|
33
|
+
} finally {
|
|
34
|
+
// make sure to close the db connection, both when `logic` throws an error or succeeds
|
|
35
|
+
await dbConnection.end();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
};
|
package/dist/practices/persist-with-rds/best-practice/src/utils/database/withDatabaseTransaction.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DatabaseConnection } from './getDatabaseConnection';
|
|
2
|
+
|
|
3
|
+
export const withDatabaseTransaction = <
|
|
4
|
+
P extends { dbConnection: DatabaseConnection },
|
|
5
|
+
R,
|
|
6
|
+
>(
|
|
7
|
+
logic: (args: P) => R | Promise<R>,
|
|
8
|
+
): typeof logic => {
|
|
9
|
+
return (async (args: P) => {
|
|
10
|
+
await args.dbConnection.query({ sql: 'START TRANSACTION' }); // begin transaction
|
|
11
|
+
try {
|
|
12
|
+
const result = await logic({ ...args }); // run the request
|
|
13
|
+
await args.dbConnection.query({ sql: 'COMMIT' }); // commit if successful
|
|
14
|
+
return result;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
await args.dbConnection.query({ sql: 'ROLLBACK' }); // rollback if not successful
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
}) as typeof logic;
|
|
20
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FileCheckFunction, FileFixFunction } from 'declapract';
|
|
2
|
+
|
|
3
|
+
export const check: FileCheckFunction = (contents) => {
|
|
4
|
+
if (!contents) throw new Error('fine, does not match bad practice'); // if not defined, doesn't have the script
|
|
5
|
+
const parsedContents = JSON.parse(contents);
|
|
6
|
+
if (typeof parsedContents.scripts.format === 'string') return; // matches bad practice file
|
|
7
|
+
throw new Error('fine, does not have format script');
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const fix: FileFixFunction = (contents) => {
|
|
11
|
+
// parse the contents
|
|
12
|
+
if (!contents) return {}; // do nothing if no contents, shouldn't have reached here to begin with
|
|
13
|
+
const parsedContents = JSON.parse(contents);
|
|
14
|
+
|
|
15
|
+
// remove "format"
|
|
16
|
+
const fixedContents = {
|
|
17
|
+
...parsedContents,
|
|
18
|
+
scripts: {
|
|
19
|
+
...parsedContents.scripts,
|
|
20
|
+
format: undefined, // remove format
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// and return the fixed json
|
|
25
|
+
return { contents: JSON.stringify(fixedContents, null, 2) };
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.md
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"devDependencies": {
|
|
3
|
+
"prettier": "@declapract{check.minVersion('2.8.1')}",
|
|
4
|
+
"@trivago/prettier-plugin-sort-imports": "@declapract{check.minVersion('2.0.4')}"
|
|
5
|
+
},
|
|
6
|
+
"scripts": {
|
|
7
|
+
"fix:format:prettier": "prettier --write '**/*.ts' --config ./prettier.config.js",
|
|
8
|
+
"test:format:prettier": "prettier --parser typescript --check 'src/**/*.ts' --config ./prettier.config.js"
|
|
9
|
+
}
|
|
10
|
+
}
|