@contember/engine-server 1.2.0-alpha.8 → 1.2.0-beta.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.
- package/dist/src/MasterContainer.d.ts +6 -6
- package/dist/src/MasterContainer.d.ts.map +1 -1
- package/dist/src/MasterContainer.js +10 -13
- package/dist/src/MasterContainer.js.map +1 -1
- package/dist/src/bootstrap/Initializer.d.ts.map +1 -1
- package/dist/src/bootstrap/Initializer.js +3 -15
- package/dist/src/bootstrap/Initializer.js.map +1 -1
- package/dist/src/config/configSchema.d.ts +81 -0
- package/dist/src/config/configSchema.d.ts.map +1 -1
- package/dist/src/config/configSchema.js +16 -2
- package/dist/src/config/configSchema.js.map +1 -1
- package/dist/src/config/configTemplate.d.ts.map +1 -1
- package/dist/src/config/configTemplate.js +29 -24
- package/dist/src/config/configTemplate.js.map +1 -1
- package/dist/src/project/ProjectContainer.d.ts +8 -2
- package/dist/src/project/ProjectContainer.d.ts.map +1 -1
- package/dist/src/project/ProjectContainer.js +20 -5
- package/dist/src/project/ProjectContainer.js.map +1 -1
- package/dist/src/project/ProjectContainerResolver.d.ts +2 -3
- package/dist/src/project/ProjectContainerResolver.d.ts.map +1 -1
- package/dist/src/project/ProjectContainerResolver.js +3 -4
- package/dist/src/project/ProjectContainerResolver.js.map +1 -1
- package/dist/src/project/ProjectInitializer.d.ts +3 -2
- package/dist/src/project/ProjectInitializer.d.ts.map +1 -1
- package/dist/src/project/ProjectInitializer.js +3 -3
- package/dist/src/project/ProjectInitializer.js.map +1 -1
- package/dist/src/project/ProjectSchemaResolver.d.ts +2 -7
- package/dist/src/project/ProjectSchemaResolver.d.ts.map +1 -1
- package/dist/src/project/ProjectSchemaResolver.js +2 -16
- package/dist/src/project/ProjectSchemaResolver.js.map +1 -1
- package/dist/src/projectGroup/ProjectGroupContainer.d.ts +3 -1
- package/dist/src/projectGroup/ProjectGroupContainer.d.ts.map +1 -1
- package/dist/src/projectGroup/ProjectGroupContainer.js +10 -8
- package/dist/src/projectGroup/ProjectGroupContainer.js.map +1 -1
- package/dist/src/start.js +16 -13
- package/dist/src/start.js.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/utils/sentry.d.ts +8 -9
- package/dist/src/utils/sentry.d.ts.map +1 -1
- package/dist/src/utils/sentry.js +44 -29
- package/dist/src/utils/sentry.js.map +1 -1
- package/dist/src/utils/serverStartup.d.ts +3 -1
- package/dist/src/utils/serverStartup.d.ts.map +1 -1
- package/dist/src/utils/serverStartup.js +49 -12
- package/dist/src/utils/serverStartup.js.map +1 -1
- package/dist/src/utils/serverTermination.d.ts +2 -1
- package/dist/src/utils/serverTermination.d.ts.map +1 -1
- package/dist/src/utils/serverTermination.js +4 -6
- package/dist/src/utils/serverTermination.js.map +1 -1
- package/dist/tests/cases/configResolver.test.d.ts +2 -0
- package/dist/tests/cases/configResolver.test.d.ts.map +1 -0
- package/dist/tests/cases/configResolver.test.js +67 -0
- package/dist/tests/cases/configResolver.test.js.map +1 -0
- package/dist/tests/src/tester.js +2 -2
- package/dist/tests/src/tester.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/package.json +19 -22
- package/src/MasterContainer.ts +17 -15
- package/src/bootstrap/Initializer.ts +3 -16
- package/src/config/configSchema.ts +44 -21
- package/src/config/configTemplate.ts +29 -24
- package/src/project/ProjectContainer.ts +23 -4
- package/src/project/ProjectContainerResolver.ts +4 -4
- package/src/project/ProjectInitializer.ts +4 -3
- package/src/project/ProjectSchemaResolver.ts +1 -18
- package/src/projectGroup/ProjectGroupContainer.ts +12 -7
- package/src/start.ts +24 -17
- package/src/tsconfig.json +6 -15
- package/src/utils/sentry.ts +45 -35
- package/src/utils/serverStartup.ts +46 -10
- package/src/utils/serverTermination.ts +5 -6
- package/tests/cases/configResolver.test.ts +67 -0
- package/tests/src/tester.ts +1 -1
package/package.json
CHANGED
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/engine-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.2.0-beta.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"typings": "dist/src/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
+
"test": "vitest tests/cases",
|
|
8
9
|
"test-e2e": "vitest --no-threads tests/e2e"
|
|
9
10
|
},
|
|
10
11
|
"dependencies": {
|
|
11
|
-
"@contember/
|
|
12
|
-
"@contember/
|
|
13
|
-
"@contember/
|
|
14
|
-
"@contember/
|
|
15
|
-
"@contember/
|
|
16
|
-
"@contember/
|
|
17
|
-
"@contember/engine-
|
|
18
|
-
"@contember/engine-
|
|
19
|
-
"@contember/engine-
|
|
20
|
-
"@contember/engine-
|
|
21
|
-
"@contember/engine-
|
|
22
|
-
"@contember/engine-
|
|
23
|
-
"@contember/
|
|
24
|
-
"@contember/
|
|
25
|
-
"@contember/schema": "^
|
|
26
|
-
"@contember/schema-definition": "^v1.2.0-alpha.8",
|
|
27
|
-
"@contember/schema-migrations": "^v1.2.0-alpha.8",
|
|
28
|
-
"@contember/schema-utils": "^v1.2.0-alpha.8",
|
|
12
|
+
"@contember/config-loader": "^1.2.0-beta.1",
|
|
13
|
+
"@contember/database": "^1.2.0-beta.1",
|
|
14
|
+
"@contember/dic": "^1.2.0-beta.1",
|
|
15
|
+
"@contember/typesafe": "^1.2.0-beta.1",
|
|
16
|
+
"@contember/engine-content-api": "^1.2.0-beta.1",
|
|
17
|
+
"@contember/engine-common": "^1.2.0-beta.1",
|
|
18
|
+
"@contember/engine-http": "^1.2.0-beta.1",
|
|
19
|
+
"@contember/engine-plugins": "^1.2.0-beta.1",
|
|
20
|
+
"@contember/engine-s3-plugin": "^1.2.0-beta.1",
|
|
21
|
+
"@contember/engine-system-api": "^1.2.0-beta.1",
|
|
22
|
+
"@contember/engine-tenant-api": "^1.2.0-beta.1",
|
|
23
|
+
"@contember/engine-vimeo-plugin": "^1.2.0-beta.1",
|
|
24
|
+
"@contember/logger": "^1.2.0-beta.1",
|
|
25
|
+
"@contember/schema": "^1.2.0-beta.1",
|
|
26
|
+
"@contember/schema-migrations": "^1.2.0-beta.1",
|
|
29
27
|
"@koa/cors": "^3.1.0",
|
|
30
28
|
"@sentry/node": "^7.1.1",
|
|
31
29
|
"graphql": "^16.5.0",
|
|
@@ -33,13 +31,12 @@
|
|
|
33
31
|
"koa-bodyparser": "^4.3.0",
|
|
34
32
|
"koa-compress": "^5.0.1",
|
|
35
33
|
"pg": "^8.5.0",
|
|
36
|
-
"prom-client": "^12",
|
|
37
34
|
"uuid": "^8.3.1"
|
|
38
35
|
},
|
|
39
36
|
"devDependencies": {
|
|
40
|
-
"@contember/engine-api-tester": "^
|
|
37
|
+
"@contember/engine-api-tester": "^1.2.0-beta.1",
|
|
41
38
|
"@types/koa-compress": "^4.0.1",
|
|
42
|
-
"@types/node": "^
|
|
39
|
+
"@types/node": "^18",
|
|
43
40
|
"@types/supertest": "^2.0.8",
|
|
44
41
|
"supertest": "^6.0.1"
|
|
45
42
|
}
|
package/src/MasterContainer.ts
CHANGED
|
@@ -2,7 +2,6 @@ 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 { logSentryError } from './utils'
|
|
6
5
|
import { ModificationHandlerFactory } from '@contember/schema-migrations'
|
|
7
6
|
import { Initializer } from './bootstrap'
|
|
8
7
|
import { Plugin } from '@contember/engine-plugins'
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
ContentQueryHandlerFactory,
|
|
14
13
|
ContentSchemaTransferMappingFactory,
|
|
15
14
|
createHomepageMiddleware,
|
|
15
|
+
createLoggerMiddleware,
|
|
16
16
|
createModuleInfoMiddleware,
|
|
17
17
|
createPlaygroundMiddleware,
|
|
18
18
|
createPoweredByHeaderMiddleware,
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
ImportExecutor,
|
|
26
26
|
Koa,
|
|
27
27
|
NotModifiedChecker,
|
|
28
|
+
ProjectGroupResolver as ProjectGroupResolverInterface,
|
|
28
29
|
Providers,
|
|
29
30
|
route,
|
|
30
31
|
SystemApiMiddlewareFactory,
|
|
@@ -43,8 +44,7 @@ import { TenantConfigResolver } from './config/tenantConfigResolver'
|
|
|
43
44
|
import { ProjectGroupContainerFactory } from './projectGroup/ProjectGroupContainer'
|
|
44
45
|
import corsMiddleware from '@koa/cors'
|
|
45
46
|
import { ProjectGroupResolver } from './projectGroup/ProjectGroupResolver'
|
|
46
|
-
import {
|
|
47
|
-
import { Logger } from '@contember/engine-common'
|
|
47
|
+
import { Logger } from '@contember/logger'
|
|
48
48
|
|
|
49
49
|
export interface MasterContainer {
|
|
50
50
|
initializer: Initializer
|
|
@@ -58,6 +58,7 @@ export interface MasterContainerArgs {
|
|
|
58
58
|
projectConfigResolver: ProjectConfigResolver
|
|
59
59
|
tenantConfigResolver: TenantConfigResolver
|
|
60
60
|
plugins: Plugin[]
|
|
61
|
+
logger: Logger
|
|
61
62
|
version?: string
|
|
62
63
|
}
|
|
63
64
|
|
|
@@ -69,6 +70,7 @@ export class MasterContainerFactory {
|
|
|
69
70
|
projectConfigResolver,
|
|
70
71
|
tenantConfigResolver,
|
|
71
72
|
version,
|
|
73
|
+
logger,
|
|
72
74
|
}: MasterContainerArgs) {
|
|
73
75
|
return new Builder({})
|
|
74
76
|
.addService('serverConfig', () =>
|
|
@@ -94,11 +96,13 @@ export class MasterContainerFactory {
|
|
|
94
96
|
.addService('projectContainerFactoryFactory', ({ debugMode, plugins, providers }) =>
|
|
95
97
|
new ProjectContainerFactoryFactory(debugMode, plugins, providers))
|
|
96
98
|
.addService('tenantGraphQLHandlerFactory', () =>
|
|
97
|
-
new TenantGraphQLHandlerFactory(
|
|
99
|
+
new TenantGraphQLHandlerFactory())
|
|
98
100
|
.addService('systemGraphQLHandlerFactory', ({ debugMode }) =>
|
|
99
|
-
new SystemGraphQLHandlerFactory(
|
|
100
|
-
.addService('
|
|
101
|
-
|
|
101
|
+
new SystemGraphQLHandlerFactory(debugMode))
|
|
102
|
+
.addService('logger', () =>
|
|
103
|
+
logger)
|
|
104
|
+
.addService('projectGroupContainerFactory', ({ debugMode, providers, systemContainerFactory, tenantContainerFactory, projectContainerFactoryFactory, projectConfigResolver, tenantGraphQLHandlerFactory, systemGraphQLHandlerFactory, logger }) =>
|
|
105
|
+
new ProjectGroupContainerFactory(debugMode, providers, systemContainerFactory, tenantContainerFactory, projectContainerFactoryFactory, projectConfigResolver, tenantGraphQLHandlerFactory, systemGraphQLHandlerFactory, logger))
|
|
102
106
|
.addService('projectGroupContainer', ({ tenantConfigResolver, projectGroupContainerFactory }) =>
|
|
103
107
|
projectGroupContainerFactory.create({ slug: undefined, config: tenantConfigResolver(undefined, {}) }))
|
|
104
108
|
.addService('httpErrorMiddlewareFactory', ({ debugMode }) =>
|
|
@@ -110,7 +114,7 @@ export class MasterContainerFactory {
|
|
|
110
114
|
.addService('contentGraphqlContextFactory', ({ providers }) =>
|
|
111
115
|
new ContentGraphQLContextFactory(providers))
|
|
112
116
|
.addService('contentQueryHandlerFactory', ({ debugMode }) =>
|
|
113
|
-
new ContentQueryHandlerFactory(debugMode
|
|
117
|
+
new ContentQueryHandlerFactory(debugMode))
|
|
114
118
|
.addService('contentApiMiddlewareFactory', ({ projectGroupResolver, notModifiedChecker, contentGraphqlContextFactory, contentQueryHandlerFactory }) =>
|
|
115
119
|
new ContentApiMiddlewareFactory(projectGroupResolver, notModifiedChecker, contentGraphqlContextFactory, contentQueryHandlerFactory))
|
|
116
120
|
.addService('tenantGraphQLContextFactory', () =>
|
|
@@ -121,22 +125,19 @@ export class MasterContainerFactory {
|
|
|
121
125
|
new SystemGraphQLContextFactory())
|
|
122
126
|
.addService('systemApiMiddlewareFactory', ({ debugMode, projectGroupResolver, systemGraphQLContextFactory }) =>
|
|
123
127
|
new SystemApiMiddlewareFactory(debugMode, projectGroupResolver, systemGraphQLContextFactory))
|
|
124
|
-
.addService('logger', () =>
|
|
125
|
-
// eslint-disable-next-line no-console
|
|
126
|
-
new Logger(console.log))
|
|
127
128
|
.addService('contentSchemaTransferMappingFactory', () =>
|
|
128
129
|
new ContentSchemaTransferMappingFactory())
|
|
129
130
|
.addService('systemSchemaTransferMappingFactory', () =>
|
|
130
131
|
new SystemSchemaTransferMappingFactory())
|
|
131
|
-
.addService('importExecutor', ({ contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory
|
|
132
|
-
new ImportExecutor(contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory
|
|
132
|
+
.addService('importExecutor', ({ contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory }) =>
|
|
133
|
+
new ImportExecutor(contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory))
|
|
133
134
|
.addService('exportExecutor', ({ contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory }) =>
|
|
134
135
|
new ExportExecutor(contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory))
|
|
135
136
|
.addService('importApiMiddlewareFactory', ({ projectGroupResolver, importExecutor }) =>
|
|
136
137
|
new ImportApiMiddlewareFactory(projectGroupResolver, importExecutor))
|
|
137
138
|
.addService('exportApiMiddlewareFactory', ({ projectGroupResolver, exportExecutor }) =>
|
|
138
139
|
new ExportApiMiddlewareFactory(projectGroupResolver, exportExecutor))
|
|
139
|
-
.addService('koaMiddlewares', ({ contentApiMiddlewareFactory, tenantApiMiddlewareFactory, systemApiMiddlewareFactory, importApiMiddlewareFactory, exportApiMiddlewareFactory, httpErrorMiddlewareFactory, debugMode, version, serverConfig }) =>
|
|
140
|
+
.addService('koaMiddlewares', ({ contentApiMiddlewareFactory, tenantApiMiddlewareFactory, systemApiMiddlewareFactory, importApiMiddlewareFactory, exportApiMiddlewareFactory, httpErrorMiddlewareFactory, debugMode, version, serverConfig, logger }) =>
|
|
140
141
|
compose([
|
|
141
142
|
koaCompress({
|
|
142
143
|
br: false,
|
|
@@ -145,8 +146,9 @@ export class MasterContainerFactory {
|
|
|
145
146
|
jsonLimit: serverConfig.http.requestBodySize || '1mb',
|
|
146
147
|
}),
|
|
147
148
|
createPoweredByHeaderMiddleware(debugMode, version ?? 'unknown'),
|
|
149
|
+
createLoggerMiddleware(logger),
|
|
150
|
+
createTimerMiddleware({ debugMode }),
|
|
148
151
|
httpErrorMiddlewareFactory.create(),
|
|
149
|
-
createTimerMiddleware(),
|
|
150
152
|
route('/playground$', createPlaygroundMiddleware()),
|
|
151
153
|
createHomepageMiddleware(),
|
|
152
154
|
corsMiddleware(),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Logger } from '@contember/engine-common'
|
|
2
1
|
import { ProjectGroupContainer } from '@contember/engine-http'
|
|
3
2
|
|
|
4
3
|
export class Initializer {
|
|
@@ -7,34 +6,22 @@ export class Initializer {
|
|
|
7
6
|
) {}
|
|
8
7
|
|
|
9
8
|
public async initialize(): Promise<string[]> {
|
|
10
|
-
// eslint-disable-next-line no-console
|
|
11
|
-
const logger = new Logger(console.log)
|
|
12
|
-
logger.group('\nInitializing tenant database')
|
|
13
|
-
// todo
|
|
14
9
|
const groupContainer = await this.projectGroupContainer
|
|
15
|
-
|
|
10
|
+
const tenantMigrationsLogger = groupContainer.logger.child()
|
|
16
11
|
const tenantContainer = groupContainer.tenantContainer
|
|
17
|
-
await tenantContainer.migrationsRunner.run(
|
|
18
|
-
logger.groupEnd()
|
|
12
|
+
await tenantContainer.migrationsRunner.run(tenantMigrationsLogger)
|
|
19
13
|
|
|
20
14
|
const projects: string[] = []
|
|
21
15
|
|
|
22
16
|
const tenantProjects = await tenantContainer.projectManager.getProjects(tenantContainer.databaseContext)
|
|
23
17
|
for (const { slug: projectSlug } of tenantProjects) {
|
|
24
|
-
|
|
25
|
-
const projectContainer = await groupContainer.projectContainerResolver.getProjectContainer(projectSlug, {
|
|
26
|
-
alias: false,
|
|
27
|
-
logger,
|
|
28
|
-
})
|
|
18
|
+
const projectContainer = await groupContainer.projectContainerResolver.getProjectContainer(projectSlug, { alias: false })
|
|
29
19
|
if (!projectContainer) {
|
|
30
20
|
throw new Error()
|
|
31
21
|
}
|
|
32
22
|
const project = projectContainer.project
|
|
33
23
|
projects.push(project.slug)
|
|
34
|
-
logger.groupEnd()
|
|
35
24
|
}
|
|
36
|
-
// eslint-disable-next-line no-console
|
|
37
|
-
console.log('')
|
|
38
25
|
return projects
|
|
39
26
|
}
|
|
40
27
|
}
|
|
@@ -3,29 +3,52 @@ import { MailerOptions } from '@contember/engine-tenant-api'
|
|
|
3
3
|
import { upperCaseFirst } from '../utils'
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
Typesafe.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
const dbConfigRequired = {
|
|
7
|
+
host: Typesafe.string,
|
|
8
|
+
port: Typesafe.number,
|
|
9
|
+
user: Typesafe.string,
|
|
10
|
+
password: Typesafe.string,
|
|
11
|
+
database: Typesafe.string,
|
|
12
|
+
}
|
|
13
|
+
const dbConfigOptional = {
|
|
14
|
+
ssl: Typesafe.boolean,
|
|
15
|
+
queryTimeoutMs: Typesafe.number,
|
|
16
|
+
statementTimeoutMs: Typesafe.number,
|
|
17
|
+
connectionTimeoutMs: Typesafe.number,
|
|
18
|
+
pool: Typesafe.partial({
|
|
19
|
+
maxConnections: Typesafe.number,
|
|
20
|
+
maxConnecting: Typesafe.number,
|
|
21
|
+
maxIdle: Typesafe.number,
|
|
22
|
+
reconnectIntervalMs: Typesafe.number,
|
|
23
|
+
rateLimitCount: Typesafe.number,
|
|
24
|
+
rateLimitPeriodMs: Typesafe.number,
|
|
25
|
+
idleTimeoutMs: Typesafe.number,
|
|
26
|
+
acquireTimeoutMs: Typesafe.number,
|
|
27
|
+
maxUses: Typesafe.number,
|
|
28
|
+
maxAgeMs: Typesafe.number,
|
|
13
29
|
}),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const dbConfigSchemaInner = Typesafe.intersection(
|
|
33
|
+
Typesafe.object(dbConfigRequired),
|
|
34
|
+
Typesafe.partial(dbConfigOptional),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
const readDbSchema = Typesafe.intersection(
|
|
38
|
+
Typesafe.partial(dbConfigRequired),
|
|
39
|
+
Typesafe.partial(dbConfigOptional),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
export const dbConfigSchema = Typesafe.intersection(
|
|
43
|
+
dbConfigSchemaInner,
|
|
14
44
|
Typesafe.partial({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
}),
|
|
45
|
+
read: (val: unknown) => {
|
|
46
|
+
const readDb = readDbSchema(val)
|
|
47
|
+
if ('host' in readDb) {
|
|
48
|
+
return readDb
|
|
49
|
+
}
|
|
50
|
+
return undefined
|
|
51
|
+
},
|
|
29
52
|
}),
|
|
30
53
|
)
|
|
31
54
|
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
const createDbConfigTemplate = (prefix: string) => {
|
|
2
|
+
return {
|
|
3
|
+
ssl: `%?${prefix}_SSL::bool%`,
|
|
4
|
+
queryTimeoutMs: `%?${prefix}_QUERY_TIMEOUT_MS::number%`,
|
|
5
|
+
statementTimeoutMs: `%?${prefix}_STATEMENT_TIMEOUT_MS::number%`,
|
|
6
|
+
connectionTimeoutMs: `%?${prefix}_CONNECTION_TIMEOUT_MS::number%`,
|
|
7
|
+
pool: {
|
|
8
|
+
maxConnections: `%?${prefix}_POOL_MAX_CONNECTIONS::number%`,
|
|
9
|
+
maxConnecting: `%?${prefix}_POOL_MAX_CONNECTING::number%`,
|
|
10
|
+
maxIdle: `%?${prefix}_POOL_MAX_IDLE::number%`,
|
|
11
|
+
reconnectIntervalMs: `%?${prefix}_POOL_RECONNECT_INTERVAL_MS::number%`,
|
|
12
|
+
idleTimeoutMs: `%?${prefix}_POOL_IDLE_TIMEOUT_MS::number%`,
|
|
13
|
+
acquireTimeoutMs: `%?${prefix}_POOL_ACQUIRE_TIMEOUT_MS::number%`,
|
|
14
|
+
maxUses: `%?${prefix}_POOL_MAX_USES::number%`,
|
|
15
|
+
maxAgeMs: `%?${prefix}_POOL_MAX_AGE_MS::number%`,
|
|
16
|
+
rateLimitCount: `%?${prefix}_POOL_RATE_LIMIT_COUNT::number%`,
|
|
17
|
+
rateLimitPeriodMs: `%?${prefix}_POOL_RATE_LIMIT_PERIOD_MS::number%`,
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
}
|
|
1
21
|
export const configTemplate: any = {
|
|
2
22
|
tenant: {
|
|
3
23
|
db: {
|
|
@@ -6,20 +26,7 @@ export const configTemplate: any = {
|
|
|
6
26
|
user: `%tenant.env.DB_USER%`,
|
|
7
27
|
password: `%tenant.env.DB_PASSWORD%`,
|
|
8
28
|
database: `%tenant.env.DB_NAME%`,
|
|
9
|
-
|
|
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
|
-
},
|
|
29
|
+
...createDbConfigTemplate('tenant.env.DB'),
|
|
23
30
|
},
|
|
24
31
|
mailer: {
|
|
25
32
|
from: '%?tenant.env.MAILER_FROM%',
|
|
@@ -47,16 +54,14 @@ export const configTemplate: any = {
|
|
|
47
54
|
user: `%?project.env.DB_USER%`,
|
|
48
55
|
password: `%?project.secret.db.password||project.env.DB_PASSWORD%`,
|
|
49
56
|
database: `%?project.env.DB_NAME||project.slug%`,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
maxUses: '%?project.env.DB_POOL_MAX_USES%',
|
|
59
|
-
maxAgeMs: '%?project.env.DB_POOL_MAX_AGE_MS%',
|
|
57
|
+
...createDbConfigTemplate('project.env.DB'),
|
|
58
|
+
read: {
|
|
59
|
+
host: `%?project.env.DB_READ_HOST%`,
|
|
60
|
+
port: `%?project.env.DB_READ_PORT::number%`,
|
|
61
|
+
user: `%?project.env.DB_READ_USER%`,
|
|
62
|
+
password: `%?project.secret.db.read.password||project.env.DB_READ_PASSWORD%`,
|
|
63
|
+
database: `%?project.env.DB_READ_NAME%`,
|
|
64
|
+
...createDbConfigTemplate('project.env.DB_READ'),
|
|
60
65
|
},
|
|
61
66
|
},
|
|
62
67
|
},
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ProjectContainer,
|
|
11
11
|
Providers,
|
|
12
12
|
} from '@contember/engine-http'
|
|
13
|
+
import { Logger } from '@contember/logger'
|
|
13
14
|
|
|
14
15
|
export class ProjectContainerFactoryFactory {
|
|
15
16
|
constructor(
|
|
@@ -19,8 +20,8 @@ export class ProjectContainerFactoryFactory {
|
|
|
19
20
|
) {
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
create(schemaVersionBuilder: SchemaVersionBuilder): ProjectContainerFactory {
|
|
23
|
-
return new ProjectContainerFactory(this.debug, this.plugins, schemaVersionBuilder, this.providers)
|
|
23
|
+
create(schemaVersionBuilder: SchemaVersionBuilder, logger: Logger): ProjectContainerFactory {
|
|
24
|
+
return new ProjectContainerFactory(this.debug, this.plugins, schemaVersionBuilder, this.providers, logger)
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -34,6 +35,7 @@ export class ProjectContainerFactory {
|
|
|
34
35
|
private readonly plugins: Plugin[],
|
|
35
36
|
private readonly schemaVersionBuilder: SchemaVersionBuilder,
|
|
36
37
|
private readonly providers: Providers,
|
|
38
|
+
private readonly logger: Logger,
|
|
37
39
|
) {}
|
|
38
40
|
|
|
39
41
|
public createContainer(args: ProjectContainerFactoryArgs): ProjectContainer {
|
|
@@ -42,9 +44,11 @@ export class ProjectContainerFactory {
|
|
|
42
44
|
.pick(
|
|
43
45
|
'project',
|
|
44
46
|
'connection',
|
|
47
|
+
'readConnection',
|
|
45
48
|
'systemDatabaseContextFactory',
|
|
46
49
|
'contentSchemaResolver',
|
|
47
50
|
'graphQlSchemaFactory',
|
|
51
|
+
'logger',
|
|
48
52
|
)
|
|
49
53
|
}
|
|
50
54
|
|
|
@@ -54,10 +58,25 @@ export class ProjectContainerFactory {
|
|
|
54
58
|
this.providers)
|
|
55
59
|
.addService('schemaVersionBuilder', () =>
|
|
56
60
|
this.schemaVersionBuilder)
|
|
61
|
+
.addService('logger', () =>
|
|
62
|
+
this.logger.child({ project: project.slug }))
|
|
57
63
|
.addService('project', () =>
|
|
58
64
|
project)
|
|
59
|
-
.addService('connection', ({ project }) =>
|
|
60
|
-
Connection.create(project.db))
|
|
65
|
+
.addService('connection', ({ project, logger }) =>
|
|
66
|
+
Connection.create(project.db, err => logger.error(err)))
|
|
67
|
+
.addService('readConnection', ({ project, logger, connection }) => {
|
|
68
|
+
if (!project.db.read) {
|
|
69
|
+
return connection
|
|
70
|
+
}
|
|
71
|
+
return Connection.create({
|
|
72
|
+
...project.db,
|
|
73
|
+
...project.db.read,
|
|
74
|
+
pool: {
|
|
75
|
+
...project.db.pool,
|
|
76
|
+
...project.db.read.pool,
|
|
77
|
+
},
|
|
78
|
+
}, err => logger.error(err))
|
|
79
|
+
})
|
|
61
80
|
.addService('graphQlSchemaBuilderFactory', () =>
|
|
62
81
|
new GraphQlSchemaBuilderFactory())
|
|
63
82
|
.addService('permissionsByIdentityFactory', ({}) =>
|
|
@@ -3,9 +3,9 @@ import { ProjectContainer } from '@contember/engine-http'
|
|
|
3
3
|
import { DatabaseContext, ProjectManager, ProjectWithSecrets } from '@contember/engine-tenant-api'
|
|
4
4
|
import { ProjectInitializer as SystemProjectInitializer } from '@contember/engine-system-api'
|
|
5
5
|
import { ProjectContainerStore } from './ProjectContainerStore'
|
|
6
|
-
import { Logger } from '@contember/engine-common'
|
|
7
6
|
import { ProjectConfigResolver } from '../config/projectConfigResolver'
|
|
8
7
|
import { TenantConfig } from '../config/config'
|
|
8
|
+
import { Logger } from '@contember/logger'
|
|
9
9
|
|
|
10
10
|
export class ProjectContainerResolver {
|
|
11
11
|
private projectContainers = new ProjectContainerStore()
|
|
@@ -22,7 +22,7 @@ export class ProjectContainerResolver {
|
|
|
22
22
|
) {}
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
public async getProjectContainer(slug: string, { alias = false
|
|
25
|
+
public async getProjectContainer(slug: string, { alias = false }: { alias?: boolean } = {}): Promise<ProjectContainer | undefined> {
|
|
26
26
|
const realSlug = this.projectContainers.resolveAlias(slug)
|
|
27
27
|
if (realSlug) {
|
|
28
28
|
slug = realSlug
|
|
@@ -43,7 +43,7 @@ export class ProjectContainerResolver {
|
|
|
43
43
|
if (!project) {
|
|
44
44
|
return undefined
|
|
45
45
|
}
|
|
46
|
-
const container = await this.createProjectContainer(project
|
|
46
|
+
const container = await this.createProjectContainer(project)
|
|
47
47
|
if (slug !== project.slug) {
|
|
48
48
|
this.projectContainers.setAlias(project.slug, slug)
|
|
49
49
|
}
|
|
@@ -59,7 +59,7 @@ export class ProjectContainerResolver {
|
|
|
59
59
|
await this.systemProjectInitializer.initialize(
|
|
60
60
|
projectContainer.systemDatabaseContextFactory,
|
|
61
61
|
projectContainer.project,
|
|
62
|
-
logger ??
|
|
62
|
+
logger ?? projectContainer.logger,
|
|
63
63
|
)
|
|
64
64
|
const cleanups = this.onCreate.map(it => it(projectContainer) || (() => null))
|
|
65
65
|
return {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ProjectInitializer as ProjectInitializerInterface, ProjectWithSecrets } from '@contember/engine-tenant-api'
|
|
2
2
|
import { ProjectContainerResolver } from './ProjectContainerResolver'
|
|
3
|
+
import { Logger } from '@contember/logger'
|
|
3
4
|
|
|
4
5
|
export class ProjectInitializer implements ProjectInitializerInterface {
|
|
5
6
|
constructor(
|
|
6
7
|
private readonly projectContainerResolver: ProjectContainerResolver,
|
|
7
8
|
) {}
|
|
8
9
|
|
|
9
|
-
async initializeProject(project: ProjectWithSecrets) {
|
|
10
|
+
async initializeProject(project: ProjectWithSecrets, logger: Logger) {
|
|
10
11
|
await this.projectContainerResolver.createProjectContainer(project)
|
|
11
12
|
}
|
|
12
13
|
}
|
|
@@ -18,10 +19,10 @@ export class ProjectInitializerProxy implements ProjectInitializerInterface {
|
|
|
18
19
|
this.initializer = initializer
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
initializeProject(project: ProjectWithSecrets) {
|
|
22
|
+
initializeProject(project: ProjectWithSecrets, logger: Logger) {
|
|
22
23
|
if (!this.initializer) {
|
|
23
24
|
throw new Error('Initializer is not set')
|
|
24
25
|
}
|
|
25
|
-
return this.initializer.initializeProject(project)
|
|
26
|
+
return this.initializer.initializeProject(project, logger)
|
|
26
27
|
}
|
|
27
28
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { ProjectSchemaResolver as ProjectSchemaResolverInterface } from '@contember/engine-tenant-api'
|
|
2
|
-
import { SchemaVersionBuilder, VersionedSchema } from '@contember/engine-system-api'
|
|
3
2
|
import { ProjectContainerResolver } from '@contember/engine-http'
|
|
4
3
|
import { Schema } from '@contember/schema'
|
|
5
4
|
|
|
6
5
|
export class ProjectSchemaResolver implements ProjectSchemaResolverInterface {
|
|
7
|
-
private schemaCache = new Map<string, VersionedSchema>()
|
|
8
|
-
|
|
9
6
|
constructor(
|
|
10
7
|
private readonly projectContainerResolver: ProjectContainerResolver,
|
|
11
|
-
private readonly schemaVersionBuilder: SchemaVersionBuilder,
|
|
12
8
|
) {}
|
|
13
9
|
|
|
14
10
|
async getSchema(slug: string) {
|
|
@@ -17,16 +13,7 @@ export class ProjectSchemaResolver implements ProjectSchemaResolverInterface {
|
|
|
17
13
|
return undefined
|
|
18
14
|
}
|
|
19
15
|
const db = container.systemDatabaseContextFactory.create()
|
|
20
|
-
|
|
21
|
-
const newSchema = await this.schemaVersionBuilder.buildSchema(db, cachedSchema)
|
|
22
|
-
if (cachedSchema !== newSchema) {
|
|
23
|
-
this.schemaCache.set(slug, newSchema)
|
|
24
|
-
}
|
|
25
|
-
return newSchema
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
clearCache() {
|
|
29
|
-
this.schemaCache.clear()
|
|
16
|
+
return container.contentSchemaResolver.getSchema(db)
|
|
30
17
|
}
|
|
31
18
|
}
|
|
32
19
|
|
|
@@ -43,8 +30,4 @@ export class ProjectSchemaResolverProxy implements ProjectSchemaResolverInterfac
|
|
|
43
30
|
}
|
|
44
31
|
return this.resolver.getSchema(projectSlug)
|
|
45
32
|
}
|
|
46
|
-
|
|
47
|
-
clearCache() {
|
|
48
|
-
this.resolver?.clearCache()
|
|
49
|
-
}
|
|
50
33
|
}
|
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
} from '../project'
|
|
23
23
|
import { SystemContainerFactory } from '@contember/engine-system-api'
|
|
24
24
|
import { ProjectConfigResolver } from '../config/projectConfigResolver'
|
|
25
|
-
import { createSecretKey } from 'crypto'
|
|
25
|
+
import { createSecretKey } from 'node:crypto'
|
|
26
|
+
import { Logger } from '@contember/logger'
|
|
26
27
|
|
|
27
28
|
interface ProjectGroupContainerFactoryArgs
|
|
28
29
|
{
|
|
@@ -40,18 +41,21 @@ export class ProjectGroupContainerFactory {
|
|
|
40
41
|
private readonly projectConfigResolver: ProjectConfigResolver,
|
|
41
42
|
private readonly tenantGraphQLHandlerFactory: TenantGraphQLHandlerFactory,
|
|
42
43
|
private readonly systemGraphQLHandlerFactory: SystemGraphQLHandlerFactory,
|
|
44
|
+
private readonly logger: Logger,
|
|
43
45
|
) {}
|
|
44
46
|
|
|
45
47
|
public create({ config, slug }: ProjectGroupContainerFactoryArgs): ProjectGroupContainer {
|
|
46
48
|
return new Builder({})
|
|
47
49
|
.addService('slug', () =>
|
|
48
50
|
slug)
|
|
51
|
+
.addService('logger', ({ slug }) =>
|
|
52
|
+
this.logger.child({ projectGroup: slug }))
|
|
49
53
|
.addService('providers', () =>
|
|
50
54
|
this.providers)
|
|
51
55
|
.addService('tenantDbCredentials', () =>
|
|
52
56
|
config.db)
|
|
53
|
-
.addService('tenantConnection', ({ tenantDbCredentials }): Connection.ConnectionType =>
|
|
54
|
-
Connection.create(tenantDbCredentials))
|
|
57
|
+
.addService('tenantConnection', ({ tenantDbCredentials, logger }): Connection.ConnectionType =>
|
|
58
|
+
Connection.create(tenantDbCredentials, err => logger.error(err)))
|
|
55
59
|
.addService('projectSchemaResolver', () =>
|
|
56
60
|
new ProjectSchemaResolverProxy())
|
|
57
61
|
.addService('projectInitializer', () =>
|
|
@@ -83,8 +87,8 @@ export class ProjectGroupContainerFactory {
|
|
|
83
87
|
this.systemContainerFactory.create({ identityFetcher }))
|
|
84
88
|
.addService('schemaVersionBuilder', ({ systemContainer }) =>
|
|
85
89
|
systemContainer.schemaVersionBuilder)
|
|
86
|
-
.addService('projectContainerFactory', ({ schemaVersionBuilder }) =>
|
|
87
|
-
this.projectContainerFactoryFactory.create(schemaVersionBuilder))
|
|
90
|
+
.addService('projectContainerFactory', ({ schemaVersionBuilder, logger }) =>
|
|
91
|
+
this.projectContainerFactoryFactory.create(schemaVersionBuilder, logger))
|
|
88
92
|
.addService('tenantProjectManager', ({ tenantContainer }) =>
|
|
89
93
|
tenantContainer.projectManager)
|
|
90
94
|
.addService('projectContainerResolver', ({ projectContainerFactory, tenantProjectManager, systemContainer, tenantContainer }) =>
|
|
@@ -97,8 +101,8 @@ export class ProjectGroupContainerFactory {
|
|
|
97
101
|
config,
|
|
98
102
|
))
|
|
99
103
|
|
|
100
|
-
.setupService('projectSchemaResolver', (it, { projectContainerResolver
|
|
101
|
-
it.setResolver(new ProjectSchemaResolver(projectContainerResolver
|
|
104
|
+
.setupService('projectSchemaResolver', (it, { projectContainerResolver }) => {
|
|
105
|
+
it.setResolver(new ProjectSchemaResolver(projectContainerResolver))
|
|
102
106
|
})
|
|
103
107
|
.setupService('projectInitializer', (it, { projectContainerResolver }) => {
|
|
104
108
|
it.setInitializer(new ProjectInitializer(projectContainerResolver))
|
|
@@ -124,6 +128,7 @@ export class ProjectGroupContainerFactory {
|
|
|
124
128
|
'projectMembershipResolver',
|
|
125
129
|
'tenantGraphQLHandler',
|
|
126
130
|
'slug',
|
|
131
|
+
'logger',
|
|
127
132
|
)
|
|
128
133
|
}
|
|
129
134
|
}
|