@ackee/create-node-app 1.0.1 → 2.0.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 (149) hide show
  1. package/AUTHORS +2 -1
  2. package/README.md +26 -18
  3. package/docs/development.md +42 -0
  4. package/lib/Bootstrap.js +106 -65
  5. package/lib/Bootstrap.js.map +1 -1
  6. package/lib/Builder.js +111 -0
  7. package/lib/Builder.js.map +1 -0
  8. package/lib/Files.js +21 -0
  9. package/lib/Files.js.map +1 -0
  10. package/lib/Logger.js +26 -8
  11. package/lib/Logger.js.map +1 -1
  12. package/lib/Mergers/ConfigMerger.js +22 -0
  13. package/lib/Mergers/ConfigMerger.js.map +1 -0
  14. package/lib/Mergers/ContainerMerger.js +172 -0
  15. package/lib/Mergers/ContainerMerger.js.map +1 -0
  16. package/lib/Mergers/EnvJsoncMerger.js +20 -0
  17. package/lib/Mergers/EnvJsoncMerger.js.map +1 -0
  18. package/lib/Mergers/Merger.js +36 -0
  19. package/lib/Mergers/Merger.js.map +1 -0
  20. package/lib/Mergers/PackageJsonMerger.js +36 -0
  21. package/lib/Mergers/PackageJsonMerger.js.map +1 -0
  22. package/lib/Npm.js +40 -12
  23. package/lib/Npm.js.map +1 -1
  24. package/lib/PackageJson.js +4 -4
  25. package/lib/PackageJson.js.map +1 -1
  26. package/lib/StarterLoader.js +86 -0
  27. package/lib/StarterLoader.js.map +1 -0
  28. package/package.json +8 -5
  29. package/src/Bootstrap.ts +123 -82
  30. package/src/Builder.ts +172 -0
  31. package/src/Files.ts +22 -0
  32. package/src/Logger.ts +26 -7
  33. package/src/Mergers/ConfigMerger.ts +28 -0
  34. package/src/Mergers/ContainerMerger.ts +241 -0
  35. package/src/Mergers/EnvJsoncMerger.ts +24 -0
  36. package/src/Mergers/Merger.ts +51 -0
  37. package/src/Mergers/PackageJsonMerger.ts +45 -0
  38. package/src/Npm.ts +60 -15
  39. package/src/PackageJson.ts +6 -4
  40. package/src/Starter.ts +2 -2
  41. package/src/StarterLoader.ts +148 -0
  42. package/starter/{cloudrun → _base}/.env.jsonc +1 -5
  43. package/starter/{cloudrun → _base}/.eslintrc.cjs +3 -2
  44. package/starter/_base/README.md +53 -0
  45. package/starter/_base/package.json +45 -0
  46. package/starter/{cloudrun → _base}/src/adapters/pino.logger.ts +1 -1
  47. package/starter/_base/src/config.ts +16 -0
  48. package/starter/{cloudrun-graphql → _base}/src/container.ts +3 -1
  49. package/starter/_base/src/index.ts +14 -0
  50. package/starter/{cloudrun → _base}/src/view/cli/README.md +2 -6
  51. package/starter/api/graphql/.env.jsonc +8 -0
  52. package/starter/{cloudrun-graphql → api/graphql}/.eslintrc.cjs +4 -5
  53. package/starter/api/graphql/node-app.jsonc +6 -0
  54. package/starter/api/graphql/package.json +36 -0
  55. package/starter/{cloudrun-graphql → api/graphql}/src/config.ts +0 -4
  56. package/starter/api/graphql/src/index.ts +11 -0
  57. package/starter/{cloudrun-graphql → api/graphql}/src/test/helloWorld.test.ts +14 -3
  58. package/starter/api/graphql/src/view/graphql/context-factory.ts +13 -0
  59. package/starter/{cloudrun-graphql → api/graphql}/src/view/server.ts +16 -6
  60. package/starter/api/rest/.env.jsonc +6 -0
  61. package/starter/api/rest/.eslintrc.cjs +8 -0
  62. package/starter/api/rest/node-app.jsonc +6 -0
  63. package/starter/api/rest/package.json +25 -0
  64. package/starter/{cloudrun → api/rest}/src/config.ts +0 -5
  65. package/starter/api/rest/src/container.ts +13 -0
  66. package/starter/{cloudrun → api/rest}/src/index.ts +4 -4
  67. package/starter/{cloudrun → api/rest}/src/test/health-check.test.ts +3 -5
  68. package/starter/{cloudrun → api/rest}/src/test/util/openapi-test.util.ts +3 -3
  69. package/starter/{cloudrun → api/rest}/src/view/rest/middleware/error-handler.ts +1 -1
  70. package/starter/{cloudrun → api/rest}/src/view/rest/routes.ts +1 -1
  71. package/starter/{cloudrun → api/rest}/src/view/rest/util/openapi.util.ts +19 -19
  72. package/starter/{cloudrun → api/rest}/src/view/server.ts +6 -4
  73. package/starter/infra/postgresql-knex/.env.jsonc +5 -0
  74. package/starter/{shared → infra/postgresql-knex}/docker-compose/docker-compose.yml +1 -1
  75. package/starter/infra/postgresql-knex/knexfile.ts +16 -0
  76. package/starter/infra/postgresql-knex/node-app.jsonc +6 -0
  77. package/starter/infra/postgresql-knex/package.json +13 -0
  78. package/starter/infra/postgresql-knex/src/adapters/knex.database.test.ts +21 -0
  79. package/starter/infra/postgresql-knex/src/adapters/knex.database.ts +14 -0
  80. package/starter/infra/postgresql-knex/src/adapters/repositories/migration.repository.ts +24 -0
  81. package/starter/infra/postgresql-knex/src/config.ts +14 -0
  82. package/starter/infra/postgresql-knex/src/container.ts +23 -0
  83. package/starter/infra/postgresql-knex/src/db/migration.template.ts +4 -0
  84. package/starter/infra/postgresql-knex/src/db/migrations/.gitkeep +0 -0
  85. package/starter/infra/postgresql-knex/src/db/seed.template.ts +3 -0
  86. package/starter/infra/postgresql-knex/src/db/seeds/.gitkeep +0 -0
  87. package/starter/infra/postgresql-knex/src/domain/ports/database.d.ts +4 -0
  88. package/starter/infra/postgresql-knex/src/domain/ports/repositories/migration.repository.d.ts +9 -0
  89. package/starter/infra/postgresql-knex/src/test/setup.ts +16 -0
  90. package/starter/{shared → pipeline/cloudrun-gitlab}/.gitlab-ci.yml +15 -6
  91. package/starter/pipeline/cloudrun-gitlab/node-app.jsonc +6 -0
  92. package/tsconfig.tsbuildinfo +1 -1
  93. package/lib/Toolbelt.js +0 -102
  94. package/lib/Toolbelt.js.map +0 -1
  95. package/lib/cloudrun/CloudRunStarter.js +0 -127
  96. package/lib/cloudrun/CloudRunStarter.js.map +0 -1
  97. package/lib/cloudrun-graphql/GraphQLStarter.js +0 -118
  98. package/lib/cloudrun-graphql/GraphQLStarter.js.map +0 -1
  99. package/src/Toolbelt.ts +0 -132
  100. package/src/cloudrun/CloudRunStarter.ts +0 -182
  101. package/src/cloudrun-graphql/GraphQLStarter.ts +0 -182
  102. package/starter/cloudrun/README.md +0 -69
  103. package/starter/cloudrun/src/container.ts +0 -18
  104. package/starter/cloudrun/src/context.ts +0 -39
  105. package/starter/cloudrun/src/domain/errors/codes.ts +0 -9
  106. package/starter/cloudrun/src/domain/errors/errors.ts +0 -25
  107. package/starter/cloudrun/src/domain/ports/logger.d.ts +0 -21
  108. package/starter/cloudrun-graphql/.env.jsonc +0 -12
  109. package/starter/cloudrun-graphql/README.md +0 -53
  110. package/starter/cloudrun-graphql/src/adapters/pino.logger.ts +0 -44
  111. package/starter/cloudrun-graphql/src/index.ts +0 -11
  112. package/starter/shared/.gitignore_ +0 -5
  113. package/starter/shared/ci-branch-config/common.env +0 -7
  114. package/starter/shared/ci-branch-config/development.env +0 -7
  115. package/starter/shared/ci-branch-config/master.env +0 -7
  116. package/starter/shared/ci-branch-config/stage.env +0 -7
  117. package/starter/shared/docker-compose/docker-compose.override.yml +0 -5
  118. package/starter/shared/jest.config.js +0 -12
  119. /package/starter/{shared → _base}/.dockerignore +0 -0
  120. /package/starter/{cloudrun → _base}/.eslint.tsconfig.json +0 -0
  121. /package/starter/{shared → _base}/.mocha-junit-config.json +0 -0
  122. /package/starter/{shared → _base}/.mocharc.json +0 -0
  123. /package/starter/{shared → _base}/.nvmrc +0 -0
  124. /package/starter/{shared → _base}/Dockerfile +0 -0
  125. /package/starter/{shared → _base}/prettier.config.cjs +0 -0
  126. /package/starter/{cloudrun-graphql → _base}/src/context.ts +0 -0
  127. /package/starter/{cloudrun-graphql → _base}/src/domain/errors/codes.ts +0 -0
  128. /package/starter/{cloudrun-graphql → _base}/src/domain/errors/errors.ts +0 -0
  129. /package/starter/{cloudrun-graphql → _base}/src/domain/ports/logger.d.ts +0 -0
  130. /package/starter/{shared → _base}/src/test/setup.ts +0 -0
  131. /package/starter/{cloudrun → _base}/src/view/cli/cli.ts +0 -0
  132. /package/starter/{shared → _base}/tsconfig.json +0 -0
  133. /package/starter/{cloudrun-graphql → api/graphql}/.eslint.tsconfig.json +0 -0
  134. /package/starter/{cloudrun-graphql → api/graphql}/codegen.yml +0 -0
  135. /package/starter/{cloudrun-graphql → api/graphql}/src/view/controller.ts +0 -0
  136. /package/starter/{cloudrun-graphql → api/graphql}/src/view/graphql/resolvers/greeting.resolver.ts +0 -0
  137. /package/starter/{cloudrun-graphql → api/graphql}/src/view/graphql/resolvers.ts +0 -0
  138. /package/starter/{cloudrun-graphql → api/graphql}/src/view/graphql/schema/schema.graphql +0 -0
  139. /package/starter/{cloudrun-graphql → api/graphql}/src/view/graphql/schema.ts +0 -0
  140. /package/starter/{cloudrun → api/rest}/src/domain/health-check.service.ts +0 -0
  141. /package/starter/{cloudrun → api/rest}/src/view/cli/openapi/generate.ts +0 -0
  142. /package/starter/{cloudrun/src/view/rest/controller → api/rest/src/view/rest/controllers}/health-check.controller.ts +0 -0
  143. /package/starter/{cloudrun → api/rest}/src/view/rest/middleware/context-middleware.ts +0 -0
  144. /package/starter/{cloudrun → api/rest}/src/view/rest/middleware/request-logger.ts +0 -0
  145. /package/starter/{cloudrun → api/rest}/src/view/rest/request.d.ts +0 -0
  146. /package/starter/{cloudrun → api/rest}/src/view/rest/spec/openapi.yml +0 -0
  147. /package/starter/{shared → infra/postgresql-knex}/docker-compose/docker-compose-entrypoint.sh +0 -0
  148. /package/starter/{shared → infra/postgresql-knex}/docker-compose/docker-compose.ci.yml +0 -0
  149. /package/starter/{shared → infra/postgresql-knex}/docker-compose/docker-compose.local.yml +0 -0
@@ -1,182 +0,0 @@
1
- import { Starter } from '../Starter.js'
2
- import { Toolbelt } from '../Toolbelt.js'
3
-
4
- export class CloudRunStarter implements Starter {
5
- public readonly name = 'cloudrun'
6
- protected toolbelt?: Toolbelt
7
-
8
- public setToolbelt(toolbelt: Toolbelt): Starter {
9
- this.toolbelt = toolbelt
10
- return this
11
- }
12
-
13
- public install(): void {
14
- if (this.toolbelt == null) {
15
- throw new Error('No toolbelt')
16
- }
17
- const tb = this.toolbelt
18
- tb.copySharedAsset('.gitignore')
19
- tb.copySharedAsset('.gitlab-ci.yml')
20
- tb.copySharedAsset('.nvmrc')
21
- tb.copySharedAsset('Dockerfile')
22
- tb.copySharedAsset('.dockerignore')
23
-
24
- tb.mkdir(tb.stringToPath(`${tb.destination}/ci-branch-config`))
25
- tb.copySharedAsset('ci-branch-config/common.env')
26
- tb.replaceInFile(
27
- `ci-branch-config/common.env`,
28
- '{{PROJECT_NAME}}',
29
- tb.projectName
30
- )
31
- tb.copySharedAsset('ci-branch-config/development.env')
32
- tb.replaceInFile(
33
- `ci-branch-config/development.env`,
34
- '{{PROJECT_NAME}}',
35
- tb.projectName
36
- )
37
- tb.copySharedAsset('ci-branch-config/stage.env')
38
- tb.replaceInFile(
39
- `ci-branch-config/stage.env`,
40
- '{{PROJECT_NAME}}',
41
- tb.projectName
42
- )
43
- tb.copySharedAsset('ci-branch-config/master.env')
44
- tb.replaceInFile(
45
- `ci-branch-config/master.env`,
46
- '{{PROJECT_NAME}}',
47
- tb.projectName
48
- )
49
- tb.mkdir(tb.stringToPath(`${tb.destination}/docker-compose`))
50
- tb.copySharedAsset('docker-compose/docker-compose-entrypoint.sh')
51
- tb.copySharedAsset('docker-compose/docker-compose.ci.yml')
52
- tb.copySharedAsset('docker-compose/docker-compose.local.yml')
53
- tb.symlink(
54
- `${tb.destination}/docker-compose/docker-compose.override.yml`,
55
- `${tb.destination}/docker-compose/docker-compose.local.yml`
56
- )
57
- tb.copySharedAsset('docker-compose/docker-compose.yml')
58
- tb.replaceInFile(
59
- `docker-compose/docker-compose.yml`,
60
- '{{PROJECT_NAME}}',
61
- tb.projectName
62
- )
63
-
64
- tb.npm.iDev('typescript')
65
- tb.npm.iDev('@types/node')
66
- tb.npm.iDev('ts-node')
67
- tb.npm.i('source-map-support')
68
- tb.copySharedAsset('tsconfig.json')
69
- tb.packageJson.setType('module')
70
- tb.packageJson.addNpmScript('build', 'tsc')
71
- tb.packageJson.addNpmScript(
72
- 'start',
73
- 'node -r source-map-support/register dist/index.js'
74
- )
75
-
76
- tb.npm.i('configuru')
77
- tb.npm.i('pino')
78
- tb.npm.i('pino-http')
79
- tb.npm.iDev('pino-pretty')
80
- tb.copyAsset('.env.jsonc')
81
- tb.mkdir(tb.stringToPath(`${tb.destination}/src`))
82
- tb.copyAsset('src/config.ts')
83
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/adapters`))
84
- tb.copyAsset('src/container.ts')
85
- tb.copyAsset('src/context.ts')
86
- tb.copyAsset('src/index.ts')
87
-
88
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view`))
89
- tb.copyAsset(`/src/view/server.ts`)
90
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/rest`))
91
- tb.copyAsset(`/src/view/rest/request.d.ts`)
92
- tb.copyAsset(`/src/view/rest/routes.ts`)
93
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/rest/controller`))
94
- tb.copyAsset(`/src/view/rest/controller/health-check.controller.ts`)
95
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/rest/middleware`))
96
- tb.copyAsset(`/src/view/rest/middleware/context-middleware.ts`)
97
- tb.copyAsset(`/src/view/rest/middleware/error-handler.ts`)
98
- tb.copyAsset(`/src/view/rest/middleware/request-logger.ts`)
99
-
100
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/rest/util`))
101
- tb.copyAsset(`/src/view/rest/util/openapi.util.ts`)
102
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/rest/spec`))
103
- tb.copyAsset(`/src/view/rest/spec/openapi.yml`)
104
- tb.npm.i('node-healthz')
105
-
106
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/domain`))
107
- tb.copyAsset('src/domain/health-check.service.ts')
108
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/domain/errors`))
109
- tb.copyAsset('src/domain/errors/errors.ts')
110
- tb.copyAsset('src/domain/errors/codes.ts')
111
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/domain/util`))
112
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/domain/ports`))
113
- tb.copyAsset('src/domain/ports/logger.d.ts')
114
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/adapters`))
115
- tb.copyAsset('src/adapters/pino.logger.ts')
116
-
117
- tb.npm.i('express')
118
- tb.npm.iDev('@types/express')
119
-
120
- tb.npm.iDev('mocha')
121
- tb.npm.iDev('mocha-junit-reporter')
122
- tb.npm.iDev('mocha-multi-reporters')
123
- tb.npm.iDev('nyc')
124
- tb.npm.iDev('@types/mocha')
125
- tb.npm.iDev('@istanbuljs/nyc-config-typescript')
126
- tb.npm.iDev('supertest')
127
- tb.npm.iDev('@types/supertest')
128
- tb.copySharedAsset('.mocharc.json', tb.destination)
129
- tb.copySharedAsset('.mocha-junit-config.json', tb.destination)
130
- tb.packageJson.addNpmScript('test', 'mocha')
131
- tb.packageJson.addNpmScript(
132
- 'ci-test:no-coverage',
133
- 'npm run test -- --parallel=false -R mocha-multi-reporters --reporter-options configFile=.mocha-junit-config.json'
134
- )
135
- tb.packageJson.addNpmScript(
136
- 'ci-test',
137
- 'nyc -a -r cobertura --report-dir output npm run ci-test:no-coverage'
138
- )
139
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/test`))
140
- tb.copySharedAsset('src/test/setup.ts')
141
- tb.copyAsset('src/test/health-check.test.ts')
142
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/test/util`))
143
- tb.copyAsset('src/test/util/openapi-test.util.ts')
144
-
145
- tb.npm.iDev('@ackee/styleguide-backend-config')
146
- tb.npm.iDev('prettier')
147
- tb.npm.iDev('eslint')
148
- tb.npm.iDev('eslint-formatter-gitlab@^5.0.0')
149
- tb.copyAsset('.eslint.tsconfig.json')
150
- tb.copyAsset('.eslintrc.cjs')
151
- tb.copySharedAsset('prettier.config.cjs')
152
- tb.packageJson.addNpmScript(
153
- 'prettier',
154
- "prettier --check --write '**/*.{ts,js,json,md}'"
155
- )
156
- tb.packageJson.addNpmScript('lint', "eslint '**/*.ts' -f codeframe --fix")
157
- tb.packageJson.addNpmScript('codestyle', 'npm run prettier && npm run lint')
158
- tb.packageJson.addNpmScript(
159
- 'ci-lint',
160
- 'npm run lint -- -f checkstyle -o ./output/checkstyle-result.xml'
161
- )
162
-
163
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/cli`))
164
- tb.copyAsset('src/view/cli/cli.ts')
165
- tb.copyAsset('src/view/cli/README.md')
166
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/cli/openapi`))
167
- tb.copyAsset('src/view/cli/openapi/generate.ts')
168
- tb.npm.iDev('yargs')
169
- tb.npm.iDev('@types/yargs')
170
- tb.npm.iDev('yaml')
171
- tb.packageJson.addNpmScript('cli', 'tsx ./src/view/cli/cli.ts')
172
- tb.npm.iDev('openapi-typescript')
173
- tb.npm.iDev('tsx')
174
- tb.packageJson.addNpmScript(
175
- 'generate:api',
176
- 'npm run cli openapi generate src/view/rest/spec/openapi.yml && npm run codestyle'
177
- )
178
-
179
- tb.packageJson.runScript('generate:api')
180
- tb.packageJson.runScript('build')
181
- }
182
- }
@@ -1,182 +0,0 @@
1
- import { Starter } from '../Starter.js'
2
- import { Toolbelt } from '../Toolbelt.js'
3
-
4
- export class GraphQLStarter implements Starter {
5
- public readonly name = 'cloudrun-graphql'
6
- protected toolbelt?: Toolbelt
7
-
8
- public setToolbelt(toolbelt: Toolbelt): Starter {
9
- this.toolbelt = toolbelt
10
- return this
11
- }
12
-
13
- public install(): void {
14
- if (this.toolbelt == null) {
15
- throw new Error('No toolbelt')
16
- }
17
- const tb = this.toolbelt
18
- tb.copySharedAsset('.gitignore')
19
- tb.copySharedAsset('.gitlab-ci.yml')
20
- tb.copySharedAsset('.nvmrc')
21
- tb.copySharedAsset('Dockerfile')
22
- tb.copySharedAsset('.dockerignore')
23
-
24
- tb.mkdir(tb.stringToPath(`${tb.destination}/ci-branch-config`))
25
- tb.copySharedAsset('ci-branch-config/common.env')
26
- tb.replaceInFile(
27
- `ci-branch-config/common.env`,
28
- '{{PROJECT_NAME}}',
29
- tb.projectName
30
- )
31
- tb.copySharedAsset('ci-branch-config/development.env')
32
- tb.replaceInFile(
33
- `ci-branch-config/development.env`,
34
- '{{PROJECT_NAME}}',
35
- tb.projectName
36
- )
37
- tb.copySharedAsset('ci-branch-config/stage.env')
38
- tb.replaceInFile(
39
- `ci-branch-config/stage.env`,
40
- '{{PROJECT_NAME}}',
41
- tb.projectName
42
- )
43
- tb.copySharedAsset('ci-branch-config/master.env')
44
- tb.replaceInFile(
45
- `ci-branch-config/master.env`,
46
- '{{PROJECT_NAME}}',
47
- tb.projectName
48
- )
49
-
50
- tb.mkdir(tb.stringToPath(`${tb.destination}/docker-compose`))
51
- tb.copySharedAsset('docker-compose/docker-compose-entrypoint.sh')
52
- tb.copySharedAsset('docker-compose/docker-compose.ci.yml')
53
- tb.copySharedAsset('docker-compose/docker-compose.local.yml')
54
- tb.copySharedAsset('docker-compose/docker-compose.override.yml')
55
- tb.symlink(
56
- `${tb.destination}/docker-compose/docker-compose.override.yml`,
57
- `${tb.destination}/docker-compose/docker-compose.local.yml`
58
- )
59
- tb.copySharedAsset('docker-compose/docker-compose.yml')
60
- tb.replaceInFile(
61
- `docker-compose/docker-compose.yml`,
62
- '{{PROJECT_NAME}}',
63
- tb.projectName
64
- )
65
-
66
- tb.npm.iDev('typescript')
67
- tb.npm.iDev('@types/node')
68
- tb.npm.iDev('ts-node')
69
- tb.npm.i('source-map-support')
70
- tb.copySharedAsset('tsconfig.json')
71
- tb.packageJson.addNpmScript(
72
- 'build:graphql-types',
73
- 'graphql-codegen --config codegen.yml'
74
- )
75
- tb.packageJson.addNpmScript(
76
- 'build:copy-schema',
77
- 'mkdir -p ./dist/view/graphql/schema && cp -r ./src/view/graphql/schema ./dist/view/graphql/schema'
78
- )
79
- tb.packageJson.addNpmScript(
80
- 'build',
81
- 'npm run build:graphql-types && npm run build:copy-schema && tsc'
82
- )
83
- tb.packageJson.addNpmScript(
84
- 'start',
85
- 'node -r source-map-support/register dist/index.js'
86
- )
87
-
88
- tb.npm.i('configuru')
89
- tb.npm.i('pino')
90
- tb.npm.iDev('pino-pretty')
91
- tb.copyAsset('.env.jsonc')
92
- tb.mkdir(tb.stringToPath(`${tb.destination}/src`))
93
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view`))
94
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/domain`))
95
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/domain/errors`))
96
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/domain/ports`))
97
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/domain/utils`))
98
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/adapters`))
99
- tb.copyAsset('src/domain/errors/codes.ts')
100
- tb.copyAsset('src/domain/errors/errors.ts')
101
- tb.copyAsset('src/domain/errors/errors.ts')
102
- tb.copyAsset('src/domain/ports/logger.d.ts')
103
- tb.copyAsset('src/adapters/pino.logger.ts')
104
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/graphql`))
105
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/graphql/resolvers`))
106
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/view/graphql/schema`))
107
- tb.copyAsset('src/config.ts')
108
- tb.copyAsset('src/index.ts')
109
- tb.copyAsset('src/container.ts')
110
- tb.copyAsset('src/context.ts')
111
- tb.copyAsset('codegen.yml')
112
-
113
- tb.copyAsset('src/view/controller.ts')
114
- tb.copyAsset('src/view/server.ts')
115
- tb.copyAsset('src/view/graphql/schema.ts')
116
- tb.copyAsset('src/view/graphql/resolvers.ts')
117
- tb.copyAsset('src/view/graphql/resolvers/greeting.resolver.ts')
118
- tb.copyAsset('src/view/graphql/schema/schema.graphql')
119
-
120
- tb.npm.iDev('mocha')
121
- tb.npm.iDev('mocha-junit-reporter')
122
- tb.npm.iDev('mocha-multi-reporters')
123
- tb.npm.iDev('nyc')
124
- tb.npm.iDev('tsx')
125
- tb.npm.iDev('@types/mocha')
126
- tb.npm.iDev('@istanbuljs/nyc-config-typescript')
127
- tb.copySharedAsset('.mocharc.json', tb.destination)
128
- tb.copySharedAsset('.mocha-junit-config.json', tb.destination)
129
- tb.packageJson.setType('module')
130
- tb.packageJson.addNpmScript('test', 'mocha')
131
-
132
- tb.packageJson.addNpmScript(
133
- 'ci-test:no-coverage',
134
- 'npm run test -- --parallel=false -R mocha-multi-reporters --reporter-options configFile=.mocha-junit-config.json'
135
- )
136
- tb.packageJson.addNpmScript(
137
- 'ci-test',
138
- 'nyc -a -r cobertura --report-dir output npm run ci-test:no-coverage'
139
- )
140
- tb.mkdir(tb.stringToPath(`${tb.destination}/src/test`))
141
- tb.copySharedAsset('src/test/setup.ts')
142
- tb.copyAsset('src/test/helloWorld.test.ts')
143
-
144
- tb.npm.i('@as-integrations/express5')
145
- tb.npm.iDev('@ackee/styleguide-backend-config')
146
- tb.npm.iDev('prettier')
147
- tb.npm.iDev('eslint')
148
- tb.npm.iDev('eslint-formatter-gitlab@^5.0.0')
149
- tb.copyAsset('.eslint.tsconfig.json')
150
- tb.copyAsset('.eslintrc.cjs')
151
- tb.copySharedAsset('prettier.config.cjs')
152
-
153
- tb.packageJson.addNpmScript(
154
- 'prettier',
155
- "prettier --check --write '**/*.{ts,js,json,md}'"
156
- )
157
- tb.packageJson.addNpmScript(
158
- 'lint',
159
- 'eslint --ext .ts --ext .graphql src -f codeframe --fix'
160
- )
161
- tb.packageJson.addNpmScript('codestyle', 'npm run prettier && npm run lint')
162
- tb.packageJson.addNpmScript(
163
- 'ci-lint',
164
- 'npm run lint -- -f checkstyle -o ./output/checkstyle-result.xml'
165
- )
166
-
167
- tb.npm.i('@apollo/server')
168
- tb.npm.iDev('@graphql-codegen/cli')
169
- tb.npm.iDev('lodash')
170
- tb.npm.iDev('@graphql-eslint/eslint-plugin')
171
- tb.npm.iDev('@graphql-codegen/typescript')
172
- tb.npm.iDev('@graphql-codegen/typescript-resolvers')
173
- tb.npm.i('@graphql-tools/load-files')
174
- tb.npm.i('@graphql-tools/merge')
175
- tb.npm.i('@graphql-tools/schema')
176
- tb.npm.i('graphql')
177
- tb.npm.i('express')
178
- tb.npm.iDev('@types/express')
179
-
180
- tb.packageJson.runScript('build')
181
- }
182
- }
@@ -1,69 +0,0 @@
1
- # Cloudrun Starter
2
-
3
- Node.js project scaffolded with create-node-app Cloudrun
4
-
5
- ## 🎉 Initialize new project
6
-
7
- Run `create-node-app cloudrun` to init your project. By default project is created in `../node-app` folder.
8
-
9
- You can pass `destination` argument into the command as well.
10
- Example:
11
-
12
- - `create-node-app cloudrun /Users/foo/Documents/bar`
13
-
14
- ## 🧑‍💻 Development
15
-
16
- Project follows port-adapters folder structure. Three main layers can be found in [src folder](src):
17
-
18
- - [domain](src/domain) containing all domain services and ports for external services,
19
- - [adapters](src/adapters) containing implementations of ports,
20
- - and [view](src/view) containing entrypoints to the application (rest, cli).
21
-
22
- The main entrypoint of the application is defined in the [src/index.ts](index.ts) file. The applicaiton dependencies are defined
23
- and maintained in the [container.ts](src/container.ts) file which loads configuration from [config.ts](src/config.ts) using [configuru library](https://github.com/AckeeCZ/configuru).
24
-
25
- Tests are divided in the two parts:
26
-
27
- - integration tests should be maintained in the [test folder](src/test/)
28
- - unit tests should be kept close to the targeted file and hold the same name as the tested file but with `test.ts` suffix
29
-
30
- ## 👷 Continuous Integration
31
-
32
- ### Environment variables
33
-
34
- If you didn't provided GCloud project parameter, make sure you replace all the variable values containing `node-app` in `ci-branch-config` files.
35
-
36
- The following variables must be set for each branch in `ci-branch-config` directory.
37
-
38
- - `GCP_PROJECT_ID` - GCP project identifier
39
- - `ENVIRONMENT` - e.g. `development`
40
-
41
- Optional variables:
42
-
43
- - `ALLOCATED_MEMORY` - Memory allocated at Cloudrun, default is 384Mi
44
- - `CLOUD_RUN_SERVICE_ACCOUNT` - CloudRun service account
45
- - `ENV_SECRETS` - Secret variables of the deployment, format is: `KEY=[NAME OF SECRET IN SECRET MANAGER:VERSION],...`
46
- - `ENV_VARS` - Environment variables of the deployment, format is: `KEY=VALUE,...`
47
- - `GCP_SA_KEY` - We use different service accounts for different environments. So we have to overwrite `GCP_SA_KEY` variable e.g.`GCP_SA_KEY=$SECRET_GCP_SA_KEY_DEVELOPMENT` Variable `SECRET_GCP_SA_KEY_<environment>` should be set in `GitLab CI secret variables`
48
- - `GCP_SECRET_NAME` - Name of secret in Google Secret Manager
49
- - `MAX_INSTANCES` - Maximum instance count in Cloudrun, default is 8
50
- - `MIN_INSTANCES` - Minimum instance count in Cloudrun, default is 0
51
- - `SECRET_PATH` - CloudRun volume where secrets will be injected e.g. `/config/secrets.json` can't be the same path ass app work dir e.g. `/usr/src/app` deploy will fail cause secret protection. But have to be identical with ENV `CFG_JSON_PATH` in Dockerfile
52
- - `SKIP_AUDIT` - Skip NPM Audit, defaults to `false`
53
- - `SKIP_LINT` - Skip lint, defaults to `false`
54
- - `SKIP_TESTS` - Skip tests, defaults to `false`
55
- - `SQL_INSTANCE_NAME` - SQL instance name
56
- - `VPC_CONNECTOR_NAME` - serverless connector name, has to be in the same region
57
- - `DOCKER_REGISTRY_TYPE` - whenever to push Docker image into Container Registry or Artifacts Registry, default is
58
- `container`
59
- - `DOCKER_REGISTRY_URL` - hostname of Docker Registry, defaults to `eu.gcr.io`
60
- - `ANY_ADDITIONAL_CLOUDRUN_ARGS` - any argument required by Cloud Run, eg `--concurrency=1000 --clear-labels ...`
61
-
62
- Common variables:
63
-
64
- - `GCP_TEST_SECRET_PROJECT_ID` - GCP project identifier for test secrets
65
- - `GCP_SECRET_TEST_NAME` - Name of test secret in Google Secret Manager
66
-
67
- ## 📄 Additional Resources
68
-
69
- - [Google Cloudrun docs](https://cloud.google.com/run/docs)
@@ -1,18 +0,0 @@
1
- import { config } from './config.js'
2
- import { pinoLoggerFactory } from './adapters/pino.logger.js'
3
- import { LoggerPort } from './domain/ports/logger.d.js'
4
- import { healthCheckService } from './domain/health-check.service.js'
5
-
6
- export interface Container {
7
- logger: LoggerPort
8
- healthCheckService: typeof healthCheckService
9
- }
10
-
11
- export const createContainer = (): Container => {
12
- const logger = pinoLoggerFactory.create(config.logger)
13
-
14
- return {
15
- logger,
16
- healthCheckService,
17
- }
18
- }
@@ -1,39 +0,0 @@
1
- import { Container } from './container.js'
2
-
3
- interface BaseContext {
4
- container: Container
5
- note?: string
6
- }
7
-
8
- export interface ApiUserRequestContext extends BaseContext {
9
- type: 'api-user'
10
- user: null // Add UserContext if Auth is implemented
11
- }
12
-
13
- export interface ServerRequestContext extends BaseContext {
14
- type: 'server'
15
- }
16
-
17
- /**
18
- * Defines context in which current application runs.
19
- * Context should be created with every external call (user request, cli input, ...)
20
- */
21
- export type RequestContext = ApiUserRequestContext | ServerRequestContext
22
-
23
- /**
24
- * Creator of the context for the App. Every API layer is responsible for
25
- * creating the context based on the Api parameters (http headers, protocol settings etc...)
26
- */
27
- export type RequestContextFactory<Params extends any[]> = (
28
- container: Readonly<Container>,
29
- ...params: Params
30
- ) => Promise<RequestContext>
31
-
32
- /**
33
- * Creator of the server context that should be used only in executions that are invoked
34
- * on server, f.e. CLI, server start up etc.
35
- */
36
- export type ServerRequestContextFactory<Params extends any[]> = (
37
- container: Readonly<Container>,
38
- ...params: Params
39
- ) => Promise<ServerRequestContext>
@@ -1,9 +0,0 @@
1
- export enum ErrorCode {
2
- UNKNOWN = 0,
3
- VALIDATION = 1000,
4
- }
5
-
6
- export const errorMessages = {
7
- [ErrorCode.UNKNOWN]: 'Unknown error',
8
- [ErrorCode.VALIDATION]: 'Validation error',
9
- }
@@ -1,25 +0,0 @@
1
- import { ErrorCode, errorMessages } from './codes.js'
2
-
3
- export class DomainError<AdditionalData = any> extends Error {
4
- constructor(
5
- public readonly code: ErrorCode,
6
- public readonly message: string = errorMessages[code],
7
- public readonly data?: AdditionalData
8
- ) {
9
- super(message)
10
- }
11
- }
12
-
13
- export type ValidationErrorData =
14
- | Array<{ field: string; message: string }>
15
- | { field: string; message: string }
16
-
17
- export class ValidationError extends DomainError<ValidationErrorData> {
18
- constructor(errors: ValidationErrorData) {
19
- super(
20
- ErrorCode.VALIDATION,
21
- errorMessages[ErrorCode.VALIDATION],
22
- Array.isArray(errors) ? errors : [errors]
23
- )
24
- }
25
- }
@@ -1,21 +0,0 @@
1
- export interface LoggerConfig {
2
- defaultLevel: string
3
- enablePrettyPrint?: boolean
4
- }
5
-
6
- type BaseLoggerFn = (object: any, message?: string) => void
7
-
8
- export interface LoggerPort {
9
- level: string
10
- debug: BaseLoggerFn
11
- info: BaseLoggerFn
12
- warn: BaseLoggerFn
13
- error: BaseLoggerFn
14
- fatal: BaseLoggerFn
15
- trace: BaseLoggerFn
16
- silent: BaseLoggerFn
17
- }
18
-
19
- export interface LoggerFactoryPort {
20
- create: (config: LoggerConfig) => LoggerPort
21
- }
@@ -1,12 +0,0 @@
1
- {
2
- // Server will run on this port
3
- "SERVER_PORT": 3000,
4
- // Logging level, see https://github.com/pinojs/pino/blob/master/docs/api.md#logger-level
5
- "LOGGER_DEFAULT_LEVEL": "debug",
6
- // Enable/disable logging object multiline formatted logging https://github.com/pinojs/pino/blob/master/docs/api.md#prettyprint-boolean--object
7
- "LOGGER_PRETTY": false,
8
- // Response development errors for debugging
9
- "SERVER_ALLOW_RESPONSE_ERRORS": false,
10
- // Enable GraphQL introspection
11
- "SERVER_ENABLE_INTROSPECTION": true
12
- }
@@ -1,53 +0,0 @@
1
- # GraphQL Cloudrun Starter
2
-
3
- Node.js project scaffolded with Cloudrun and GraphQL
4
-
5
- ## 🎉 Initialize project
6
-
7
- Run `create-node-app cloudrun-graphql` to init your project. By default project is created in `../node-app` folder.
8
-
9
- You can pass `destination` argument into the command as well.
10
- Example:
11
-
12
- - `create-node-app cloudrun-graphql /Users/foo/Documents/bar `
13
-
14
- ## 👷 Continuous Integration
15
-
16
- ### Environment variables
17
-
18
- Make sure you replace all the variable values containing `REPLACEME` in `ci-branch-config` files.
19
-
20
- The following variables must be set for each branch in `ci-branch-config` directory.
21
-
22
- - `GCP_PROJECT_ID` - GCP project identifier
23
- - `ENVIRONMENT` - e.g. `development`
24
-
25
- Optional variables:
26
-
27
- - `ALLOCATED_MEMORY` - Memory allocated at Cloudrun, default is 384Mi
28
- - `CLOUD_RUN_SERVICE_ACCOUNT` - CloudRun service account
29
- - `ENV_SECRETS` - Secret variables of the deployment, format is: `KEY=[NAME OF SECRET IN SECRET MANAGER:VERSION],...`
30
- - `ENV_VARS` - Environment variables of the deployment, format is: `KEY=VALUE,...`
31
- - `GCP_SA_KEY` - We use different service accounts for different environments. So we have to overwrite `GCP_SA_KEY` variable e.g.`GCP_SA_KEY=$SECRET_GCP_SA_KEY_DEVELOPMENT` Variable `SECRET_GCP_SA_KEY_<environment>` should be set in `GitLab CI secret variables`
32
- - `GCP_SECRET_NAME` - Name of secret in Google Secret Manager
33
- - `MAX_INSTANCES` - Maximum instance count in Cloudrun, default is 8
34
- - `MIN_INSTANCES` - Minimum instance count in Cloudrun, default is 0
35
- - `SECRET_PATH` - CloudRun volume where secrets will be injected e.g. `/config/secrets.json` can't be the same path ass app work dir e.g. `/usr/src/app` deploy will fail cause secret protection. But have to be identical with ENV `CFG_JSON_PATH` in Dockerfile
36
- - `SKIP_AUDIT` - Skip NPM Audit, defaults to `false`
37
- - `SKIP_LINT` - Skip lint, defaults to `false`
38
- - `SKIP_TESTS` - Skip tests, defaults to `false`
39
- - `SQL_INSTANCE_NAME` - SQL instance name
40
- - `VPC_CONNECTOR_NAME` - serverless connector name, has to be in the same region
41
- - `DOCKER_REGISTRY_TYPE` - whenever to push Docker image into Container Registry or Artifacts Registry, default is
42
- `container`
43
- - `DOCKER_REGISTRY_URL` - hostname of Docker Registry, defaults to `eu.gcr.io`
44
- - `ANY_ADDITIONAL_CLOUDRUN_ARGS` - any argument required by Cloud Run, eg `--concurrency=1000 --clear-labels ...`
45
-
46
- Common variables:
47
-
48
- - `GCP_TEST_SECRET_PROJECT_ID` - GCP project identifier for test secrets
49
- - `GCP_SECRET_TEST_NAME` - Name of test secret in Google Secret Manager
50
-
51
- ## 📄 Additional Resources
52
-
53
- - [Google Cloudrun docs](https://cloud.google.com/run/docs)
@@ -1,44 +0,0 @@
1
- import { pino as pinoLogger } from 'pino'
2
- import { LoggerFactoryPort } from '../domain/ports/logger.d.js'
3
-
4
- // https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity
5
- const PinoLevelToSeverityLookup: Record<string, string> = {
6
- trace: 'DEBUG',
7
- debug: 'DEBUG',
8
- info: 'INFO',
9
- warn: 'WARNING',
10
- error: 'ERROR',
11
- fatal: 'CRITICAL',
12
- } as const
13
-
14
- const defaultPinoConf = (defaultLevel: string) => ({
15
- messageKey: 'message',
16
- formatters: {
17
- messageKey: 'message',
18
- level: (label: string, num: number) => {
19
- return {
20
- severity:
21
- PinoLevelToSeverityLookup[label] ??
22
- PinoLevelToSeverityLookup[defaultLevel],
23
- level: num,
24
- }
25
- },
26
- },
27
- })
28
-
29
- export const pinoLoggerFactory: LoggerFactoryPort = {
30
- create: config => {
31
- return pinoLogger({
32
- ...defaultPinoConf(config.defaultLevel),
33
- transport: config.enablePrettyPrint
34
- ? {
35
- target: 'pino-pretty',
36
- options: {
37
- colorize: true,
38
- },
39
- }
40
- : undefined,
41
- level: config.defaultLevel,
42
- })
43
- },
44
- }
@@ -1,11 +0,0 @@
1
- import { safeConfig } from './config.js'
2
- import { createAppServer, startServer } from './view/server.js'
3
- import { createContainer } from './container.js'
4
-
5
- const appContainer = createContainer()
6
- const { logger } = appContainer
7
-
8
- logger.info({ config: safeConfig }, 'Loaded config')
9
-
10
- const appServer = createAppServer()
11
- void startServer({ ...appServer, container: appContainer })