@apolitical/server 4.3.0-pla-471.1 → 4.3.0-pla-471.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apolitical/server",
3
- "version": "4.3.0-pla-471.1",
3
+ "version": "4.3.0-pla-471.3",
4
4
  "description": "Node.js module to encapsulate Apolitical's express server setup",
5
5
  "author": "Apolitical Group Limited <engineering@apolitical.co>",
6
6
  "license": "MIT",
package/src/container.js CHANGED
@@ -56,6 +56,7 @@ const expressService = require('./services/express.service');
56
56
  const healthService = require('./services/health.service');
57
57
  const jwtService = require('./services/jwt.service');
58
58
  const serverService = require('./services/server.service');
59
+ const secretManagerService = require('./services/secret-manager.service');
59
60
  const secretsService = require('./services/secrets.service');
60
61
 
61
62
  // DI container
@@ -116,6 +117,7 @@ container.register({
116
117
  healthService: asFunction(healthService).singleton(),
117
118
  jwtService: asFunction(jwtService).singleton(),
118
119
  serverService: asFunction(serverService).singleton(),
120
+ secretManagerService: asFunction(secretManagerService).singleton(),
119
121
  secretsService: asFunction(secretsService).singleton(),
120
122
  });
121
123
 
package/src/index.js CHANGED
@@ -1,12 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const { resolve } = require('./container');
4
- const { SecretManagerService } = require('./services/secret-manager.service');
5
4
 
6
5
  // OTel must load before the Express server is started
7
6
  resolve('otelLoader')();
8
7
 
9
- const serverService = resolve('serverService');
10
- serverService.SecretManagerService = SecretManagerService;
11
-
12
- module.exports = serverService;
8
+ module.exports = resolve('serverService');
@@ -1,18 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const { SecretManagerServiceClient } = require('@google-cloud/secret-manager');
3
+ module.exports = ({ secretManager, logger }) => {
4
+ let clientPromise = null;
4
5
 
5
- /**
6
- * Thin wrapper around Google Cloud Secret Manager.
7
- *
8
- * Every method is static because the class is consumed before the DI
9
- * container is available (e.g. inside config loading at startup).
10
- * The underlying client is lazily created and reused across all calls.
11
- *
12
- * Aligned with the backend/v2 implementation at:
13
- * backend/v2/libs/externals/gcp/secrets/src/secret-manager.service.ts
14
- */
15
- class SecretManagerService {
16
6
  /**
17
7
  * Derive the secret name prefix from the PLATFORM_BASE_URL subdomain.
18
8
  * - https://apolitical.co → "live"
@@ -21,7 +11,7 @@ class SecretManagerService {
21
11
  * - https://localhost → "tilt" (Local Tilt)
22
12
  * - http://localhost → "pnpm" (Local standalone)
23
13
  */
24
- static getSecretPrefix(useLocal) {
14
+ function getSecretPrefix(useLocal) {
25
15
  const baseURL = String(process.env.PLATFORM_BASE_URL ?? '');
26
16
  try {
27
17
  const hostname = new URL(baseURL).hostname;
@@ -35,14 +25,14 @@ class SecretManagerService {
35
25
  return useLocal ? 'pnpm' : 'beta';
36
26
  }
37
27
 
38
- static async _getClient() {
39
- if (!this._clientPromise) {
40
- this._clientPromise = (async () => {
41
- console.log('[SecretManager] Initialising client.');
42
- return new SecretManagerServiceClient();
28
+ function getClient() {
29
+ if (!clientPromise) {
30
+ clientPromise = (async () => {
31
+ logger.info('[SecretManager] Initialising client.');
32
+ return new secretManager.SecretManagerServiceClient();
43
33
  })();
44
34
  }
45
- return this._clientPromise;
35
+ return clientPromise;
46
36
  }
47
37
 
48
38
  /**
@@ -51,11 +41,11 @@ class SecretManagerService {
51
41
  * The full secret name is built as `{prefix}_{secretBaseName}`, where the
52
42
  * prefix is derived from PLATFORM_BASE_URL (e.g. "beta", "live").
53
43
  */
54
- static async accessSecret(secretBaseName, options) {
55
- const client = await this._getClient();
44
+ async function accessSecret(secretBaseName, options) {
45
+ const client = await getClient();
56
46
  const projectId = process.env.GCP_PROJECT_ID ?? (await client.auth.getProjectId());
57
47
 
58
- const prefix = this.getSecretPrefix(options?.useLocal);
48
+ const prefix = getSecretPrefix(options?.useLocal);
59
49
  const secretName = `${prefix}_${secretBaseName}`;
60
50
  const version = options?.version ?? 'latest';
61
51
  const name = `projects/${projectId}/secrets/${secretName}/versions/${version}`;
@@ -68,6 +58,9 @@ class SecretManagerService {
68
58
 
69
59
  return typeof payload === 'string' ? payload : payload.toString('utf8');
70
60
  }
71
- }
72
61
 
73
- module.exports = { SecretManagerService };
62
+ return {
63
+ getSecretPrefix,
64
+ accessSecret,
65
+ };
66
+ };
@@ -8,6 +8,7 @@ module.exports = ({
8
8
  jwtService,
9
9
  serverError,
10
10
  requestHelper,
11
+ secretManagerService,
11
12
  secretsService,
12
13
  }) => {
13
14
  // Register shutdown to clean up any resources used by the express app
@@ -23,6 +24,7 @@ module.exports = ({
23
24
  authorisation: authorisationMiddleware,
24
25
  },
25
26
  request: requestHelper,
27
+ secretManager: secretManagerService,
26
28
  secrets: secretsService,
27
29
  };
28
30
  };