declapract-typescript-ehmpathy 0.39.18 → 0.41.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.
Files changed (53) hide show
  1. package/dist/practices/cicd-common/best-practice/.github/workflows/.declastruct.yml +109 -0
  2. package/dist/practices/cicd-common/best-practice/.github/workflows/.test.yml +17 -11
  3. package/dist/practices/cicd-common/best-practice/.github/workflows/release.yml +2 -2
  4. package/dist/practices/cicd-common/best-practice/.github/workflows/review.yml +1 -1
  5. package/dist/practices/cicd-package/best-practice/.github/workflows/provision.yml +24 -0
  6. package/dist/practices/cicd-service/best-practice/.agent/repo=.this/skills/use.rds.capacity.sh +45 -0
  7. package/dist/practices/cicd-service/best-practice/.agent/repo=.this/skills/use.vpc.tunnel.ts +79 -0
  8. package/dist/practices/cicd-service/best-practice/.github/workflows/.deploy-sls.yml +8 -31
  9. package/dist/practices/cicd-service/best-practice/.github/workflows/.sql-schema-control.yml +10 -49
  10. package/dist/practices/cicd-service/best-practice/.github/workflows/.terraform.yml +5 -5
  11. package/dist/practices/cicd-service/best-practice/.github/workflows/provision.yml +9 -15
  12. package/dist/practices/cicd-service/best-practice/package.json +7 -0
  13. package/dist/practices/cicd-service/best-practice/package.json.declapract.ts +3 -0
  14. package/dist/practices/domain/best-practice/package.json +2 -2
  15. package/dist/practices/errors/best-practice/package.json +1 -1
  16. package/dist/practices/git/best-practice/.gitignore.declapract.ts +1 -0
  17. package/dist/practices/lint/best-practice/.declapract.todo.md +5 -0
  18. package/dist/practices/lint/best-practice/.eslintrc.js +21 -1
  19. package/dist/practices/lint/best-practice/package.json +1 -0
  20. package/dist/practices/package-json-order/best-practice/package.json.declapract.ts +8 -6
  21. package/dist/practices/persist-with-dynamodb/best-practice/package.json +5 -4
  22. package/dist/practices/persist-with-rds/bad-practices/old-packagejson-script-names/package.json +9 -0
  23. package/dist/practices/persist-with-rds/bad-practices/old-packagejson-script-names/package.json.declapract.ts +22 -0
  24. package/dist/practices/persist-with-rds/best-practice/config/dev.json +21 -13
  25. package/dist/practices/persist-with-rds/best-practice/config/prod.json +21 -13
  26. package/dist/practices/persist-with-rds/best-practice/config/prod.json.declapract.ts +13 -1
  27. package/dist/practices/persist-with-rds/best-practice/config/test.json +18 -13
  28. package/dist/practices/persist-with-rds/best-practice/config/test.json.declapract.ts +13 -1
  29. package/dist/practices/persist-with-rds/best-practice/package.json +8 -6
  30. package/dist/practices/persist-with-rds/best-practice/provision/schema/connection.config.js +10 -11
  31. package/dist/practices/persist-with-rds/best-practice/provision/schema/deploy.database.sh +1 -1
  32. package/dist/practices/persist-with-rds/best-practice/src/utils/config/Config.ts +26 -0
  33. package/dist/practices/persist-with-rds/best-practice/src/utils/config/Config.ts.declapract.ts +39 -0
  34. package/dist/practices/persist-with-rds/best-practice/src/utils/database/getDatabaseConnection.ts +30 -9
  35. package/dist/practices/{terraform-github/best-practice → provision-github/bad-practices/terraform-github}/provision/github/environment/main.tf +1 -1
  36. package/dist/practices/provision-github/best-practice/package.json +6 -0
  37. package/dist/practices/provision-github/best-practice/package.json.declapract.ts +3 -0
  38. package/dist/practices/provision-github/best-practice/provision/github/declastruct.resources.ts +124 -0
  39. package/dist/practices/tests/best-practice/jest.acceptance.config.ts +3 -0
  40. package/dist/practices/tests/best-practice/jest.acceptance.env.ts +23 -2
  41. package/dist/practices/tests/best-practice/jest.integration.config.ts +3 -0
  42. package/dist/practices/tests/best-practice/jest.integration.env.ts +23 -2
  43. package/dist/practices/tests/best-practice/jest.unit.config.ts +3 -0
  44. package/dist/practices/tests/best-practice/jest.unit.env.ts +16 -1
  45. package/dist/practices/tests/best-practice/jest.unit.env.ts.declapract.ts +3 -2
  46. package/dist/practices/tests/best-practice/package.json +2 -2
  47. package/dist/practices/typescript/best-practice/tsconfig.build.json +7 -6
  48. package/dist/useCases.yml +3 -2
  49. package/package.json +4 -4
  50. package/readme.md +131 -20
  51. /package/dist/practices/{terraform-github/best-practice → provision-github/bad-practices/terraform-github}/provision/github/environment/import-existing-repo.sh +0 -0
  52. /package/dist/practices/{terraform-github/best-practice → provision-github/bad-practices/terraform-github}/provision/github/environment/versions.tf +0 -0
  53. /package/dist/practices/{terraform-github/best-practice → provision-github/bad-practices/terraform-github}/provision/github/product/repository.tf +0 -0
@@ -0,0 +1,124 @@
1
+ import { DeclastructProvider } from 'declastruct';
2
+ import {
3
+ DeclaredGithubBranch,
4
+ DeclaredGithubBranchProtection,
5
+ DeclaredGithubRepo,
6
+ DeclaredGithubRepoConfig,
7
+ getDeclastructGithubProvider,
8
+ } from 'declastruct-github';
9
+ import { DomainEntity, RefByUnique } from 'domain-objects';
10
+ import { UnexpectedCodePathError } from 'helpful-errors';
11
+
12
+ import pkg from '../../package.json';
13
+
14
+ export const getProviders = async (): Promise<DeclastructProvider[]> => [
15
+ getDeclastructGithubProvider(
16
+ {
17
+ credentials: {
18
+ token:
19
+ process.env.GITHUB_TOKEN ??
20
+ UnexpectedCodePathError.throw('github token not supplied'),
21
+ },
22
+ },
23
+ {
24
+ log: {
25
+ info: () => {},
26
+ debug: () => {},
27
+ warn: console.warn,
28
+ error: console.error,
29
+ },
30
+ },
31
+ ),
32
+ ];
33
+
34
+ export const getResources = async (): Promise<DomainEntity<any>[]> => {
35
+ // declare the repo
36
+ const repo = DeclaredGithubRepo.as({
37
+ owner: '@declapract{variable.organizationName}',
38
+ name: '@declapract{variable.projectName}',
39
+ description: (pkg as any).description ?? null,
40
+ visibility: (pkg as any).private === true ? 'private' : 'public',
41
+ private: (pkg as any).private ?? false, // todo: why do we have to specify this twice?
42
+ homepage: (pkg as any).homepage ?? null,
43
+
44
+ // things we haven't changed from the defaults
45
+ archived: false,
46
+ });
47
+
48
+ // ref the main branch
49
+ const branchMain = RefByUnique.as<typeof DeclaredGithubBranch>({
50
+ name: 'main',
51
+ repo,
52
+ });
53
+
54
+ // declare config for the repo
55
+ const repoConfig = DeclaredGithubRepoConfig.as({
56
+ repo,
57
+
58
+ // explicitly set the main branch
59
+ defaultBranch: branchMain.name,
60
+
61
+ // we only use issues; the rest is noise today
62
+ hasIssues: true,
63
+ hasProjects: false,
64
+ hasWiki: false,
65
+ hasDownloads: false,
66
+ isTemplate: false,
67
+
68
+ // only squash merges are allowed
69
+ allowSquashMerge: true,
70
+ allowMergeCommit: false, // but especially not merge merges. never merge merges
71
+ allowRebaseMerge: false,
72
+
73
+ // allow nice to haves for pulls
74
+ allowAutoMerge: true,
75
+ allowUpdateBranch: true,
76
+
77
+ // always cleanup after yourself
78
+ deleteBranchOnMerge: true,
79
+
80
+ // configure messages
81
+ mergeCommitMessage: 'PR_TITLE',
82
+ mergeCommitTitle: 'MERGE_MESSAGE',
83
+ squashMergeCommitMessage: 'COMMIT_MESSAGES',
84
+ squashMergeCommitTitle: 'COMMIT_OR_PR_TITLE',
85
+ webCommitSignoffRequired: false,
86
+ });
87
+
88
+ // declare protection for that branch, too
89
+ const branchMainProtection = DeclaredGithubBranchProtection.as({
90
+ branch: branchMain,
91
+
92
+ enforceAdmins: true, // yes, even admins need to follow this (note: they can still take the time to go and change the settings temporarily for the exceptions)
93
+ allowsDeletions: false, // dont allow the `main` branch to be deleted
94
+ allowsForcePushes: false, // dont allow `main` branch to be force pushed to
95
+ requireLinearHistory: false, // # no ugly merge commits, woo! 🎉
96
+
97
+ requiredStatusChecks: {
98
+ strict: true, // branch must be up to date. otherwise, we dont know if it will really pass once it is merged
99
+ contexts: [
100
+ 'suite / install / npm',
101
+ 'suite / test-commits',
102
+ 'suite / test-types',
103
+ 'suite / test-format',
104
+ 'suite / test-lint',
105
+ 'suite / test-unit',
106
+ 'suite / test-integration',
107
+ 'suite / test-acceptance-locally',
108
+ 'pullreq-title', // "review / pullreq-title",
109
+ ],
110
+ },
111
+
112
+ // things we haven't changed from the defaults
113
+ allowForkSyncing: false,
114
+ blockCreations: false,
115
+ lockBranch: false,
116
+ requiredConversationResolution: false,
117
+ requiredPullRequestReviews: null,
118
+ requiredSignatures: false,
119
+ restrictions: null,
120
+ });
121
+
122
+ // and return the full set
123
+ return [repo, repoConfig, branchMainProtection];
124
+ };
@@ -22,6 +22,9 @@ const config: Config = {
22
22
  testMatch: ['**/*.acceptance.test.ts'],
23
23
  setupFiles: ['core-js'],
24
24
  setupFilesAfterEnv: ['./jest.acceptance.env.ts'],
25
+
26
+ // use 50% of threads to leave headroom for other processes
27
+ maxWorkers: '50%', // https://stackoverflow.com/questions/71287710/why-does-jest-run-faster-with-maxworkers-50
25
28
  };
26
29
 
27
30
  // eslint-disable-next-line import/no-default-export
@@ -1,13 +1,34 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import util from 'util';
4
+
1
5
  // eslint-disable-next-line no-undef
2
6
  jest.setTimeout(90000); // we're calling downstream apis
3
7
 
8
+ // set console.log to not truncate nested objects
9
+ util.inspect.defaultOptions.depth = 5;
10
+
11
+ /**
12
+ * .what = verify that we're running from a valid project directory; otherwise, fail fast
13
+ * .why = prevent confusion and hard-to-debug errors from running tests in the wrong directory
14
+ */
15
+ if (!existsSync(join(process.cwd(), 'package.json')))
16
+ throw new Error('no package.json found in cwd. are you @gitroot?');
17
+
4
18
  /**
5
- * .what = verify that the env has sufficient auth to run the tests; otherwise, fail fast
19
+ * .what = verify that the env has sufficient auth to run the tests if aws is used; otherwise, fail fast
6
20
  * .why =
7
21
  * - prevent time wasted waiting on tests to fail due to lack of credentials
8
22
  * - prevent time wasted debugging tests which are failing due to hard-to-read missed credential errors
9
23
  */
10
- if (!(process.env.AWS_PROFILE || process.env.AWS_ACCESS_KEY_ID))
24
+ const declapractUsePath = join(process.cwd(), 'declapract.use.ts');
25
+ const requiresAwsAuth =
26
+ existsSync(declapractUsePath) &&
27
+ readFileSync(declapractUsePath, 'utf8').includes('awsAccountId');
28
+ if (
29
+ requiresAwsAuth &&
30
+ !(process.env.AWS_PROFILE || process.env.AWS_ACCESS_KEY_ID)
31
+ )
11
32
  throw new Error(
12
33
  'no aws credentials present. please authenticate with aws to run acceptance tests',
13
34
  );
@@ -22,6 +22,9 @@ const config: Config = {
22
22
  testMatch: ['**/*.integration.test.ts'],
23
23
  setupFiles: ['core-js'],
24
24
  setupFilesAfterEnv: ['./jest.integration.env.ts'],
25
+
26
+ // use 50% of threads to leave headroom for other processes
27
+ maxWorkers: '50%', // https://stackoverflow.com/questions/71287710/why-does-jest-run-faster-with-maxworkers-50
25
28
  };
26
29
 
27
30
  // eslint-disable-next-line import/no-default-export
@@ -1,6 +1,20 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import util from 'util';
4
+
1
5
  // eslint-disable-next-line no-undef
2
6
  jest.setTimeout(90000); // since we're calling downstream apis
3
7
 
8
+ // set console.log to not truncate nested objects
9
+ util.inspect.defaultOptions.depth = 5;
10
+
11
+ /**
12
+ * .what = verify that we're running from a valid project directory; otherwise, fail fast
13
+ * .why = prevent confusion and hard-to-debug errors from running tests in the wrong directory
14
+ */
15
+ if (!existsSync(join(process.cwd(), 'package.json')))
16
+ throw new Error('no package.json found in cwd. are you @gitroot?');
17
+
4
18
  /**
5
19
  * sanity check that unit tests are only run the 'test' environment
6
20
  *
@@ -15,12 +29,19 @@ if (
15
29
  throw new Error(`integration.test is not targeting stage 'test'`);
16
30
 
17
31
  /**
18
- * .what = verify that the env has sufficient auth to run the tests; otherwise, fail fast
32
+ * .what = verify that the env has sufficient auth to run the tests if aws is used; otherwise, fail fast
19
33
  * .why =
20
34
  * - prevent time wasted waiting on tests to fail due to lack of credentials
21
35
  * - prevent time wasted debugging tests which are failing due to hard-to-read missed credential errors
22
36
  */
23
- if (!(process.env.AWS_PROFILE || process.env.AWS_ACCESS_KEY_ID))
37
+ const declapractUsePath = join(process.cwd(), 'declapract.use.ts');
38
+ const requiresAwsAuth =
39
+ existsSync(declapractUsePath) &&
40
+ readFileSync(declapractUsePath, 'utf8').includes('awsAccountId');
41
+ if (
42
+ requiresAwsAuth &&
43
+ !(process.env.AWS_PROFILE || process.env.AWS_ACCESS_KEY_ID)
44
+ )
24
45
  throw new Error(
25
46
  'no aws credentials present. please authenticate with aws to run integration tests',
26
47
  );
@@ -27,6 +27,9 @@ const config: Config = {
27
27
  ],
28
28
  setupFiles: ['core-js'],
29
29
  setupFilesAfterEnv: ['./jest.unit.env.ts'],
30
+
31
+ // use 50% of threads to leave headroom for other processes
32
+ maxWorkers: '50%', // https://stackoverflow.com/questions/71287710/why-does-jest-run-faster-with-maxworkers-50
30
33
  };
31
34
 
32
35
  // eslint-disable-next-line import/no-default-export
@@ -1,7 +1,22 @@
1
+ import { existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import util from 'util';
4
+
5
+ // mock that getConfig just returns plaintext test env config in unit tests
1
6
  jest.mock('./src/utils/config/getConfig', () => ({
2
- getConfig: jest.fn().mockImplementation(() => require('./config/test.json')), // mock that getConfig just returns plaintext test env config in unit tests
7
+ getConfig: jest.fn().mockImplementation(() => require('./config/test.json')),
3
8
  }));
4
9
 
10
+ // set console.log to not truncate nested objects
11
+ util.inspect.defaultOptions.depth = 5;
12
+
13
+ /**
14
+ * .what = verify that we're running from a valid project directory; otherwise, fail fast
15
+ * .why = prevent confusion and hard-to-debug errors from running tests in the wrong directory
16
+ */
17
+ if (!existsSync(join(process.cwd(), 'package.json')))
18
+ throw new Error('no package.json found in cwd. are you @gitroot?');
19
+
5
20
  /**
6
21
  * sanity check that unit tests are only run the 'test' environment
7
22
  *
@@ -15,8 +15,9 @@ export const contents: FileContentsFunction = async (context) => {
15
15
  let contents = contentsSuperset;
16
16
  if (!context.projectPractices.includes('config'))
17
17
  contents = contents.replace(
18
- `jest.mock('./src/utils/config/getConfig', () => ({
19
- getConfig: jest.fn().mockImplementation(() => require('./config/test.json')), // mock that getConfig just returns plaintext test env config in unit tests
18
+ `// mock that getConfig just returns plaintext test env config in unit tests
19
+ jest.mock('./src/utils/config/getConfig', () => ({
20
+ getConfig: jest.fn().mockImplementation(() => require('./config/test.json')),
20
21
  }));
21
22
 
22
23
  `,
@@ -3,8 +3,8 @@
3
3
  "@types/jest": "@declapract{check.minVersion('29.2.4')}",
4
4
  "jest": "@declapract{check.minVersion('29.3.1')}",
5
5
  "test-fns": "@declapract{check.minVersion('1.4.2')}",
6
- "ts-jest": "@declapract{check.minVersion('29.1.3')}",
7
- "ts-node": "@declapract{check.minVersion('10.9.2')}",
6
+ "ts-jest": "@declapract{check.minVersion('29.4.5')}",
7
+ "tsx": "@declapract{check.minVersion('4.20.6')}",
8
8
  "core-js": "@declapract{check.minVersion('3.26.1')}",
9
9
  "@babel/core": "@declapract{check.minVersion('7.28.5')}",
10
10
  "@babel/preset-env": "@declapract{check.minVersion('7.28.5')}",
@@ -4,13 +4,14 @@
4
4
  "rootDir": "src"
5
5
  },
6
6
  "include": [
7
- "src/**/*.ts"
7
+ "src/**/*.ts",
8
+ "nontyped_modules/**/*.d.ts"
8
9
  ],
9
10
  "exclude": [
10
- "**/*.test.(ts|js)", // all explicitly .test files are dev only assets too
11
- "**/.test/**/*.(ts|js)",
12
- "src/**/.scratch/**/*.(ts|js)",
13
- "src/**/__test_utils__/**/*.(ts|js)",
14
- "src/**/__test_assets__/**/*.(ts|js)"
11
+ "**/*.test.ts", // all explicitly .test files are dev only assets too
12
+ "**/*.test.js",
13
+ "**/.test/**/*",
14
+ "**/.scratch/**/*",
15
+ "**/__test*__/**/*" // todo: deprecate this pattern in favor of .test
15
16
  ]
16
17
  }
package/dist/useCases.yml CHANGED
@@ -23,6 +23,7 @@ use-cases:
23
23
  practices:
24
24
  - cicd-package
25
25
  - node-package
26
+ - provision-github
26
27
  lambda-service:
27
28
  extends:
28
29
  - typescript-project
@@ -40,8 +41,8 @@ use-cases:
40
41
  - node-service
41
42
  - runtime-type-checking
42
43
  - serverless
44
+ - provision-github
43
45
  - terraform-common
44
- - terraform-github
45
46
  - terraform-aws
46
47
  - tests-service
47
48
  - uuid
@@ -70,7 +71,7 @@ use-cases:
70
71
  - package-json-order
71
72
  - prettier
72
73
  - terraform-common
73
- - terraform-github
74
+ - provision-github
74
75
  - lint
75
76
  - lint-react
76
77
  - lint-react-native
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "declapract-typescript-ehmpathy",
3
3
  "author": "ehmpathy",
4
4
  "description": "declapract best practices declarations for typescript",
5
- "version": "0.39.18",
5
+ "version": "0.41.0",
6
6
  "license": "MIT",
7
7
  "main": "src/index.js",
8
8
  "repository": "ehmpathy/declapract-typescript-ehmpathy",
@@ -41,10 +41,10 @@
41
41
  "prepare:husky": "npx husky install && chmod ug+x .husky/*"
42
42
  },
43
43
  "dependencies": {
44
- "domain-objects": "0.22.1",
44
+ "domain-objects": "0.29.2",
45
45
  "expect": "29.4.2",
46
46
  "flat": "5.0.2",
47
- "helpful-errors": "1.3.8",
47
+ "helpful-errors": "1.5.3",
48
48
  "simple-log-methods": "0.5.0"
49
49
  },
50
50
  "peerDependencies": {
@@ -68,12 +68,12 @@
68
68
  "eslint-config-prettier": "8.5.0",
69
69
  "eslint-plugin-import": "2.26.0",
70
70
  "eslint-plugin-prettier": "4.2.1",
71
+ "eslint-plugin-unused-imports": "4.3.0",
71
72
  "husky": "8.0.3",
72
73
  "jest": "29.3.1",
73
74
  "prettier": "2.8.1",
74
75
  "test-fns": "1.4.2",
75
76
  "ts-jest": "29.1.3",
76
- "ts-node": "10.9.2",
77
77
  "type-fns": "0.8.1",
78
78
  "typescript": "5.4.5",
79
79
  "visualogic": "1.2.3"
package/readme.md CHANGED
@@ -1,39 +1,150 @@
1
1
  # declapract-typescript-ehmpathy
2
2
 
3
- declapract = declared best practices
3
+ Declared best practices for TypeScript projects.
4
4
 
5
- this repo contains the [ehmpathy org's](https://github.com/ehmpathy) declared best practices for typescript, for usage with [declapract](https://github.com/ehmpathy/declapract)
5
+ Sync your projects with the latest and greatest best practices with codemods powered by [declapract](https://github.com/ehmpathy/declapract).
6
6
 
7
- # usage
7
+ ## What is this?
8
+
9
+ This package contains battle-tested TypeScript best practices from the [ehmpathy org](https://github.com/ehmpathy), packaged for automated enforcement via codemods through [declapract](https://github.com/ehmpathy/declapract).
10
+
11
+ Instead of adhoc configuration of linters, formatters, test frameworks, cicd pipelines, and infrastructure for every project, this package provides:
12
+
13
+ - **40+ declared practices** covering TypeScript development, testing, CI/CD, AWS infrastructure, and more
14
+ - **Automated checking** to verify your repo follows best practices - and avoids bad practices
15
+ - **Automatic fixes** for most common issues
16
+ - **Project templates** to bootstrap new projects with everything configured
17
+
18
+ ## How to use it?
19
+
20
+ ### 1. Install declapract
8
21
 
9
- 1. add `declapract` to your repo
10
22
  ```sh
11
23
  npm install --save-dev declapract
12
24
  ```
13
25
 
14
- 2. add a declapract usage config to your repo
26
+ ### 2. Configure your project
27
+
28
+ Create `declapract.use.yml` in your repo:
29
+
15
30
  ```yml
16
- # declapract.use.yml
17
31
  declarations: npm:declapract-typescript-ehmpathy
18
- useCase: lambda-service # specify which use case your repo is following, see `declapract-typescript-ehmpathy:src/useCases.yml` for options
19
- variables: # specify the values of the variables to use against checks
20
- organizationName: 'awesome-org'
21
- projectName: 'svc-awesome-thing'
22
- infrastructureNamespaceId: 'abcde12345'
23
- slackReleaseWebHook: 'https://...'
32
+ useCase: typescript-project # Choose from: typescript-project, npm-package, lambda-service, lambda-service-with-rds, lambda-service-with-dynamodb, app-react-native-expo
33
+ variables:
34
+ organizationName: 'my-org'
35
+ projectName: 'my-project'
36
+ infrastructureNamespaceId: 'prod-abc123'
37
+ slackReleaseWebHook: 'https://hooks.slack.com/...'
24
38
  ```
25
39
 
26
- 3. clone a declared best practices example, do bootstrap a new repo
40
+ ### 3. Plan changes
41
+
27
42
  ```sh
28
- declapract clone lambda-service-with-rds # bootstrap a new lambda-service-with-rds repo
29
- ```
43
+ # plan all practices
44
+ declapract plan
30
45
 
31
- 4. check that your repo is conforming to best practices
32
- ```
33
- declapract check
46
+ # or scope to one
47
+ declapract plan --practice
34
48
  ```
35
49
 
36
- 5. fix a specific practice that your repo is failing to conform to (if it has an automatic fix declared)
50
+ ### 4. Apply changes
51
+
37
52
  ```sh
38
- declapract fix --practice dates-and-times # e.g., apply a fix for the the dates-and-times practice
53
+ # apply all practices
54
+ declapract apply
55
+
56
+ # or scope to one
57
+ declapract apply --practice
39
58
  ```
59
+
60
+ ## Benefits
61
+
62
+ ### Consistency
63
+ All projects follow the same patterns, making it easy to switch between codebases
64
+
65
+ ### Quality
66
+ Enforced best practices catch issues before code review
67
+
68
+ ### Speed
69
+ Bootstrap new projects in minutes instead of hours
70
+
71
+ ### Maintenance
72
+ Update best practices across all repos by updating one dependency
73
+
74
+ ### Documentation
75
+ Practices are explicitly declared and versioned, serving as living documentation
76
+
77
+ ## What use cases are supported?
78
+
79
+ This package defines complete sets of practices for common project types:
80
+
81
+ ### `typescript-project`
82
+ Base configuration for any TypeScript project (18 core practices)
83
+
84
+ ### `npm-package`
85
+ TypeScript packages published to npm (adds CI/CD for publishing)
86
+
87
+ ### `lambda-service`
88
+ AWS Lambda microservices (adds AWS infrastructure, handlers, config, logging)
89
+
90
+ ### `lambda-service-with-rds`
91
+ Lambda services with PostgreSQL database (adds RDS provisioning and DAOs)
92
+
93
+ ### `lambda-service-with-dynamodb`
94
+ Lambda services with DynamoDB (adds DynamoDB DAOs)
95
+
96
+ ### `app-react-native-expo`
97
+ React Native mobile apps with Expo
98
+
99
+ ## What practices are included?
100
+
101
+ ### Core TypeScript Development
102
+ - **typescript** - Strict TypeScript configuration
103
+ - **lint** - ESLint with TypeScript rules (airbnb-typescript)
104
+ - **format** - Prettier configuration
105
+ - **domain** - Domain-driven design with `domain-objects`
106
+ - **directory-structure-src** - Consistent project structures
107
+ - **runtime-type-checking** - Type-safe validation with `domain-objects`
108
+ - **errors** - Structured error handling with `helpful-errors`
109
+ - etc
110
+
111
+ ### Tests & Quality
112
+ - **tests** - Jest configuration for unit, integration, and acceptance tests
113
+ - **conventional-commits** - Enforced commit message standards
114
+ - **husky** - Git hooks for pre-commit validation
115
+ - etc
116
+
117
+ ### CI/CD
118
+ - **cicd-common** - GitHub Actions workflows for testing
119
+ - **cicd-package** - Publishing workflows for npm packages
120
+ - **cicd-service** - Deployment workflows for services
121
+
122
+ ### AWS Lambda Services
123
+ - **lambda-handlers** - Standard Lambda function structure
124
+ - **lambda-clients** - Type-safe Lambda client wrappers
125
+ - **config** - Environment configuration with AWS Parameter Store
126
+ - **logs** - Structured logging with `simple-log-methods`
127
+ - **uuid** - UUID generation standards
128
+ - etc
129
+
130
+ ### Infrastructure
131
+ - **terraform-common** - Common Terraform patterns
132
+ - **terraform-aws** - AWS-specific Terraform modules
133
+ - **declastruct-github** - GitHub repository configuration
134
+ - **environments-aws** - Multi-environment setup (dev/test/prod)
135
+ - etc
136
+
137
+ ### Persistence
138
+ - **persist-with-rds** - PostgreSQL with `sql-dao-generator`
139
+ - **persist-with-dynamodb** - DynamoDB DAO patterns
140
+
141
+ ### React Native
142
+ - **app-react-native-expo** - Expo app configuration
143
+ - **lint-react** - React-specific linting
144
+ - **lint-react-native** - React Native linting
145
+
146
+ ## Learn more
147
+
148
+ - [declapract documentation](https://github.com/ehmpathy/declapract)
149
+ - [full list of practices](./src/practices)
150
+ - [full list of usecases](./src/useCases.yml)