declapract-typescript-ehmpathy 0.42.3 → 0.42.5

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 (43) hide show
  1. package/dist/practices/artifact/best-practice/package.json +1 -1
  2. package/dist/practices/cicd-service/best-practice/package.json +1 -1
  3. package/dist/practices/config/best-practice/src/utils/config/getConfig.ts +4 -3
  4. package/dist/practices/environments/best-practice/package.json +7 -0
  5. package/dist/practices/environments/best-practice/package.json.declapract.ts +3 -0
  6. package/dist/practices/environments/best-practice/src/utils/environment.ts +105 -13
  7. package/dist/practices/git/best-practice/.gitignore.declapract.ts +1 -0
  8. package/dist/practices/lint/bad-practices/depcheck-denylisted-ignores/.declapract.readme.md +8 -0
  9. package/dist/practices/lint/bad-practices/depcheck-denylisted-ignores/.depcheckrc.yml.declapract.ts +59 -0
  10. package/dist/practices/lint/best-practice/.depcheckrc.yml +3 -7
  11. package/dist/practices/lint/best-practice/.depcheckrc.yml.declapract.ts +38 -1
  12. package/dist/practices/persist-with-rds/bad-practices/old-integration-test-db-dir/.declapract.readme.md +1 -1
  13. package/dist/practices/persist-with-rds/bad-practices/old-integration-test-db-dir/provision/docker/integration_test_db/<star><star>/<star>.declapract.ts +13 -1
  14. package/dist/practices/persist-with-rds/bad-practices/old-integration-test-db-hyphen-dir/.declapract.readme.md +1 -0
  15. package/dist/practices/persist-with-rds/bad-practices/old-integration-test-db-hyphen-dir/provision/docker/integration-test-db/<star><star>/<star>.declapract.ts +15 -0
  16. package/dist/practices/persist-with-rds/bad-practices/old-integration-test-db-paths/.declapract.readme.md +1 -0
  17. package/dist/practices/persist-with-rds/bad-practices/old-integration-test-db-paths/package.json +8 -0
  18. package/dist/practices/persist-with-rds/bad-practices/old-integration-test-db-paths/package.json.declapract.ts +10 -0
  19. package/dist/practices/persist-with-rds/best-practice/package.json +5 -5
  20. package/dist/practices/persist-with-rds/best-practice/provision/docker/{integration-test-db → testdb}/build-image.dockerfile +1 -1
  21. package/dist/practices/persist-with-rds/best-practice/provision/docker/{integration-test-db → testdb}/docker-compose.yml +5 -0
  22. package/dist/practices/persist-with-rds/best-practice/provision/schema/deploy.database.sh +1 -1
  23. package/dist/practices/persist-with-rds/best-practice/src/utils/database/getDatabaseConnection.ts +2 -1
  24. package/dist/practices/pnpm/best-practice/.agent/repo=.this/skills/use.npm.alias.sh +6 -5
  25. package/dist/practices/prettier/best-practice/.prettierignore +1 -0
  26. package/dist/practices/prettier/best-practice/prettier.config.js +1 -0
  27. package/dist/practices/provision-github/best-practice/package.json +1 -1
  28. package/dist/practices/tests/bad-practices/deprecated-test-deps/.declapract.readme.md +7 -0
  29. package/dist/practices/tests/bad-practices/deprecated-test-deps/package.json +9 -0
  30. package/dist/practices/tests/bad-practices/deprecated-test-deps/package.json.declapract.ts +39 -0
  31. package/dist/practices/tests/best-practice/jest.acceptance.config.ts +1 -3
  32. package/dist/practices/tests/best-practice/jest.acceptance.env.ts +1 -1
  33. package/dist/practices/tests/best-practice/jest.integration.config.ts +1 -3
  34. package/dist/practices/tests/best-practice/jest.integration.env.ts +3 -2
  35. package/dist/practices/tests/best-practice/jest.unit.config.ts +1 -3
  36. package/dist/practices/tests/best-practice/package.json +2 -5
  37. package/dist/practices/typescript/best-practice/package.json +1 -1
  38. package/dist/practices/typescript/best-practice/tsconfig.build.json +2 -1
  39. package/dist/practices/typescript/best-practice/tsconfig.json +1 -0
  40. package/package.json +3 -2
  41. /package/dist/practices/persist-with-rds/best-practice/provision/docker/{integration-test-db → testdb}/init/.gitignore +0 -0
  42. /package/dist/practices/persist-with-rds/best-practice/provision/docker/{integration-test-db → testdb}/init/readme.md +0 -0
  43. /package/dist/practices/persist-with-rds/best-practice/provision/docker/{integration-test-db → testdb}/wait-for-postgres.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "devDependencies": {
3
- "simple-artifact-builder": "@declapract{check.minVersion('1.1.13')}"
3
+ "simple-artifact-builder": "@declapract{check.minVersion('1.1.15')}"
4
4
  },
5
5
  "scripts": {
6
6
  "build:artifact": "npx simple-artifact-builder zip"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "devDependencies": {
3
- "declastruct": "@declapract{check.minVersion('1.3.0')}",
3
+ "declastruct": "@declapract{check.minVersion('1.4.0')}",
4
4
  "declastruct-aws": "@declapract{check.minVersion('1.0.3')}",
5
5
  "declastruct-unix-network": "@declapract{check.minVersion('1.0.0')}"
6
6
  }
@@ -1,8 +1,9 @@
1
1
  // export a default instance of the config object
2
2
  import ConfigCache from 'config-with-paramstore';
3
3
 
4
- import { stage } from '../environment';
5
- import { Config } from './Config';
4
+ import { getEnvironment } from '../environment';
5
+ import { type Config } from './Config';
6
6
 
7
7
  export const configInstance = new ConfigCache();
8
- export const getConfig = async (): Promise<Config> => configInstance.get(stage);
8
+ export const getConfig = async (): Promise<Config> =>
9
+ configInstance.get((await getEnvironment()).config);
@@ -0,0 +1,7 @@
1
+ {
2
+ "dependencies": {
3
+ "@aws-sdk/client-iam": "@declapract{check.minVersion('3.940.0')}",
4
+ "with-simple-cache": "@declapract{check.minVersion('0.15.1')}",
5
+ "simple-in-memory-cache": "@declapract{check.minVersion('0.4.0')}"
6
+ }
7
+ }
@@ -0,0 +1,3 @@
1
+ import { FileCheckType } from 'declapract';
2
+
3
+ export const check = FileCheckType.CONTAINS;
@@ -1,8 +1,29 @@
1
- import { createIsOfEnum } from 'type-fns';
1
+ import {
2
+ IAMClient,
3
+ ListAccountAliasesCommand,
4
+ type ListAccountAliasesCommandOutput,
5
+ } from '@aws-sdk/client-iam';
6
+ import { UnexpectedCodePathError } from 'helpful-errors';
7
+ import { createCache } from 'simple-in-memory-cache';
8
+ import { createIsOfEnum, type Literalize } from 'type-fns';
9
+ import { withSimpleCache } from 'with-simple-cache';
2
10
 
3
11
  import { log } from './logger';
4
12
 
5
- export enum Stage {
13
+ export enum ConfigChoice {
14
+ PRODUCTION = 'prod',
15
+ DEVELOPMENT = 'dev',
16
+ TEST = 'test',
17
+ }
18
+ export const isOfConfigChoice = createIsOfEnum(ConfigChoice);
19
+
20
+ export enum Access {
21
+ PRODUCTION = 'prod',
22
+ DEVELOPMENT = 'dev',
23
+ }
24
+ export const isOfAccess = createIsOfEnum(Access);
25
+
26
+ export enum Stage { // todo: deprecate stage
6
27
  PRODUCTION = 'prod',
7
28
  DEVELOPMENT = 'dev',
8
29
  TEST = 'test',
@@ -19,7 +40,7 @@ export const isOfStage = createIsOfEnum(Stage);
19
40
  */
20
41
  const TIMEZONE = process.env.TZ;
21
42
  if (TIMEZONE !== 'UTC') {
22
- log.warn(
43
+ log.debug(
23
44
  'env.TZ is not set to UTC. this can cause issues. updating this on your behalf',
24
45
  { found: TIMEZONE, desire: 'UTC' },
25
46
  );
@@ -43,27 +64,98 @@ const inferStageFromNodeEnv = () => {
43
64
  /**
44
65
  * a method that exposes relevant environmental variables in a standard way
45
66
  */
46
- const getEnvironment = () => {
67
+ export const getStage = (): Stage => {
47
68
  const stage = process.env.STAGE ?? inferStageFromNodeEnv(); // figure it out from NODE_ENV if not explicitly defined
48
69
  if (!stage) throw new Error('process.env.STAGE must be defined');
49
70
  if (!isOfStage(stage)) throw new Error(`invalid stage defined '${stage}'`);
50
- return { stage };
71
+ return stage;
51
72
  };
52
73
 
53
- // export stage immediately, since it does not change; // todo: replace this with env.access
54
- export const { stage } = getEnvironment();
74
+ /**
75
+ * .what = infer access (prod/dev) from curernt credentials
76
+ *
77
+ * .why?
78
+ * - allows detection of the access grain we are currently authenticated into, if authenticated
79
+ * - account aliases typically contain the environment (e.g., 'ahbode-dev', 'ahbode-prod')
80
+ */
81
+ export const inferAccess = withSimpleCache(
82
+ async (): Promise<Access | null> => {
83
+ // skip aws api calls if no credentials are configured
84
+ if (!process.env.AWS_PROFILE && !process.env.AWS_ACCESS_KEY_ID) return null;
85
+
86
+ // grab the alias of the current account
87
+ const iam = new IAMClient({});
88
+ const response: ListAccountAliasesCommandOutput = await iam.send(
89
+ new ListAccountAliasesCommand({}),
90
+ );
91
+
92
+ // infer access from alias
93
+ const alias = response.AccountAliases?.[0];
94
+ if (alias?.includes('prod')) return Access.PRODUCTION;
95
+ if (alias?.includes('dev')) return Access.DEVELOPMENT;
96
+ throw new Error(`Could not infer access from account alias '${alias}'`);
97
+ },
98
+ { cache: createCache() },
99
+ );
55
100
 
56
- // export service client stage
57
- export const serviceClientStage =
58
- stage === Stage.PRODUCTION ? Stage.PRODUCTION : Stage.DEVELOPMENT; // i.e., if its prod, hit prod. otherwise, dev
101
+ /**
102
+ * infer stage from access (prod/dev)
103
+ *
104
+ * logic:
105
+ * - if NODE_ENV === 'test', return test (test environment always uses test config)
106
+ * - otherwise, defer to access from AWS credentials
107
+ */
108
+ const inferConfigChoice = async (): Promise<ConfigChoice> => {
109
+ // grab some facts
110
+ const access = await inferAccess();
111
+ const envarNode = process.env.NODE_ENV;
112
+ const envarConfig = process.env.CONFIG ?? process.env.STAGE; // fallback to stage as alias to config choice
113
+
114
+ // if access is against prod, then must use prod config; no exceptions
115
+ if (access === Access.PRODUCTION) return ConfigChoice.PRODUCTION;
116
+
117
+ // if access is against prep and asked for dev, then use dev config
118
+ if (access === Access.DEVELOPMENT && envarConfig === 'dev')
119
+ return ConfigChoice.DEVELOPMENT;
120
+
121
+ // if access is against prep and asked for test, then use test config
122
+ if (access === Access.DEVELOPMENT && envarNode === 'test')
123
+ return ConfigChoice.TEST;
124
+
125
+ // if access is against prep and not asked for test, then must use dev config
126
+ if (access === Access.DEVELOPMENT) return ConfigChoice.DEVELOPMENT;
127
+
128
+ // otherwise, unsupported
129
+ throw new UnexpectedCodePathError(
130
+ 'Could not infer config choice: NODE_ENV is not test and no valid access could be determined',
131
+ { access, envarNode, envarConfig },
132
+ );
133
+ };
59
134
 
60
135
  // export the v3 environmental variables
61
- export const environment = {
62
- access: stage,
136
+ export interface Environment {
137
+ /**
138
+ * .what = the choice of config to execute against
139
+ */
140
+ config: Literalize<ConfigChoice>;
141
+
142
+ /**
143
+ * .what = the resources accessible from this environment, if any
144
+ */
145
+ access: Literalize<Access> | null;
146
+
147
+ /**
148
+ * .what = the server that hosts this environment
149
+ */
150
+ server: 'CICD' | 'AWS:LAMBDA' | 'LOCAL';
151
+ }
152
+ export const getEnvironment = async (): Promise<Environment> => ({
153
+ config: await inferConfigChoice(),
154
+ access: await inferAccess(),
63
155
  server: (() => {
64
156
  if (process.env.CI) return 'CICD' as const;
65
157
  if (process.env.LAMBDA_TASK_ROOT) return 'AWS:LAMBDA' as const;
66
158
  return 'LOCAL' as const; // default to local
67
159
  })(),
68
160
  // region: // todo
69
- };
161
+ });
@@ -12,6 +12,7 @@ const expectedIgnores = [
12
12
  '.terraform.lock',
13
13
  '.yalc',
14
14
  '.temp',
15
+ '.vscode',
15
16
  'coverage',
16
17
  'dist',
17
18
  'node_modules',
@@ -0,0 +1,8 @@
1
+ These packages should not be ignored in depcheck - they are either deprecated or have better alternatives:
2
+
3
+ - date-fns: use luxon instead
4
+ - procedure-fns: deprecated
5
+ - ts-node: use tsx instead
6
+ - ts-jest: use @swc/jest instead
7
+ - core-js: no longer needed with modern node
8
+ - babel-jest: use @swc/jest instead
@@ -0,0 +1,59 @@
1
+ import { FileCheckFunction, FileFixFunction } from 'declapract';
2
+ import expect from 'expect';
3
+ import yaml from 'yaml';
4
+
5
+ const denylist = [
6
+ 'date-fns',
7
+ 'procedure-fns',
8
+ 'ts-node',
9
+ 'ts-jest',
10
+ 'core-js',
11
+ 'babel-jest',
12
+ ];
13
+
14
+ export const check: FileCheckFunction = (contents) => {
15
+ if (!contents) throw new Error('no file found'); // no file = not bad practice
16
+
17
+ const parsed = yaml.parse(contents) as { ignores?: string[] };
18
+ const currentIgnores = parsed?.ignores ?? [];
19
+
20
+ // Find denylisted ignores that are present
21
+ const denylistedPresent = currentIgnores.filter((item) =>
22
+ denylist.includes(item),
23
+ );
24
+
25
+ // Bad practice: throw if no denylisted items found (all is fine), return if denylisted items exist
26
+ if (denylistedPresent.length === 0) {
27
+ throw new Error('no denylisted packages found in ignores');
28
+ }
29
+ // Return (don't throw) = bad practice detected
30
+ };
31
+
32
+ export const fix: FileFixFunction = (contents) => {
33
+ if (!contents) return { contents };
34
+
35
+ // Parse using parseDocument to preserve comments
36
+ const doc = yaml.parseDocument(contents);
37
+ const parsed = doc.toJSON() as { ignores?: string[] };
38
+ const currentIgnores = parsed?.ignores ?? [];
39
+
40
+ // Find denylisted ignores that are present
41
+ const denylistedPresent = currentIgnores.filter((item) =>
42
+ denylist.includes(item),
43
+ );
44
+
45
+ if (denylistedPresent.length === 0) return { contents };
46
+
47
+ // Remove denylisted ignores from the document
48
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
+ const ignoresNode = doc.get('ignores') as any;
50
+ if (ignoresNode?.items) {
51
+ // Filter out denylisted items
52
+ ignoresNode.items = ignoresNode.items.filter(
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ (item: any) => !denylist.includes(item.value ?? item),
55
+ );
56
+ }
57
+
58
+ return { contents: doc.toString() };
59
+ };
@@ -1,15 +1,11 @@
1
1
  ignores:
2
- - depcheck
2
+ - rhachet
3
3
  - declapract
4
4
  - declapract-typescript-ehmpathy
5
5
  - '@commitlint/config-conventional'
6
6
  - '@trivago/prettier-plugin-sort-imports'
7
7
  - '@tsconfig/node-lts-strictest'
8
- - babel-jest
9
- - core-js
10
- - ts-jest
11
8
  - tsx
12
9
  - husky
13
- - if-env
14
- - test-fns
15
- - helpful-errors
10
+ - '@swc/core'
11
+ - '@swc/jest'
@@ -1,4 +1,41 @@
1
1
  // eslint-disable-next-line import/no-extraneous-dependencies
2
- import { FileCheckType } from 'declapract';
2
+ import { FileCheckType, FileFixFunction } from 'declapract';
3
+ // eslint-disable-next-line import/no-extraneous-dependencies
4
+ import yaml from 'yaml';
3
5
 
4
6
  export const check = FileCheckType.CONTAINS;
7
+
8
+ export const fix: FileFixFunction = (contents, context) => {
9
+ if (!contents) return { contents: context.declaredFileContents };
10
+
11
+ const declaredContents = context.declaredFileContents ?? '';
12
+
13
+ // Parse both files as YAML (using parseDocument to preserve comments)
14
+ const currentDoc = yaml.parseDocument(contents);
15
+ const declaredParsed = yaml.parse(declaredContents) as { ignores?: string[] };
16
+
17
+ const currentIgnores =
18
+ (currentDoc.toJSON() as { ignores?: string[] })?.ignores ?? [];
19
+ const declaredIgnores = declaredParsed?.ignores ?? [];
20
+
21
+ // Find missing ignores
22
+ const missingIgnores = declaredIgnores.filter(
23
+ (item) => !currentIgnores.includes(item),
24
+ );
25
+
26
+ if (missingIgnores.length === 0) return { contents };
27
+
28
+ // Add missing ignores to the document (preserves comments)
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ let ignoresNode = currentDoc.get('ignores') as any;
31
+ if (!ignoresNode) {
32
+ currentDoc.set('ignores', []);
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ ignoresNode = currentDoc.get('ignores') as any;
35
+ }
36
+ for (const ignore of missingIgnores) {
37
+ ignoresNode.add(ignore);
38
+ }
39
+
40
+ return { contents: currentDoc.toString() };
41
+ };
@@ -1 +1 @@
1
- we switched from `provision/docker/integration_test_db` to `provision/docker/integration-test-db`
1
+ we switched from `provision/docker/integration_test_db` to `provision/docker/testdb`
@@ -1,3 +1,15 @@
1
- import { FileCheckType } from 'declapract';
1
+ import { FileCheckType, FileFixFunction } from 'declapract';
2
2
 
3
3
  export const check = FileCheckType.EXISTS; // if a file exists with this path pattern, then it's bad practice
4
+
5
+ export const fix: FileFixFunction = async (contents, { relativeFilePath }) => {
6
+ // Move from integration_test_db to testdb
7
+ const newPath = relativeFilePath.replace(
8
+ 'provision/docker/integration_test_db',
9
+ 'provision/docker/testdb',
10
+ );
11
+ return {
12
+ contents,
13
+ relativeFilePath: newPath,
14
+ };
15
+ };
@@ -0,0 +1 @@
1
+ we switched from `provision/docker/integration-test-db` to `provision/docker/testdb`
@@ -0,0 +1,15 @@
1
+ import { FileCheckType, FileFixFunction } from 'declapract';
2
+
3
+ export const check = FileCheckType.EXISTS; // if a file exists with this path pattern, then it's bad practice
4
+
5
+ export const fix: FileFixFunction = async (contents, { relativeFilePath }) => {
6
+ // Move from integration-test-db to testdb
7
+ const newPath = relativeFilePath.replace(
8
+ 'provision/docker/integration-test-db',
9
+ 'provision/docker/testdb',
10
+ );
11
+ return {
12
+ contents,
13
+ relativeFilePath: newPath,
14
+ };
15
+ };
@@ -0,0 +1 @@
1
+ we switched from `provision/docker/integration-test-db` to `provision/docker/testdb` - this detects old paths in package.json scripts
@@ -0,0 +1,8 @@
1
+ {
2
+ "scripts": {
3
+ "provision:testdb:docker:prepare": "@declapract{check.contains('integration-test-db')}",
4
+ "provision:testdb:docker:up": "@declapract{check.contains('integration-test-db')}",
5
+ "provision:testdb:docker:await": "@declapract{check.contains('integration-test-db')}",
6
+ "provision:testdb:docker:down": "@declapract{check.contains('integration-test-db')}"
7
+ }
8
+ }
@@ -0,0 +1,10 @@
1
+ import { FileCheckType, FileFixFunction } from 'declapract';
2
+
3
+ export const check = FileCheckType.CONTAINS;
4
+
5
+ export const fix: FileFixFunction = (contents) => {
6
+ if (!contents) return { contents }; // do nothing if no contents
7
+ // Replace integration-test-db with testdb in all paths
8
+ const fixed = contents.replace(/integration-test-db/g, 'testdb');
9
+ return { contents: fixed };
10
+ };
@@ -18,11 +18,11 @@
18
18
  "provision:schema:plan": "npx sql-schema-control plan -c provision/schema/control.yml",
19
19
  "provision:schema:apply": "npx sql-schema-control apply -c provision/schema/control.yml",
20
20
  "provision:schema:sync": "npx sql-schema-control sync -c provision/schema/control.yml",
21
- "provision:testdb:docker:clear": "docker rm -f $(docker ps -a -f 'publish=7821' -q) 2>/dev/null || true && echo 'ensured port is available 👍'",
22
- "provision:testdb: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",
23
- "provision:testdb:docker:up": "docker compose -f ./provision/docker/integration-test-db/docker-compose.yml up -d --force-recreate --build --renew-anon-volumes",
24
- "provision:testdb:docker:await": "docker compose -f ./provision/docker/integration-test-db/docker-compose.yml exec -T postgres /root/wait-for-postgres.sh",
25
- "provision:testdb:docker:down": "docker compose -f ./provision/docker/integration-test-db/docker-compose.yml down",
21
+ "provision:testdb:docker:clear": "for port in $(docker compose -f ./provision/docker/testdb/docker-compose.yml config --format json | jq -r '.services[].ports[]?.published'); do docker rm -f $(docker ps -a -f \"publish=$port\" -q) 2>/dev/null || true; done && echo 'ensured ports are available 👍'",
22
+ "provision:testdb:docker:prepare": "cp provision/schema/sql/init/.extensions.sql provision/docker/testdb/init/extensions.sql && cp provision/schema/sql/init/.schema.sql provision/docker/testdb/init/schema.sql && cp provision/schema/sql/init/.user.cicd.sql provision/docker/testdb/init/user.cicd.sql",
23
+ "provision:testdb:docker:up": "docker compose -f ./provision/docker/testdb/docker-compose.yml up -d --force-recreate --build --renew-anon-volumes",
24
+ "provision:testdb:docker:await": "docker compose -f ./provision/docker/testdb/docker-compose.yml exec -T postgres /root/wait-for-postgres.sh",
25
+ "provision:testdb:docker:down": "docker compose -f ./provision/docker/testdb/docker-compose.yml down",
26
26
  "provision:testdb": "npm run provision:testdb:docker:clear && npm run provision:testdb:docker:prepare && npm run provision:testdb:docker:up && npm run provision:testdb:docker:await && npm run provision:schema:plan && npm run provision:schema:apply && npm run provision:schema:plan",
27
27
  "start:testdb": "npm run provision:testdb",
28
28
  "start:livedb:dev": "echo 'will ping the database until assured its not asleep' && STAGE=dev .agent/repo=.this/skills/use.rds.capacity.sh"
@@ -1,4 +1,4 @@
1
- FROM postgres:10.7
1
+ FROM postgres:13.20
2
2
 
3
3
  COPY init/ /docker-entrypoint-initdb.d/
4
4
 
@@ -11,3 +11,8 @@ services:
11
11
  environment:
12
12
  POSTGRES_PASSWORD: a-secure-password # default user is `postgres`
13
13
  POSTGRES_DB: @declapract{variable.databaseName} # creates the database for us automatically
14
+ healthcheck:
15
+ test: ['CMD-SHELL', 'pg_isready -U postgres -d homeservicesdb']
16
+ interval: 5s
17
+ timeout: 5s
18
+ retries: 5
@@ -13,7 +13,7 @@
13
13
  ##
14
14
  ## usage example:
15
15
  ## ```sh
16
- ## ./provision/schema/deploy.database.sh dev $(op get item @declapract{variable.organizationName}db.dev.postgres | jq -r .details.password)
16
+ ## ./provision/schema/deploy.database.sh dev $(op item get ahbodedb.dev.postgres --fields label=password --format json | jq -r .value)
17
17
  ## ```
18
18
  #####################################################
19
19
 
@@ -2,7 +2,7 @@ import { HelpfulError, UnexpectedCodePathError } from 'helpful-errors';
2
2
  import pg, { Client, QueryResult, QueryResultRow } from 'pg';
3
3
 
4
4
  import { getConfig } from '../config/getConfig';
5
- import { environment } from '../environment';
5
+ import { getEnvironment } from '../environment';
6
6
 
7
7
  // https://github.com/brianc/node-postgres/pull/353#issuecomment-283709264
8
8
  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
@@ -40,6 +40,7 @@ values:
40
40
  }
41
41
 
42
42
  export const getDatabaseConnection = async (): Promise<DatabaseConnection> => {
43
+ const environment = await getEnvironment();
43
44
  const config = await getConfig();
44
45
  const target = config.database.target;
45
46
  const role = config.database.role.crud;
@@ -7,7 +7,8 @@
7
7
  # What it does:
8
8
  # 1. Creates an alias 'npm.slow' pointing to the original npm binary
9
9
  # 2. Creates an alias 'npm' that redirects to pnpm
10
- # 3. Persists aliases to ~/.bash_aliases (sourced by ~/.bashrc)
10
+ # 3. Sets up pnpm tab completion (works for both pnpm and npm alias)
11
+ # 4. Everything goes in ~/.bash_aliases (works in both bash and zsh)
11
12
  #
12
13
  # When to use:
13
14
  # - After setting up a new development environment
@@ -19,15 +20,15 @@
19
20
  set -euo pipefail
20
21
 
21
22
  BASH_ALIASES="${HOME}/.bash_aliases"
22
-
23
- # ensure ~/.bash_aliases exists
24
23
  touch "$BASH_ALIASES"
25
24
 
26
25
  # findsert npm.slow (only add if not already defined)
27
26
  if ! grep -q "^alias npm.slow=" "$BASH_ALIASES" 2>/dev/null; then
28
27
  NPM_PATH=$(which npm)
29
28
  echo "alias npm.slow=\"$NPM_PATH\"" >> "$BASH_ALIASES"
30
- echo "Added: alias npm.slow=\"$NPM_PATH\""
29
+ echo "👍 findsert: alias npm.slow=\"$NPM_PATH\""
30
+ else
31
+ echo "👍 findsert: npm.slow alias already exists"
31
32
  fi
32
33
 
33
34
  # upsert npm => pnpm
@@ -36,7 +37,7 @@ if grep -q "^alias npm=" "$BASH_ALIASES" 2>/dev/null; then
36
37
  else
37
38
  echo 'alias npm="pnpm"' >> "$BASH_ALIASES"
38
39
  fi
39
- echo "Added: alias npm=\"pnpm\""
40
+ echo "👍 upsert: alias npm=\"pnpm\""
40
41
 
41
42
  # report
42
43
  echo ""
@@ -1 +1,2 @@
1
1
  *.md
2
+ .yalc/
@@ -4,6 +4,7 @@ module.exports = {
4
4
  trailingComma: 'all',
5
5
  tabWidth: 2,
6
6
  singleQuote: true,
7
+ plugins: ['@trivago/prettier-plugin-sort-imports'],
7
8
  importOrder: ['^[./]'],
8
9
  importOrderSeparation: true,
9
10
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "devDependencies": {
3
- "declastruct": "@declapract{check.minVersion('1.3.0')}",
3
+ "declastruct": "@declapract{check.minVersion('1.4.0')}",
4
4
  "declastruct-github": "@declapract{check.minVersion('1.0.3')}"
5
5
  }
6
6
  }
@@ -0,0 +1,7 @@
1
+ These test dependencies are deprecated and should be removed:
2
+
3
+ - babel-jest: use @swc/jest instead (faster)
4
+ - @babel/core: no longer needed with @swc/jest
5
+ - @babel/preset-env: no longer needed with @swc/jest
6
+ - core-js: no longer needed with modern node
7
+ - ts-jest: use @swc/jest instead (faster)
@@ -0,0 +1,9 @@
1
+ {
2
+ "devDependencies": {
3
+ "babel-jest": "@declapract{check.minVersion('0.0.0')}",
4
+ "@babel/core": "@declapract{check.minVersion('0.0.0')}",
5
+ "@babel/preset-env": "@declapract{check.minVersion('0.0.0')}",
6
+ "core-js": "@declapract{check.minVersion('0.0.0')}",
7
+ "ts-jest": "@declapract{check.minVersion('0.0.0')}"
8
+ }
9
+ }
@@ -0,0 +1,39 @@
1
+ import { FileCheckType, FileFixFunction } from 'declapract';
2
+
3
+ export const check = FileCheckType.CONTAINS;
4
+
5
+ const deprecatedDeps = [
6
+ 'babel-jest',
7
+ '@babel/core',
8
+ '@babel/preset-env',
9
+ 'core-js',
10
+ 'ts-jest',
11
+ ];
12
+
13
+ export const fix: FileFixFunction = (contents) => {
14
+ if (!contents) return { contents }; // do nothing if no contents
15
+ const packageJSON = JSON.parse(contents);
16
+
17
+ // Remove deprecated deps from devDependencies
18
+ const updatedDevDeps = { ...packageJSON.devDependencies };
19
+ for (const dep of deprecatedDeps) {
20
+ delete updatedDevDeps[dep];
21
+ }
22
+
23
+ // Remove deprecated deps from dependencies (in case they're there)
24
+ const updatedDeps = { ...packageJSON.dependencies };
25
+ for (const dep of deprecatedDeps) {
26
+ delete updatedDeps[dep];
27
+ }
28
+
29
+ const updatedPackageJSON = {
30
+ ...packageJSON,
31
+ dependencies: Object.keys(updatedDeps).length > 0 ? updatedDeps : undefined,
32
+ devDependencies:
33
+ Object.keys(updatedDevDeps).length > 0 ? updatedDevDeps : undefined,
34
+ };
35
+
36
+ return {
37
+ contents: JSON.stringify(updatedPackageJSON, null, 2),
38
+ };
39
+ };
@@ -12,15 +12,13 @@ const config: Config = {
12
12
  testEnvironment: 'node',
13
13
  moduleFileExtensions: ['js', 'ts'],
14
14
  transform: {
15
- '^.+\\.tsx?$': 'ts-jest', // https://kulshekhar.github.io/ts-jest/docs/getting-started/presets
16
- '^.+\\.(js|jsx|mjs)$': 'babel-jest', // transform esm modules with babel
15
+ '^.+\\.(t|j)sx?$': '@swc/jest',
17
16
  },
18
17
  transformIgnorePatterns: [
19
18
  // here's an example of how to ignore esm module transformation, when needed
20
19
  // 'node_modules/(?!(@octokit|universal-user-agent|before-after-hook)/)',
21
20
  ],
22
21
  testMatch: ['**/*.acceptance.test.ts'],
23
- setupFiles: ['core-js'],
24
22
  setupFilesAfterEnv: ['./jest.acceptance.env.ts'],
25
23
 
26
24
  // use 50% of threads to leave headroom for other processes
@@ -21,7 +21,7 @@ if (!existsSync(join(process.cwd(), 'package.json')))
21
21
  * - prevent time wasted waiting on tests to fail due to lack of credentials
22
22
  * - prevent time wasted debugging tests which are failing due to hard-to-read missed credential errors
23
23
  */
24
- const declapractUsePath = join(process.cwd(), 'declapract.use.ts');
24
+ const declapractUsePath = join(process.cwd(), 'declapract.use.yml');
25
25
  const requiresAwsAuth =
26
26
  existsSync(declapractUsePath) &&
27
27
  readFileSync(declapractUsePath, 'utf8').includes('awsAccountId');
@@ -12,15 +12,13 @@ const config: Config = {
12
12
  testEnvironment: 'node',
13
13
  moduleFileExtensions: ['js', 'ts'],
14
14
  transform: {
15
- '^.+\\.tsx?$': 'ts-jest', // https://kulshekhar.github.io/ts-jest/docs/getting-started/presets
16
- '^.+\\.(js|jsx|mjs)$': 'babel-jest', // transform esm modules with babel
15
+ '^.+\\.(t|j)sx?$': '@swc/jest',
17
16
  },
18
17
  transformIgnorePatterns: [
19
18
  // here's an example of how to ignore esm module transformation, when needed
20
19
  // 'node_modules/(?!(@octokit|universal-user-agent|before-after-hook)/)',
21
20
  ],
22
21
  testMatch: ['**/*.integration.test.ts'],
23
- setupFiles: ['core-js'],
24
22
  setupFilesAfterEnv: ['./jest.integration.env.ts'],
25
23
 
26
24
  // use 50% of threads to leave headroom for other processes
@@ -23,7 +23,8 @@ if (!existsSync(join(process.cwd(), 'package.json')))
23
23
  * - prevent executing financially impacting mutations
24
24
  */
25
25
  if (
26
- (process.env.NODE_ENV !== 'test' || process.env.STAGE) &&
26
+ (process.env.NODE_ENV !== 'test' ||
27
+ (process.env.STAGE && process.env.STAGE !== 'test')) &&
27
28
  process.env.I_KNOW_WHAT_IM_DOING !== 'true'
28
29
  )
29
30
  throw new Error(`integration.test is not targeting stage 'test'`);
@@ -34,7 +35,7 @@ if (
34
35
  * - prevent time wasted waiting on tests to fail due to lack of credentials
35
36
  * - prevent time wasted debugging tests which are failing due to hard-to-read missed credential errors
36
37
  */
37
- const declapractUsePath = join(process.cwd(), 'declapract.use.ts');
38
+ const declapractUsePath = join(process.cwd(), 'declapract.use.yml');
38
39
  const requiresAwsAuth =
39
40
  existsSync(declapractUsePath) &&
40
41
  readFileSync(declapractUsePath, 'utf8').includes('awsAccountId');
@@ -12,8 +12,7 @@ const config: Config = {
12
12
  testEnvironment: 'node',
13
13
  moduleFileExtensions: ['js', 'ts'],
14
14
  transform: {
15
- '^.+\\.tsx?$': 'ts-jest', // https://kulshekhar.github.io/ts-jest/docs/getting-started/presets
16
- '^.+\\.(js|jsx|mjs)$': 'babel-jest', // transform esm modules with babel
15
+ '^.+\\.(t|j)sx?$': '@swc/jest',
17
16
  },
18
17
  transformIgnorePatterns: [
19
18
  // here's an example of how to ignore esm module transformation, when needed
@@ -25,7 +24,6 @@ const config: Config = {
25
24
  '!**/*.acceptance.test.ts',
26
25
  '!**/*.integration.test.ts',
27
26
  ],
28
- setupFiles: ['core-js'],
29
27
  setupFilesAfterEnv: ['./jest.unit.env.ts'],
30
28
 
31
29
  // use 50% of threads to leave headroom for other processes
@@ -3,12 +3,9 @@
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.4.5')}",
7
6
  "tsx": "@declapract{check.minVersion('4.20.6')}",
8
- "core-js": "@declapract{check.minVersion('3.26.1')}",
9
- "@babel/core": "@declapract{check.minVersion('7.28.5')}",
10
- "@babel/preset-env": "@declapract{check.minVersion('7.28.5')}",
11
- "babel-jest": "@declapract{check.minVersion('30.2.0')}"
7
+ "@swc/core": "@declapract{check.minVersion('1.15.3')}",
8
+ "@swc/jest": "@declapract{check.minVersion('0.2.39')}"
12
9
  },
13
10
  "scripts": {
14
11
  "test:unit": "jest -c ./jest.unit.config.ts --forceExit --verbose --passWithNoTests $([ -z $THOROUGH ] && echo '--changedSince=main')",
@@ -7,6 +7,6 @@
7
7
  "build:clean": "rm dist/ -rf",
8
8
  "build:compile": "tsc -p ./tsconfig.build.json",
9
9
  "build": "npm run build:clean && npm run build:compile && npm run build:artifact",
10
- "test:types": "tsc -p ./tsconfig.build.json --noEmit"
10
+ "test:types": "tsc -p ./tsconfig.json --noEmit"
11
11
  }
12
12
  }
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "extends": "./tsconfig.json",
3
3
  "compilerOptions": {
4
- "rootDir": "src"
4
+ "rootDir": "src",
5
+ "incremental": false
5
6
  },
6
7
  "include": [
7
8
  "src/**/*.ts",
@@ -11,6 +11,7 @@
11
11
  "sourceMap": true,
12
12
  "outDir": "dist",
13
13
  "target": "es2020",
14
+ "incremental": true
14
15
  },
15
16
  "include": [
16
17
  "**/*.ts"
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.42.3",
5
+ "version": "0.42.5",
6
6
  "license": "MIT",
7
7
  "main": "src/index.js",
8
8
  "repository": "ehmpathy/declapract-typescript-ehmpathy",
@@ -46,7 +46,8 @@
46
46
  "expect": "29.4.2",
47
47
  "flat": "5.0.2",
48
48
  "helpful-errors": "1.5.3",
49
- "simple-log-methods": "0.5.0"
49
+ "simple-log-methods": "0.5.0",
50
+ "yaml": "1.10.2"
50
51
  },
51
52
  "peerDependencies": {
52
53
  "declapract": ">=0.12.1"