@abgov/nx-adsp 12.2.1 → 12.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/nx-adsp",
3
- "version": "12.2.1",
3
+ "version": "12.3.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "src/index.js",
6
6
  "description": "Government of Alberta - Nx plugin for ADSP apps.",
@@ -26,12 +26,18 @@ function default_1(host, options) {
26
26
  const { applicationGenerator: initExpress } = yield Promise.resolve().then(() => require('@nx/express'));
27
27
  yield initExpress(host, Object.assign(Object.assign({}, options), { skipFormat: true, skipPackageJson: false, linter: eslint_1.Linter.EsLint, unitTestRunner: 'jest', js: false, directory: `apps/${options.name}` }));
28
28
  (0, devkit_1.addDependenciesToPackageJson)(host, {
29
- '@abgov/adsp-service-sdk': '^2.0.0',
30
- dotenv: '^16.0.0',
31
- passport: '^0.6.0',
29
+ '@abgov/adsp-service-sdk': '^2.5.0',
30
+ compression: '^1.8.1',
31
+ cors: '^2.8.5',
32
+ dotenv: '^16.4.7',
33
+ envalid: '^8.0.0',
34
+ helmet: '^8.0.0',
35
+ passport: '^0.7.0',
32
36
  'passport-anonymous': '^1.0.1',
33
37
  }, {
34
- '@types/passport': '^1.0.9',
38
+ '@types/compression': '^1.7.5',
39
+ '@types/cors': '^2.8.17',
40
+ '@types/passport': '^1.0.16',
35
41
  '@types/passport-anonymous': '^1.0.3',
36
42
  });
37
43
  addFiles(host, normalizedOptions);
@@ -1 +1 @@
1
- {"version":3,"file":"express-service.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/express-service/express-service.ts"],"names":[],"mappings":";;AA6CA,4BAwCC;;AArFD,wCAAyE;AACzE,uCAQoB;AACpB,uCAAoC;AACpC,6BAA6B;AAG7B,SAAe,gBAAgB,CAC7B,IAAU,EACV,OAAe;;QAEf,MAAM,WAAW,GAAG,IAAA,cAAK,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;QACjD,MAAM,WAAW,GAAG,GAAG,IAAA,2BAAkB,EAAC,IAAI,CAAC,CAAC,OAAO,IAAI,WAAW,EAAE,CAAC;QAEzE,MAAM,IAAI,GAAG,MAAM,IAAA,4BAAoB,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEvD,uCACK,OAAO,KACV,WAAW;YACX,WAAW;YACX,IAAI,IACJ;IACJ,CAAC;CAAA;AAED,SAAS,QAAQ,CAAC,IAAU,EAAE,OAAyB;IACrD,MAAM,eAAe,iDAChB,OAAO,GACP,OAAO,CAAC,IAAI,KACf,IAAI,EAAE,EAAE,GACT,CAAC;IACF,IAAA,sBAAa,EACX,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,WAAW,EACnB,eAAe,CAChB,CAAC;AACJ,CAAC;AAED,mBAA+B,IAAU,EAAE,OAAe;;QACxD,MAAM,iBAAiB,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEhE,MAAM,EAAE,oBAAoB,EAAE,WAAW,EAAE,GAAG,2CAAa,aAAa,EAAC,CAAC;QAC1E,MAAM,WAAW,CAAC,IAAI,kCACjB,OAAO,KACV,UAAU,EAAE,IAAI,EAChB,eAAe,EAAE,KAAK,EACtB,MAAM,EAAE,eAAM,CAAC,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,KAAK,EACT,SAAS,EAAE,QAAQ,OAAO,CAAC,IAAI,EAAE,IACjC,CAAC;QAEH,IAAA,qCAA4B,EAC1B,IAAI,EACJ;YACE,yBAAyB,EAAE,QAAQ;YACnC,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,QAAQ;YAClB,oBAAoB,EAAE,QAAQ;SAC/B,EACD;YACE,iBAAiB,EAAE,QAAQ;YAC3B,2BAA2B,EAAE,QAAQ;SACtC,CACF,CAAC;QAEF,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAClC,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;QAExB,MAAM,IAAA,2BAAmB,EAAC,IAAI,kCACzB,iBAAiB,KACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,CAAC,WAAW,IACtC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,IAAA,4BAAmB,EAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC;CAAA"}
1
+ {"version":3,"file":"express-service.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/express-service/express-service.ts"],"names":[],"mappings":";;AA6CA,4BA8CC;;AA3FD,wCAAyE;AACzE,uCAQoB;AACpB,uCAAoC;AACpC,6BAA6B;AAG7B,SAAe,gBAAgB,CAC7B,IAAU,EACV,OAAe;;QAEf,MAAM,WAAW,GAAG,IAAA,cAAK,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;QACjD,MAAM,WAAW,GAAG,GAAG,IAAA,2BAAkB,EAAC,IAAI,CAAC,CAAC,OAAO,IAAI,WAAW,EAAE,CAAC;QAEzE,MAAM,IAAI,GAAG,MAAM,IAAA,4BAAoB,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEvD,uCACK,OAAO,KACV,WAAW;YACX,WAAW;YACX,IAAI,IACJ;IACJ,CAAC;CAAA;AAED,SAAS,QAAQ,CAAC,IAAU,EAAE,OAAyB;IACrD,MAAM,eAAe,iDAChB,OAAO,GACP,OAAO,CAAC,IAAI,KACf,IAAI,EAAE,EAAE,GACT,CAAC;IACF,IAAA,sBAAa,EACX,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,WAAW,EACnB,eAAe,CAChB,CAAC;AACJ,CAAC;AAED,mBAA+B,IAAU,EAAE,OAAe;;QACxD,MAAM,iBAAiB,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEhE,MAAM,EAAE,oBAAoB,EAAE,WAAW,EAAE,GAAG,2CAAa,aAAa,EAAC,CAAC;QAC1E,MAAM,WAAW,CAAC,IAAI,kCACjB,OAAO,KACV,UAAU,EAAE,IAAI,EAChB,eAAe,EAAE,KAAK,EACtB,MAAM,EAAE,eAAM,CAAC,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,KAAK,EACT,SAAS,EAAE,QAAQ,OAAO,CAAC,IAAI,EAAE,IACjC,CAAC;QAEH,IAAA,qCAA4B,EAC1B,IAAI,EACJ;YACE,yBAAyB,EAAE,QAAQ;YACnC,WAAW,EAAE,QAAQ;YACrB,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,QAAQ;YACjB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,QAAQ;YAClB,oBAAoB,EAAE,QAAQ;SAC/B,EACD;YACE,oBAAoB,EAAE,QAAQ;YAC9B,aAAa,EAAE,SAAS;YACxB,iBAAiB,EAAE,SAAS;YAC5B,2BAA2B,EAAE,QAAQ;SACtC,CACF,CAAC;QAEF,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAClC,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;QAExB,MAAM,IAAA,2BAAmB,EAAC,IAAI,kCACzB,iBAAiB,KACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,CAAC,WAAW,IACtC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,IAAA,4BAAmB,EAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC;CAAA"}
@@ -29,5 +29,7 @@ describe('Express Service Generator', () => {
29
29
  expect(config.root).toBe('apps/test');
30
30
 
31
31
  expect(host.exists('apps/test/src/main.ts')).toBeTruthy();
32
+ expect(host.exists('apps/test/src/environment.ts')).toBeTruthy();
33
+ expect(host.exists('apps/test/src/environments/environment.ts')).toBeFalsy();
32
34
  }, 60000);
33
35
  });
@@ -0,0 +1,19 @@
1
+ import { config } from 'dotenv';
2
+ import { cleanEnv, num, str } from 'envalid';
3
+ import { resolve } from 'path';
4
+
5
+ config({
6
+ path: resolve(process.cwd(), 'apps/<%= projectName %>/.env'),
7
+ override: true,
8
+ });
9
+
10
+ export const environment = cleanEnv(process.env, {
11
+ KEYCLOAK_ROOT_URL: str({ default: '<%= accessServiceUrl %>' }),
12
+ DIRECTORY_URL: str({ default: '<%= directoryServiceUrl %>' }),
13
+ TENANT_REALM: str({ default: '<%= tenantRealm %>' }),
14
+ CLIENT_ID: str({ default: 'urn:ads:<%= tenant %>:<%= projectName %>' }),
15
+ CLIENT_SECRET: str({ default: '' }),
16
+ TRUSTED_PROXY: str({ default: 'uniquelocal' }),
17
+ LOG_LEVEL: str({ default: 'debug' }),
18
+ PORT: num({ default: 3000 }),
19
+ });
@@ -1,63 +1,84 @@
1
- /**
2
- * This is not a production server yet!
3
- * This is only a minimal backend to get started.
4
- */
5
1
  import { AdspId, initializeService } from '@abgov/adsp-service-sdk';
2
+ import compression from 'compression';
3
+ import cors from 'cors';
6
4
  import express from 'express';
5
+ import helmet from 'helmet';
7
6
  import passport from 'passport';
8
7
  import { Strategy as AnonymousStrategy } from 'passport-anonymous';
9
8
 
10
- import { environment } from './environments/environment';
11
-
12
- async function initializeApp(): Promise<express.Application> {
13
- const app = express();
14
- app.use(passport.initialize());
9
+ import { environment } from './environment';
15
10
 
11
+ async function initializeApp() {
16
12
  const serviceId = AdspId.parse(environment.CLIENT_ID);
17
- const { tenantStrategy } = await initializeService(
13
+ const capabilities = await initializeService(
18
14
  {
19
15
  displayName: '<%= projectName %>',
20
16
  description: 'Put your service description here.',
21
- realm: environment.TENANT_REALM,
22
17
  serviceId,
18
+ realm: environment.TENANT_REALM,
23
19
  clientSecret: environment.CLIENT_SECRET,
24
- accessServiceUrl: new URL(environment.ACCESS_SERVICE_URL),
25
- directoryUrl: new URL(environment.DIRECTORY_SERVICE_URL),
20
+ accessServiceUrl: new URL(environment.KEYCLOAK_ROOT_URL),
21
+ directoryUrl: new URL(environment.DIRECTORY_URL),
26
22
  },
27
23
  { logLevel: environment.LOG_LEVEL }
28
24
  );
29
25
 
30
- passport.use('tenant', tenantStrategy);
26
+ const { logger, tenantStrategy, traceHandler, configurationHandler, healthCheck } = capabilities;
27
+
28
+ const app = express();
29
+
30
+ app.use(compression());
31
+ app.use(helmet());
32
+ app.use(express.json());
33
+ app.use(cors());
34
+
35
+ if (environment.TRUSTED_PROXY) {
36
+ app.set('trust proxy', environment.TRUSTED_PROXY);
37
+ }
38
+
39
+ app.use(traceHandler);
40
+
31
41
  passport.use('anonymous', new AnonymousStrategy());
42
+ passport.use('tenant', tenantStrategy);
43
+ app.use(passport.initialize());
32
44
 
33
- app.use(passport.authenticate(['tenant', 'anonymous'], { session: false }));
45
+ app.use(
46
+ '/<%= projectName %>/v1',
47
+ passport.authenticate(['tenant', 'anonymous'], { session: false }),
48
+ configurationHandler
49
+ );
34
50
 
35
- app.get('/<%= projectName %>/v1/public', (_req, res) => {
36
- res.send({ message: `Welcome to public API resource!` });
51
+ app.get('/health', async (_req, res) => {
52
+ const platform = await healthCheck();
53
+ res.json({ ...platform });
37
54
  });
38
55
 
39
- app.get(
40
- '/<%= projectName %>/v1/private',
41
- (req, res, next) => {
42
- if (!req.user) {
43
- res.sendStatus(401);
44
- } else {
45
- next();
46
- }
47
- },
48
- (req, res) => {
49
- const user = req.user;
50
- res.send({ message: `Welcome to private API resource! ${user.name}` });
51
- }
52
- );
53
- return app;
54
- }
56
+ app.get('/', (req, res) => {
57
+ const rootUrl = new URL(`${req.protocol}://${req.get('host')}`);
58
+ res.json({
59
+ _links: {
60
+ self: { href: new URL(req.originalUrl, rootUrl).href },
61
+ health: { href: new URL('/health', rootUrl).href },
62
+ api: { href: new URL('/<%= projectName %>/v1', rootUrl).href },
63
+ },
64
+ });
65
+ });
55
66
 
56
- initializeApp().then((app) => {
57
- const port = environment.port || 3333;
67
+ app.get('/<%= projectName %>/v1', (_req, res) => {
68
+ res.json({
69
+ _links: {
70
+ self: { href: '/<%= projectName %>/v1' },
71
+ },
72
+ });
73
+ });
74
+
75
+ return { app, logger };
76
+ }
58
77
 
78
+ initializeApp().then(({ app, logger }) => {
79
+ const port = environment.PORT;
59
80
  const server = app.listen(port, () => {
60
- console.log(`Listening at http://localhost:${port}/<%= projectName %>/v1`);
81
+ logger.info(`Listening at http://localhost:${port}/<%= projectName %>/v1`);
61
82
  });
62
- server.on('error', console.error);
83
+ server.on('error', (err) => logger.error(`Error encountered in server: ${err}`));
63
84
  });
@@ -15,7 +15,7 @@ utilsMock.getAdspConfiguration.mockResolvedValue({
15
15
  directoryServiceUrl: environments.test.directoryServiceUrl,
16
16
  });
17
17
 
18
- describe.skip('React App Generator', () => {
18
+ describe('MERN Generator', () => {
19
19
  const options: Schema = {
20
20
  name: 'test',
21
21
  env: 'dev',
@@ -15,7 +15,7 @@ utilsMock.getAdspConfiguration.mockResolvedValue({
15
15
  directoryServiceUrl: environments.test.directoryServiceUrl,
16
16
  });
17
17
 
18
- describe.skip('React App Generator', () => {
18
+ describe('React App Generator', () => {
19
19
  const options: Schema = {
20
20
  name: 'test',
21
21
  env: 'dev',
@@ -1,13 +0,0 @@
1
- import * as dotenv from 'dotenv';
2
- dotenv.config();
3
-
4
- export const environment = {
5
- production: true,
6
- TENANT_REALM: '<%= tenantRealm %>',
7
- ACCESS_SERVICE_URL: '<%= accessServiceUrl %>',
8
- DIRECTORY_SERVICE_URL: '<%= directoryServiceUrl %>',
9
- CLIENT_ID: 'urn:ads:<%= tenant %>:<%= projectName %>',
10
- CLIENT_SECRET: '',
11
- LOG_LEVEL: 'info',
12
- ...process.env,
13
- };
@@ -1,14 +0,0 @@
1
- import * as dotenv from 'dotenv';
2
- dotenv.config();
3
-
4
- export const environment = {
5
- production: false,
6
- port: '3333',
7
- TENANT_REALM: '<%= tenantRealm %>',
8
- ACCESS_SERVICE_URL: '<%= accessServiceUrl %>',
9
- DIRECTORY_SERVICE_URL: '<%= directoryServiceUrl %>',
10
- CLIENT_ID: 'urn:ads:<%= tenant %>:<%= projectName %>',
11
- CLIENT_SECRET: '',
12
- LOG_LEVEL: 'debug',
13
- ...process.env
14
- };