@contember/engine-server 1.1.0-beta.3 → 1.2.0-alpha.1

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 (126) hide show
  1. package/dist/src/MasterContainer.d.ts +12 -25
  2. package/dist/src/MasterContainer.d.ts.map +1 -1
  3. package/dist/src/MasterContainer.js +36 -80
  4. package/dist/src/MasterContainer.js.map +1 -1
  5. package/dist/src/bootstrap/Initializer.d.ts +3 -3
  6. package/dist/src/bootstrap/Initializer.d.ts.map +1 -1
  7. package/dist/src/bootstrap/Initializer.js +15 -6
  8. package/dist/src/bootstrap/Initializer.js.map +1 -1
  9. package/dist/src/config/config.d.ts +5 -4
  10. package/dist/src/config/config.d.ts.map +1 -1
  11. package/dist/src/config/config.js +2 -2
  12. package/dist/src/config/config.js.map +1 -1
  13. package/dist/src/config/configSchema.d.ts +45 -11
  14. package/dist/src/config/configSchema.d.ts.map +1 -1
  15. package/dist/src/config/configSchema.js +20 -18
  16. package/dist/src/config/configSchema.js.map +1 -1
  17. package/dist/src/config/configTemplate.d.ts.map +1 -1
  18. package/dist/src/config/configTemplate.js +23 -0
  19. package/dist/src/config/configTemplate.js.map +1 -1
  20. package/dist/src/index.d.ts +9 -3
  21. package/dist/src/index.d.ts.map +1 -1
  22. package/dist/src/index.js +23 -4
  23. package/dist/src/index.js.map +1 -1
  24. package/dist/src/project/ProjectContainer.js +1 -1
  25. package/dist/src/project/ProjectContainer.js.map +1 -1
  26. package/dist/src/project/ProjectContainerResolver.d.ts +6 -3
  27. package/dist/src/project/ProjectContainerResolver.d.ts.map +1 -1
  28. package/dist/src/project/ProjectContainerResolver.js +4 -16
  29. package/dist/src/project/ProjectContainerResolver.js.map +1 -1
  30. package/dist/src/projectGroup/ProjectGroupContainer.d.ts +2 -1
  31. package/dist/src/projectGroup/ProjectGroupContainer.d.ts.map +1 -1
  32. package/dist/src/projectGroup/ProjectGroupContainer.js +8 -4
  33. package/dist/src/projectGroup/ProjectGroupContainer.js.map +1 -1
  34. package/dist/src/projectGroup/ProjectGroupResolver.d.ts +7 -0
  35. package/dist/src/projectGroup/ProjectGroupResolver.d.ts.map +1 -0
  36. package/dist/src/projectGroup/ProjectGroupResolver.js +13 -0
  37. package/dist/src/projectGroup/ProjectGroupResolver.js.map +1 -0
  38. package/dist/src/start.js +15 -112
  39. package/dist/src/start.js.map +1 -1
  40. package/dist/src/tsconfig.tsbuildinfo +1 -1
  41. package/dist/src/utils/index.d.ts +0 -4
  42. package/dist/src/utils/index.d.ts.map +1 -1
  43. package/dist/src/utils/index.js +0 -4
  44. package/dist/src/utils/index.js.map +1 -1
  45. package/dist/src/utils/serverStartup.d.ts +31 -0
  46. package/dist/src/utils/serverStartup.d.ts.map +1 -0
  47. package/dist/src/utils/serverStartup.js +42 -0
  48. package/dist/src/utils/serverStartup.js.map +1 -0
  49. package/dist/src/utils/serverTermination.d.ts +12 -0
  50. package/dist/src/utils/serverTermination.d.ts.map +1 -0
  51. package/dist/src/utils/serverTermination.js +26 -0
  52. package/dist/src/utils/serverTermination.js.map +1 -0
  53. package/dist/tests/e2e/http.test.js +74 -157
  54. package/dist/tests/e2e/http.test.js.map +1 -1
  55. package/dist/tests/e2e/requests.d.ts +4 -0
  56. package/dist/tests/e2e/requests.d.ts.map +1 -0
  57. package/dist/tests/e2e/requests.js +59 -0
  58. package/dist/tests/e2e/requests.js.map +1 -0
  59. package/dist/tests/e2e/tester.d.ts +19 -0
  60. package/dist/tests/e2e/tester.d.ts.map +1 -0
  61. package/dist/tests/e2e/tester.js +99 -0
  62. package/dist/tests/e2e/tester.js.map +1 -0
  63. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  64. package/esbuild.js +7 -14
  65. package/package.json +20 -20
  66. package/src/MasterContainer.ts +58 -110
  67. package/src/bootstrap/Initializer.ts +16 -6
  68. package/src/config/config.ts +7 -5
  69. package/src/config/configSchema.ts +30 -33
  70. package/src/config/configTemplate.ts +23 -0
  71. package/src/index.ts +15 -2
  72. package/src/project/ProjectContainer.ts +1 -1
  73. package/src/project/ProjectContainerResolver.ts +4 -17
  74. package/src/projectGroup/ProjectGroupContainer.ts +12 -3
  75. package/src/projectGroup/ProjectGroupResolver.ts +12 -0
  76. package/src/start.ts +18 -127
  77. package/src/utils/index.ts +0 -4
  78. package/src/utils/serverStartup.ts +42 -0
  79. package/src/utils/serverTermination.ts +20 -0
  80. package/tests/e2e/http.test.ts +84 -150
  81. package/tests/e2e/requests.ts +71 -0
  82. package/tests/e2e/tester.ts +118 -0
  83. package/alpine.dockerfile +0 -30
  84. package/debian.dockerfile +0 -27
  85. package/dist/src/http/CollectHttpMetricsMiddelware.d.ts +0 -5
  86. package/dist/src/http/CollectHttpMetricsMiddelware.d.ts.map +0 -1
  87. package/dist/src/http/CollectHttpMetricsMiddelware.js +0 -36
  88. package/dist/src/http/CollectHttpMetricsMiddelware.js.map +0 -1
  89. package/dist/src/http/ShowMetricsMiddleware.d.ts +0 -4
  90. package/dist/src/http/ShowMetricsMiddleware.d.ts.map +0 -1
  91. package/dist/src/http/ShowMetricsMiddleware.js +0 -20
  92. package/dist/src/http/ShowMetricsMiddleware.js.map +0 -1
  93. package/dist/src/http/index.d.ts +0 -3
  94. package/dist/src/http/index.d.ts.map +0 -1
  95. package/dist/src/http/index.js +0 -19
  96. package/dist/src/http/index.js.map +0 -1
  97. package/dist/src/projectGroup/ProjectGroupContainerResolver.d.ts +0 -12
  98. package/dist/src/projectGroup/ProjectGroupContainerResolver.d.ts.map +0 -1
  99. package/dist/src/projectGroup/ProjectGroupContainerResolver.js +0 -36
  100. package/dist/src/projectGroup/ProjectGroupContainerResolver.js.map +0 -1
  101. package/dist/src/utils/cluster.d.ts +0 -9
  102. package/dist/src/utils/cluster.d.ts.map +0 -1
  103. package/dist/src/utils/cluster.js +0 -47
  104. package/dist/src/utils/cluster.js.map +0 -1
  105. package/dist/src/utils/dbMetrics.d.ts +0 -16
  106. package/dist/src/utils/dbMetrics.d.ts.map +0 -1
  107. package/dist/src/utils/dbMetrics.js +0 -98
  108. package/dist/src/utils/dbMetrics.js.map +0 -1
  109. package/dist/src/utils/timeout.d.ts +0 -2
  110. package/dist/src/utils/timeout.d.ts.map +0 -1
  111. package/dist/src/utils/timeout.js +0 -8
  112. package/dist/src/utils/timeout.js.map +0 -1
  113. package/dist/src/utils/tuple.d.ts +0 -2
  114. package/dist/src/utils/tuple.d.ts.map +0 -1
  115. package/dist/src/utils/tuple.js +0 -6
  116. package/dist/src/utils/tuple.js.map +0 -1
  117. package/jasmine.json +0 -7
  118. package/src/http/CollectHttpMetricsMiddelware.ts +0 -32
  119. package/src/http/ShowMetricsMiddleware.ts +0 -12
  120. package/src/http/index.ts +0 -2
  121. package/src/projectGroup/ProjectGroupContainerResolver.ts +0 -47
  122. package/src/utils/cluster.ts +0 -40
  123. package/src/utils/dbMetrics.ts +0 -111
  124. package/src/utils/timeout.ts +0 -4
  125. package/src/utils/tuple.ts +0 -1
  126. package/tslint.json +0 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/engine-server",
3
- "version": "1.1.0-beta.3",
3
+ "version": "1.2.0-alpha.1",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/src/index.js",
6
6
  "typings": "dist/src/index.d.ts",
@@ -8,24 +8,24 @@
8
8
  "test-e2e": "vitest --no-threads tests/e2e"
9
9
  },
10
10
  "dependencies": {
11
- "@contember/authorization": "^1.1.0-beta.3",
12
- "@contember/config-loader": "^1.1.0-beta.3",
13
- "@contember/database": "^1.1.0-beta.3",
14
- "@contember/database-migrations": "^1.1.0-beta.3",
15
- "@contember/dic": "^1.1.0-beta.3",
16
- "@contember/typesafe": "^1.1.0-beta.3",
17
- "@contember/engine-content-api": "^1.1.0-beta.3",
18
- "@contember/engine-http": "^1.1.0-beta.3",
19
- "@contember/engine-plugins": "^1.1.0-beta.3",
20
- "@contember/engine-s3-plugin": "^1.1.0-beta.3",
21
- "@contember/engine-system-api": "^1.1.0-beta.3",
22
- "@contember/engine-tenant-api": "^1.1.0-beta.3",
23
- "@contember/engine-vimeo-plugin": "^1.1.0-beta.3",
24
- "@contember/queryable": "^1.1.0-beta.3",
25
- "@contember/schema": "^1.1.0-beta.3",
26
- "@contember/schema-definition": "^1.1.0-beta.3",
27
- "@contember/schema-migrations": "^1.1.0-beta.3",
28
- "@contember/schema-utils": "^1.1.0-beta.3",
11
+ "@contember/authorization": "^1.2.0-alpha.1",
12
+ "@contember/config-loader": "^1.2.0-alpha.1",
13
+ "@contember/database": "^1.2.0-alpha.1",
14
+ "@contember/database-migrations": "^1.2.0-alpha.1",
15
+ "@contember/dic": "^1.2.0-alpha.1",
16
+ "@contember/typesafe": "^1.2.0-alpha.1",
17
+ "@contember/engine-content-api": "^1.2.0-alpha.1",
18
+ "@contember/engine-http": "^1.2.0-alpha.1",
19
+ "@contember/engine-plugins": "^1.2.0-alpha.1",
20
+ "@contember/engine-s3-plugin": "^1.2.0-alpha.1",
21
+ "@contember/engine-system-api": "^1.2.0-alpha.1",
22
+ "@contember/engine-tenant-api": "^1.2.0-alpha.1",
23
+ "@contember/engine-vimeo-plugin": "^1.2.0-alpha.1",
24
+ "@contember/queryable": "^1.2.0-alpha.1",
25
+ "@contember/schema": "^1.2.0-alpha.1",
26
+ "@contember/schema-definition": "^1.2.0-alpha.1",
27
+ "@contember/schema-migrations": "^1.2.0-alpha.1",
28
+ "@contember/schema-utils": "^1.2.0-alpha.1",
29
29
  "@koa/cors": "^3.1.0",
30
30
  "@sentry/node": "^6.8.0",
31
31
  "graphql": "^15.4.0",
@@ -37,7 +37,7 @@
37
37
  "uuid": "^8.3.1"
38
38
  },
39
39
  "devDependencies": {
40
- "@contember/engine-api-tester": "^1.1.0-beta.3",
40
+ "@contember/engine-api-tester": "^1.2.0-alpha.1",
41
41
  "@types/koa-compress": "^4.0.1",
42
42
  "@types/node": "^17.0.5",
43
43
  "@types/supertest": "^2.0.8",
@@ -2,11 +2,10 @@ import { SystemContainerFactory } from '@contember/engine-system-api'
2
2
  import { TenantContainerFactory } from '@contember/engine-tenant-api'
3
3
  import { Builder } from '@contember/dic'
4
4
  import { ServerConfig } from './config/config'
5
- import { createDbMetricsRegistrar, logSentryError, ProcessType } from './utils'
5
+ import { logSentryError } from './utils'
6
6
  import { ModificationHandlerFactory } from '@contember/schema-migrations'
7
7
  import { Initializer } from './bootstrap'
8
8
  import { Plugin } from '@contember/engine-plugins'
9
- import { createColllectHttpMetricsMiddleware, createShowMetricsMiddleware } from './http'
10
9
  import {
11
10
  compose,
12
11
  ContentApiMiddlewareFactory,
@@ -18,31 +17,31 @@ import {
18
17
  createPoweredByHeaderMiddleware,
19
18
  createProviders,
20
19
  createTimerMiddleware,
21
- CryptoWrapper,
22
20
  ErrorMiddlewareFactory,
23
21
  Koa,
24
22
  NotModifiedChecker,
25
- ProjectGroupResolver,
26
23
  Providers,
27
- route, SystemApiMiddlewareFactory, SystemGraphQLContextFactory,
28
- SystemGraphQLHandlerFactory, TenantApiMiddlewareFactory, TenantGraphQLContextFactory,
24
+ route,
25
+ SystemApiMiddlewareFactory,
26
+ SystemGraphQLContextFactory,
27
+ SystemGraphQLHandlerFactory,
28
+ TenantApiMiddlewareFactory,
29
+ TenantGraphQLContextFactory,
29
30
  TenantGraphQLHandlerFactory,
30
31
  } from '@contember/engine-http'
31
- import prom from 'prom-client'
32
32
  import { ProjectContainerFactoryFactory } from './project'
33
- import { createSecretKey } from 'crypto'
34
33
  import koaCompress from 'koa-compress'
35
34
  import bodyParser from 'koa-bodyparser'
36
35
  import { ProjectConfigResolver } from './config/projectConfigResolver'
37
36
  import { TenantConfigResolver } from './config/tenantConfigResolver'
38
- import { ProjectGroupContainerResolver } from './projectGroup/ProjectGroupContainerResolver'
39
37
  import { ProjectGroupContainerFactory } from './projectGroup/ProjectGroupContainer'
40
38
  import corsMiddleware from '@koa/cors'
39
+ import { ProjectGroupResolver } from './projectGroup/ProjectGroupResolver'
40
+ import { ProjectGroupContainer, ProjectGroupResolver as ProjectGroupResolverInterface } from '@contember/engine-http'
41
41
 
42
42
  export interface MasterContainer {
43
43
  initializer: Initializer
44
44
  koa: Koa
45
- monitoringKoa: Koa
46
45
  providers: Providers
47
46
  }
48
47
 
@@ -52,7 +51,6 @@ export interface MasterContainerArgs {
52
51
  projectConfigResolver: ProjectConfigResolver
53
52
  tenantConfigResolver: TenantConfigResolver
54
53
  plugins: Plugin[]
55
- processType: ProcessType
56
54
  version?: string
57
55
  }
58
56
 
@@ -63,7 +61,6 @@ export class MasterContainerFactory {
63
61
  plugins,
64
62
  projectConfigResolver,
65
63
  tenantConfigResolver,
66
- processType,
67
64
  version,
68
65
  }: MasterContainerArgs) {
69
66
  return new Builder({})
@@ -71,8 +68,6 @@ export class MasterContainerFactory {
71
68
  serverConfig)
72
69
  .addService('debugMode', () =>
73
70
  debugMode)
74
- .addService('processType', () =>
75
- processType)
76
71
  .addService('version', () =>
77
72
  version)
78
73
  .addService('projectConfigResolver', () =>
@@ -95,62 +90,22 @@ export class MasterContainerFactory {
95
90
  new TenantGraphQLHandlerFactory(logSentryError))
96
91
  .addService('systemGraphQLHandlerFactory', ({ debugMode }) =>
97
92
  new SystemGraphQLHandlerFactory(logSentryError, debugMode))
98
- .addService('projectGroupContainerFactory', ({ providers, systemContainerFactory, tenantContainerFactory, projectContainerFactoryFactory, projectConfigResolver, tenantGraphQLHandlerFactory, systemGraphQLHandlerFactory }) =>
99
- new ProjectGroupContainerFactory(providers, systemContainerFactory, tenantContainerFactory, projectContainerFactoryFactory, projectConfigResolver, tenantGraphQLHandlerFactory, systemGraphQLHandlerFactory))
100
- .addService('projectGroupContainerResolver', ({ tenantConfigResolver, projectGroupContainerFactory }) =>
101
- new ProjectGroupContainerResolver(tenantConfigResolver, projectGroupContainerFactory))
102
- .addService('promRegistry', ({ processType, projectGroupContainerResolver }) => {
103
- if (processType === ProcessType.clusterMaster) {
104
- const register = new prom.AggregatorRegistry()
105
- prom.collectDefaultMetrics({ register })
106
- return register
107
- }
108
- const register = prom.register
109
- prom.collectDefaultMetrics({ register })
110
- const registrar = createDbMetricsRegistrar(register)
111
- projectGroupContainerResolver.onCreate.push((groupContainer, slug) => {
112
- groupContainer.projectContainerResolver.onCreate.push(projectContainer =>
113
- registrar({
114
- connection: projectContainer.connection,
115
- labels: {
116
- contember_module: 'content',
117
- contember_project: projectContainer.project.slug,
118
- contember_project_group: slug ?? 'unknown',
119
- },
120
- }),
121
- )
122
- return registrar({
123
- connection: groupContainer.tenantContainer.connection,
124
- labels: {
125
- contember_module: 'tenant',
126
- contember_project_group: slug ?? 'unknown',
127
- contember_project: 'unknown',
128
- },
129
- })
130
- })
131
- return register
132
- })
93
+ .addService('projectGroupContainerFactory', ({ debugMode, providers, systemContainerFactory, tenantContainerFactory, projectContainerFactoryFactory, projectConfigResolver, tenantGraphQLHandlerFactory, systemGraphQLHandlerFactory }) =>
94
+ new ProjectGroupContainerFactory(debugMode, providers, systemContainerFactory, tenantContainerFactory, projectContainerFactoryFactory, projectConfigResolver, tenantGraphQLHandlerFactory, systemGraphQLHandlerFactory))
95
+ .addService('projectGroupContainer', ({ tenantConfigResolver, projectGroupContainerFactory }) =>
96
+ projectGroupContainerFactory.create({ slug: undefined, config: tenantConfigResolver(undefined, {}) }))
133
97
  .addService('httpErrorMiddlewareFactory', ({ debugMode }) =>
134
98
  new ErrorMiddlewareFactory(debugMode))
135
- .addService('projectGroupResolver', ({ projectGroupContainerResolver, serverConfig }) => {
136
- const encryptionKey = serverConfig.projectGroup?.configEncryptionKey
137
- ? createSecretKey(Buffer.from(serverConfig.projectGroup?.configEncryptionKey, 'hex'))
138
- : undefined
139
- return new ProjectGroupResolver(
140
- serverConfig.projectGroup?.domainMapping,
141
- serverConfig.projectGroup?.configHeader,
142
- serverConfig.projectGroup?.configEncryptionKey ? new CryptoWrapper(encryptionKey) : undefined,
143
- projectGroupContainerResolver,
144
- )
145
- })
99
+ .addService('projectGroupResolver', ({ projectGroupContainer }): ProjectGroupResolverInterface =>
100
+ new ProjectGroupResolver(projectGroupContainer))
146
101
  .addService('notModifiedChecker', () =>
147
102
  new NotModifiedChecker())
148
103
  .addService('contentGraphqlContextFactory', ({ providers }) =>
149
104
  new ContentGraphQLContextFactory(providers))
150
105
  .addService('contentQueryHandlerFactory', ({ debugMode }) =>
151
106
  new ContentQueryHandlerFactory(debugMode, logSentryError))
152
- .addService('contentApiMiddlewareFactory', ({ debugMode, projectGroupResolver, notModifiedChecker, contentGraphqlContextFactory, contentQueryHandlerFactory }) =>
153
- new ContentApiMiddlewareFactory(debugMode, projectGroupResolver, notModifiedChecker, contentGraphqlContextFactory, contentQueryHandlerFactory))
107
+ .addService('contentApiMiddlewareFactory', ({ projectGroupResolver, notModifiedChecker, contentGraphqlContextFactory, contentQueryHandlerFactory }) =>
108
+ new ContentApiMiddlewareFactory(projectGroupResolver, notModifiedChecker, contentGraphqlContextFactory, contentQueryHandlerFactory))
154
109
  .addService('tenantGraphQLContextFactory', () =>
155
110
  new TenantGraphQLContextFactory())
156
111
  .addService('tenantApiMiddlewareFactory', ({ debugMode, projectGroupResolver, tenantGraphQLContextFactory }) =>
@@ -159,62 +114,55 @@ export class MasterContainerFactory {
159
114
  new SystemGraphQLContextFactory())
160
115
  .addService('systemApiMiddlewareFactory', ({ debugMode, projectGroupResolver, systemGraphQLContextFactory }) =>
161
116
  new SystemApiMiddlewareFactory(debugMode, projectGroupResolver, systemGraphQLContextFactory))
162
- .addService('koa', ({ contentApiMiddlewareFactory, tenantApiMiddlewareFactory, systemApiMiddlewareFactory, httpErrorMiddlewareFactory, promRegistry, debugMode, version, serverConfig }) => {
163
- const app = new Koa()
164
- app.use(
165
- compose([
166
- koaCompress({
167
- br: false,
168
- }),
169
- bodyParser({
170
- jsonLimit: serverConfig.http.requestBodySize || '1mb',
171
- }),
172
- createPoweredByHeaderMiddleware(debugMode, version ?? 'unknown'),
173
- httpErrorMiddlewareFactory.create(),
174
- createColllectHttpMetricsMiddleware(promRegistry),
175
- createTimerMiddleware(),
176
- route('/playground$', createPlaygroundMiddleware()),
177
- createHomepageMiddleware(),
178
- corsMiddleware(),
179
- route(
180
- '/content/:projectSlug/:stageSlug$',
181
- compose([
182
- createModuleInfoMiddleware('content'),
183
- contentApiMiddlewareFactory.create(),
184
- ]),
185
- ),
186
- route(
187
- '/tenant$',
188
- compose([
189
- createModuleInfoMiddleware('tenant'),
190
- tenantApiMiddlewareFactory.create(),
191
- ]),
192
- ),
193
- route(
194
- '/system/:projectSlug$',
195
- compose([
196
- createModuleInfoMiddleware('system'),
197
- systemApiMiddlewareFactory.create(),
198
- ]),
199
- ),
200
- ]),
201
- )
202
-
203
- return app
204
- })
205
- .addService('monitoringKoa', ({ promRegistry }) => {
117
+ .addService('koaMiddlewares', ({ contentApiMiddlewareFactory, tenantApiMiddlewareFactory, systemApiMiddlewareFactory, httpErrorMiddlewareFactory, debugMode, version, serverConfig }) =>
118
+ compose([
119
+ koaCompress({
120
+ br: false,
121
+ }),
122
+ bodyParser({
123
+ jsonLimit: serverConfig.http.requestBodySize || '1mb',
124
+ }),
125
+ createPoweredByHeaderMiddleware(debugMode, version ?? 'unknown'),
126
+ httpErrorMiddlewareFactory.create(),
127
+ createTimerMiddleware(),
128
+ route('/playground$', createPlaygroundMiddleware()),
129
+ createHomepageMiddleware(),
130
+ corsMiddleware(),
131
+ route(
132
+ '/content/:projectSlug/:stageSlug$',
133
+ compose([
134
+ createModuleInfoMiddleware('content'),
135
+ contentApiMiddlewareFactory.create(),
136
+ ]),
137
+ ),
138
+ route(
139
+ '/tenant$',
140
+ compose([
141
+ createModuleInfoMiddleware('tenant'),
142
+ tenantApiMiddlewareFactory.create(),
143
+ ]),
144
+ ),
145
+ route(
146
+ '/system/:projectSlug$',
147
+ compose([
148
+ createModuleInfoMiddleware('system'),
149
+ systemApiMiddlewareFactory.create(),
150
+ ]),
151
+ ),
152
+ ]))
153
+ .addService('koa', ({ koaMiddlewares }) => {
206
154
  const app = new Koa()
207
- app.use(createShowMetricsMiddleware(promRegistry))
155
+ app.use(koaMiddlewares)
208
156
 
209
157
  return app
210
158
  })
211
- .addService('initializer', ({ projectGroupContainerResolver }) =>
212
- new Initializer(projectGroupContainerResolver))
159
+ .addService('initializer', ({ projectGroupContainer }) =>
160
+ new Initializer(projectGroupContainer))
213
161
 
214
162
  }
215
163
 
216
164
  create(args: MasterContainerArgs): MasterContainer {
217
165
  const container = this.createBuilder(args).build()
218
- return container.pick('initializer', 'koa', 'monitoringKoa', 'providers')
166
+ return container.pick('initializer', 'koa', 'providers')
219
167
  }
220
168
  }
@@ -1,9 +1,9 @@
1
1
  import { Logger } from '@contember/engine-common'
2
- import { ProjectGroupContainerResolver } from '../projectGroup/ProjectGroupContainerResolver'
2
+ import { ProjectGroupContainer } from '@contember/engine-http'
3
3
 
4
4
  export class Initializer {
5
5
  constructor(
6
- private readonly projectGroupContainerResolver: ProjectGroupContainerResolver,
6
+ private readonly projectGroupContainer: ProjectGroupContainer,
7
7
  ) {}
8
8
 
9
9
  public async initialize(): Promise<string[]> {
@@ -11,17 +11,27 @@ export class Initializer {
11
11
  const logger = new Logger(console.log)
12
12
  logger.group('\nInitializing tenant database')
13
13
  // todo
14
- const groupContainer = await this.projectGroupContainerResolver.getProjectGroupContainer(undefined)
14
+ const groupContainer = await this.projectGroupContainer
15
15
 
16
- await groupContainer.tenantContainer.migrationsRunner.run(logger.write.bind(logger))
16
+ const tenantContainer = groupContainer.tenantContainer
17
+ await tenantContainer.migrationsRunner.run(logger.write.bind(logger))
17
18
  logger.groupEnd()
18
19
 
19
20
  const systemContainer = groupContainer.systemContainer
20
21
  const projects: string[] = []
21
- for (const projectContainer of await groupContainer.projectContainerResolver.getAllProjectContainers()) {
22
+
23
+ const tenantProjects = await tenantContainer.projectManager.getProjects(tenantContainer.databaseContext)
24
+ for (const { slug: projectSlug } of tenantProjects) {
25
+ logger.group(`\nUpdating project ${projectSlug}`)
26
+ const projectContainer = await groupContainer.projectContainerResolver.getProjectContainer(projectSlug, {
27
+ alias: false,
28
+ logger,
29
+ })
30
+ if (!projectContainer) {
31
+ throw new Error()
32
+ }
22
33
  const project = projectContainer.project
23
34
  projects.push(project.slug)
24
- logger.group(`\nUpdating project ${project.slug}`)
25
35
  await systemContainer.projectInitializer.initialize(projectContainer.systemDatabaseContextFactory, project, logger)
26
36
  logger.groupEnd()
27
37
  }
@@ -1,22 +1,24 @@
1
1
  import { ConfigLoader, createObjectParametersResolver, Merger, resolveParameters } from '@contember/config-loader'
2
2
  import { ConfigProcessor } from '@contember/engine-plugins'
3
- import { serverConfigSchema, tenantConfigSchema } from './configSchema'
3
+ import { serverConfigSchema as defaultServerConfigSchema, tenantConfigSchema } from './configSchema'
4
4
  import { configTemplate } from './configTemplate'
5
5
  import { createProjectConfigResolver, ProjectConfigResolver } from './projectConfigResolver'
6
6
  import { createTenantConfigResolver, TenantConfigResolver } from './tenantConfigResolver'
7
+ import { Type } from '@contember/typesafe'
7
8
 
8
- export type ServerConfig = ReturnType<typeof serverConfigSchema>
9
+ export type ServerConfig = ReturnType<typeof defaultServerConfigSchema>
9
10
  export type TenantConfig = ReturnType<typeof tenantConfigSchema>
10
11
 
11
12
  export type ConfigSource = { data: string; type: 'file' | 'json' | 'yaml' }
12
13
 
13
14
  type Env = Record<string, string>
14
15
 
15
- export async function readConfig(
16
- configSources: ConfigSource[],
16
+ export async function readConfig<T extends ServerConfig>(
17
+ configSources: ConfigSource[] = [],
17
18
  configProcessors: ConfigProcessor[] = [],
19
+ serverConfigSchema: Type<T> = defaultServerConfigSchema as Type<T>,
18
20
  ): Promise<{
19
- serverConfig: ServerConfig
21
+ serverConfig: T
20
22
  projectConfigResolver: ProjectConfigResolver
21
23
  tenantConfigResolver: TenantConfigResolver
22
24
  }> {
@@ -3,7 +3,7 @@ import { MailerOptions } from '@contember/engine-tenant-api'
3
3
  import { upperCaseFirst } from '../utils'
4
4
 
5
5
 
6
- export const dbCredentialsSchema = Typesafe.intersection(
6
+ export const dbConfigSchema = Typesafe.intersection(
7
7
  Typesafe.object({
8
8
  host: Typesafe.string,
9
9
  port: Typesafe.number,
@@ -13,12 +13,25 @@ export const dbCredentialsSchema = Typesafe.intersection(
13
13
  }),
14
14
  Typesafe.partial({
15
15
  ssl: Typesafe.boolean,
16
+ queryTimeoutMs: Typesafe.number,
17
+ statementTimeoutMs: Typesafe.number,
18
+ connectionTimeoutMs: Typesafe.number,
19
+ pool: Typesafe.partial({
20
+ maxConnections: Typesafe.number,
21
+ maxConnecting: Typesafe.number,
22
+ maxIdle: Typesafe.number,
23
+ reconnectIntervalMs: Typesafe.number,
24
+ idleTimeoutMs: Typesafe.number,
25
+ acquireTimeoutMs: Typesafe.number,
26
+ maxUses: Typesafe.number,
27
+ maxAgeMs: Typesafe.number,
28
+ }),
16
29
  }),
17
30
  )
18
31
 
19
32
  export const tenantConfigSchema = Typesafe.intersection(
20
33
  Typesafe.object({
21
- db: dbCredentialsSchema,
34
+ db: dbConfigSchema,
22
35
  mailer: Typesafe.transform(Typesafe.partial({
23
36
  from: Typesafe.string,
24
37
  host: Typesafe.string,
@@ -46,37 +59,21 @@ export const tenantConfigSchema = Typesafe.intersection(
46
59
  }),
47
60
  }),
48
61
  )
49
- export const serverConfigSchema = Typesafe.intersection(
50
- Typesafe.object({
51
- port: Typesafe.number,
52
- monitoringPort: Typesafe.number,
53
- http: Typesafe.partial({
54
- requestBodySize: Typesafe.string,
55
- }),
56
- logging: Typesafe.union(
57
- val => Typesafe.valueAt(val, ['sentry', 'dsn']) === undefined ? {} : Typesafe.fail([]),
58
- Typesafe.partial({
59
- sentry: Typesafe.object({
60
- dsn: Typesafe.string,
61
- }),
62
- }),
63
- ),
64
- }),
65
- Typesafe.partial({
66
- workerCount: Typesafe.union(Typesafe.number, Typesafe.string),
67
- projectGroup: (val: unknown, path: PropertyKey[] = []) => Typesafe.valueAt(val, ['domainMapping']) === undefined
68
- ? undefined
69
- : Typesafe.intersection(
70
- Typesafe.object({
71
- domainMapping: Typesafe.string,
72
- }),
73
- Typesafe.partial({
74
- configHeader: Typesafe.string,
75
- configEncryptionKey: Typesafe.string,
76
- }),
77
- )(val, path),
62
+
63
+ export const serverConfigSchema = Typesafe.object({
64
+ port: Typesafe.number,
65
+ http: Typesafe.partial({
66
+ requestBodySize: Typesafe.string,
78
67
  }),
79
- )
68
+ logging: Typesafe.union(
69
+ (val): { sentry?: { dsn: string } } => Typesafe.valueAt(val, ['sentry', 'dsn']) === undefined ? {} : Typesafe.fail([]),
70
+ Typesafe.partial({
71
+ sentry: Typesafe.object({
72
+ dsn: Typesafe.string,
73
+ }),
74
+ }),
75
+ ),
76
+ })
80
77
 
81
78
  export const stageConfig = Typesafe.record(
82
79
  Typesafe.string,
@@ -106,7 +103,7 @@ export const projectConfigSchema = Typesafe.object({
106
103
  Typesafe.object({
107
104
  useTenantDb: Typesafe.literal(true),
108
105
  }),
109
- dbCredentialsSchema,
106
+ dbConfigSchema,
110
107
  ),
111
108
  Typesafe.partial({
112
109
  systemSchema: Typesafe.string,
@@ -7,6 +7,19 @@ export const configTemplate: any = {
7
7
  password: `%tenant.env.DB_PASSWORD%`,
8
8
  database: `%tenant.env.DB_NAME%`,
9
9
  ssl: `%?tenant.env.DB_SSL::bool%`,
10
+ queryTimeoutMs: '%?tenant.env.DB_QUERY_TIMEOUT_MS::number%',
11
+ statementTimeoutMs: '%?tenant.env.DB_STATEMENT_TIMEOUT_MS::number%',
12
+ connectionTimeoutMs: '%?tenant.env.DB_CONNECTION_TIMEOUT_MS::number%',
13
+ pool: {
14
+ maxConnections: '%?tenant.env.DB_POOL_MAX_CONNECTIONS::number%',
15
+ maxConnecting: '%?tenant.env.DB_POOL_MAX_CONNECTING::number%',
16
+ maxIdle: '%?tenant.env.DB_POOL_MAX_IDLE::number%',
17
+ reconnectIntervalMs: '%?tenant.env.DB_POOL_RECONNECT_INTERVAL_MS::number%',
18
+ idleTimeoutMs: '%?tenant.env.DB_POOL_IDLE_TIMEOUT_MS::number%',
19
+ acquireTimeoutMs: '%?tenant.env.DB_POOL_ACQUIRE_TIMEOUT_MS::number%',
20
+ maxUses: '%?tenant.env.DB_POOL_MAX_USES::number%',
21
+ maxAgeMs: '%?tenant.env.DB_POOL_MAX_AGE_MS::number%',
22
+ },
10
23
  },
11
24
  mailer: {
12
25
  from: '%?tenant.env.MAILER_FROM%',
@@ -35,6 +48,16 @@ export const configTemplate: any = {
35
48
  password: `%?project.secret.db.password||project.env.DB_PASSWORD%`,
36
49
  database: `%?project.env.DB_NAME||project.slug%`,
37
50
  ssl: `%?project.env.DB_SSL::bool%`,
51
+ pool: {
52
+ maxConnections: '%?project.env.DB_POOL_MAX_CONNECTIONS%',
53
+ maxConnecting: '%?project.env.DB_POOL_MAX_CONNECTING%',
54
+ maxIdle: '%?project.env.DB_POOL_MAX_IDLE%',
55
+ reconnectIntervalMs: '%?project.env.DB_POOL_RECONNECT_INTERVAL_MS%',
56
+ idleTimeoutMs: '%?project.env.DB_POOL_IDLE_TIMEOUT_MS%',
57
+ acquireTimeoutMs: '%?project.env.DB_POOL_ACQUIRE_TIMEOUT_MS%',
58
+ maxUses: '%?project.env.DB_POOL_MAX_USES%',
59
+ maxAgeMs: '%?project.env.DB_POOL_MAX_AGE_MS%',
60
+ },
38
61
  },
39
62
  },
40
63
  server: {
package/src/index.ts CHANGED
@@ -1,9 +1,22 @@
1
1
  import { MasterContainerFactory, MasterContainerArgs } from './MasterContainer'
2
2
  import { ProjectConfig } from '@contember/engine-http'
3
3
  import { readConfig } from './config/config'
4
- import { ProcessType } from './utils'
4
+ import { serverConfigSchema } from './config/configSchema'
5
+ import { TenantConfigResolver } from './config/tenantConfigResolver'
6
+ import { ProjectGroupContainerFactory } from './projectGroup/ProjectGroupContainer'
5
7
 
6
- export { MasterContainerFactory, ProjectConfig, readConfig, ProcessType }
8
+ export * from './utils/serverStartup'
9
+ export * from './utils/serverTermination'
10
+ export * from './utils/sentry'
11
+ export * from './MasterContainer'
12
+
13
+ export {
14
+ ProjectConfig,
15
+ readConfig,
16
+ serverConfigSchema,
17
+ TenantConfigResolver,
18
+ ProjectGroupContainerFactory,
19
+ }
7
20
 
8
21
  export const createContainer = (args: MasterContainerArgs) => {
9
22
  return new MasterContainerFactory().create(args)
@@ -57,7 +57,7 @@ export class ProjectContainerFactory {
57
57
  .addService('project', () =>
58
58
  project)
59
59
  .addService('connection', ({ project }) =>
60
- new Connection(project.db, { timing: true }))
60
+ Connection.create(project.db, { timing: true }))
61
61
  .addService('graphQlSchemaBuilderFactory', () =>
62
62
  new GraphQlSchemaBuilderFactory())
63
63
  .addService('permissionsByIdentityFactory', ({}) =>
@@ -21,20 +21,8 @@ export class ProjectContainerResolver {
21
21
  private readonly tenantConfig: TenantConfig,
22
22
  ) {}
23
23
 
24
- public async getAllProjectContainers(): Promise<ProjectContainer[]> {
25
- const projects = await this.projectManager.getProjects(this.tenantDatabase)
26
- return await Promise.all(
27
- projects.map(async it => {
28
- const container = await this.getProjectContainer(it.slug)
29
- if (!container) {
30
- throw new Error('should not happen')
31
- }
32
- return container
33
- }),
34
- )
35
- }
36
24
 
37
- public async getProjectContainer(slug: string, alias: boolean = false): Promise<ProjectContainer | undefined> {
25
+ public async getProjectContainer(slug: string, { alias = false, logger }: {alias?: boolean; logger?: Logger} = {}): Promise<ProjectContainer | undefined> {
38
26
  const realSlug = this.projectContainers.resolveAlias(slug)
39
27
  if (realSlug) {
40
28
  slug = realSlug
@@ -55,14 +43,14 @@ export class ProjectContainerResolver {
55
43
  if (!project) {
56
44
  return undefined
57
45
  }
58
- const container = await this.createProjectContainer(project)
46
+ const container = await this.createProjectContainer(project, logger)
59
47
  if (slug !== project.slug) {
60
48
  this.projectContainers.setAlias(project.slug, slug)
61
49
  }
62
50
  return container
63
51
  }
64
52
 
65
- public async createProjectContainer(project: ProjectWithSecrets): Promise<ProjectContainer> {
53
+ public async createProjectContainer(project: ProjectWithSecrets, logger?: Logger): Promise<ProjectContainer> {
66
54
  const projectConfig = this.projectConfigResolver(project.slug, project.config, project.secrets, this.tenantConfig)
67
55
  return (await this.projectContainers.fetchContainer(project.slug, async slug => {
68
56
  const projectContainer = this.projectContainerFactory.createContainer({
@@ -71,8 +59,7 @@ export class ProjectContainerResolver {
71
59
  await this.systemProjectInitializer.initialize(
72
60
  projectContainer.systemDatabaseContextFactory,
73
61
  projectContainer.project,
74
- // eslint-disable-next-line no-console
75
- new Logger(console.log),
62
+ logger ?? new Logger(() => null),
76
63
  )
77
64
  const cleanups = this.onCreate.map(it => it(projectContainer) || (() => null))
78
65
  return {