@abgov/nx-adsp 12.15.0 → 12.16.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/generators.json +12 -0
- package/package.json +1 -1
- package/src/generators/angular-app/angular-app.js +15 -8
- package/src/generators/angular-app/angular-app.js.map +1 -1
- package/src/generators/angular-app/files/src/app/app.component.ts__tmpl__ +2 -2
- package/src/generators/angular-app/schema.json +5 -0
- package/src/generators/pean/pean.d.ts +3 -0
- package/src/generators/pean/pean.js +80 -0
- package/src/generators/pean/pean.js.map +1 -0
- package/src/generators/pean/pean.spec.ts +46 -0
- package/src/generators/pean/schema.d.ts +14 -0
- package/src/generators/pean/schema.json +60 -0
- package/src/generators/pern/pern.d.ts +3 -0
- package/src/generators/pern/pern.js +80 -0
- package/src/generators/pern/pern.js.map +1 -0
- package/src/generators/pern/pern.spec.ts +46 -0
- package/src/generators/pern/schema.d.ts +14 -0
- package/src/generators/pern/schema.json +60 -0
- package/src/generators/react-app/schema.json +5 -0
- package/src/utils/agent.d.ts +1 -1
package/generators.json
CHANGED
|
@@ -49,6 +49,18 @@
|
|
|
49
49
|
"schema": "./src/generators/mean/schema.json",
|
|
50
50
|
"description": "Generator that creates a MEAN fullstack solution.",
|
|
51
51
|
"hidden": true
|
|
52
|
+
},
|
|
53
|
+
"pern": {
|
|
54
|
+
"factory": "./src/generators/pern/pern",
|
|
55
|
+
"schema": "./src/generators/pern/schema.json",
|
|
56
|
+
"description": "Generator that creates a PERN fullstack solution.",
|
|
57
|
+
"hidden": true
|
|
58
|
+
},
|
|
59
|
+
"pean": {
|
|
60
|
+
"factory": "./src/generators/pean/pean",
|
|
61
|
+
"schema": "./src/generators/pean/schema.json",
|
|
62
|
+
"description": "Generator that creates a PEAN fullstack solution.",
|
|
63
|
+
"hidden": true
|
|
52
64
|
}
|
|
53
65
|
}
|
|
54
66
|
}
|
package/package.json
CHANGED
|
@@ -56,7 +56,7 @@ function addFiles(host, options) {
|
|
|
56
56
|
}
|
|
57
57
|
function default_1(host, options) {
|
|
58
58
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
59
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
59
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
60
60
|
const normalizedOptions = yield normalizeOptions(host, options);
|
|
61
61
|
const { applicationGenerator: initAngular } = yield Promise.resolve().then(() => require('@nx/angular/generators'));
|
|
62
62
|
yield initAngular(host, {
|
|
@@ -89,6 +89,13 @@ function default_1(host, options) {
|
|
|
89
89
|
if ((_b = (_a = config.targets.build.configurations) === null || _a === void 0 ? void 0 : _a.production) === null || _b === void 0 ? void 0 : _b.fileReplacements) {
|
|
90
90
|
delete config.targets.build.configurations.production.fileReplacements;
|
|
91
91
|
}
|
|
92
|
+
// keycloak-js pushes the initial bundle above Angular's default 1 MB error budget.
|
|
93
|
+
if ((_c = config.targets.build.configurations) === null || _c === void 0 ? void 0 : _c.production) {
|
|
94
|
+
config.targets.build.configurations.production.budgets = [
|
|
95
|
+
{ type: 'initial', maximumWarning: '2mb', maximumError: '4mb' },
|
|
96
|
+
{ type: 'anyComponentStyle', maximumWarning: '6kb', maximumError: '10kb' },
|
|
97
|
+
];
|
|
98
|
+
}
|
|
92
99
|
config.targets.build.options = Object.assign(Object.assign({}, config.targets.build.options), { polyfills: ['zone.js'], assets: [
|
|
93
100
|
...config.targets.build.options.assets,
|
|
94
101
|
`${normalizedOptions.projectRoot}/src/silent-check-sso.html`,
|
|
@@ -106,7 +113,7 @@ function default_1(host, options) {
|
|
|
106
113
|
(0, quality_1.addSemgrepTarget)(host, options.name);
|
|
107
114
|
yield (0, devkit_1.formatFiles)(host);
|
|
108
115
|
if (normalizedOptions.adsp) {
|
|
109
|
-
const accessToken = (
|
|
116
|
+
const accessToken = (_d = normalizedOptions.adsp.accessToken) !== null && _d !== void 0 ? _d : options.accessToken;
|
|
110
117
|
const clientId = `urn:ads:${normalizedOptions.adsp.tenant}:${normalizedOptions.projectName}`;
|
|
111
118
|
yield (0, keycloak_admin_1.ensurePublicClient)(normalizedOptions.adsp.accessServiceUrl, normalizedOptions.adsp.tenantRealm, clientId, accessToken);
|
|
112
119
|
if (options.serviceClientId) {
|
|
@@ -115,12 +122,12 @@ function default_1(host, options) {
|
|
|
115
122
|
}
|
|
116
123
|
}
|
|
117
124
|
if (normalizedOptions.adsp && !options.skipAgent) {
|
|
118
|
-
const accessToken = (
|
|
119
|
-
const appComponentTs = (
|
|
120
|
-
const appComponentHtml = (
|
|
121
|
-
const appConfigTs = (
|
|
122
|
-
const appRoutesTs = (
|
|
123
|
-
const environmentTs = (
|
|
125
|
+
const accessToken = (_e = normalizedOptions.adsp.accessToken) !== null && _e !== void 0 ? _e : options.accessToken;
|
|
126
|
+
const appComponentTs = (_g = (_f = host.read(`${normalizedOptions.projectRoot}/src/app/app.component.ts`)) === null || _f === void 0 ? void 0 : _f.toString()) !== null && _g !== void 0 ? _g : '';
|
|
127
|
+
const appComponentHtml = (_j = (_h = host.read(`${normalizedOptions.projectRoot}/src/app/app.component.html`)) === null || _h === void 0 ? void 0 : _h.toString()) !== null && _j !== void 0 ? _j : '';
|
|
128
|
+
const appConfigTs = (_l = (_k = host.read(`${normalizedOptions.projectRoot}/src/app/app.config.ts`)) === null || _k === void 0 ? void 0 : _k.toString()) !== null && _l !== void 0 ? _l : '';
|
|
129
|
+
const appRoutesTs = (_o = (_m = host.read(`${normalizedOptions.projectRoot}/src/app/app.routes.ts`)) === null || _m === void 0 ? void 0 : _m.toString()) !== null && _o !== void 0 ? _o : '';
|
|
130
|
+
const environmentTs = (_q = (_p = host.read(`${normalizedOptions.projectRoot}/src/environments/environment.ts`)) === null || _p === void 0 ? void 0 : _p.toString()) !== null && _q !== void 0 ? _q : '';
|
|
124
131
|
yield (0, agent_1.confirmAfterAgentInterrupt)(yield (0, agent_1.consultAgent)(normalizedOptions.adsp.directoryServiceUrl, accessToken, {
|
|
125
132
|
projectName: normalizedOptions.projectName,
|
|
126
133
|
projectType: 'angular-app',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angular-app.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/angular-app/angular-app.ts"],"names":[],"mappings":";;AAkGA,
|
|
1
|
+
{"version":3,"file":"angular-app.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/angular-app/angular-app.ts"],"names":[],"mappings":";;AAkGA,4BAmJC;;AArPD,wCAAyE;AACzE,6CAA6E;AAC7E,+DAA6G;AAC7G,+DAA4D;AAC5D,iDAAiG;AACjG,uCAYoB;AACpB,6BAA6B;AAG7B,SAAe,gBAAgB,CAC7B,IAAU,EACV,OAAkC;;QAElC,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;QACzE,MAAM,kBAAkB,GAAG,cAAc,WAAW,EAAE,CAAC;QAEvD,MAAM,IAAI,GAAG,MAAM,IAAA,4BAAoB,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEvD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;YAC/C,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;YACpB,CAAC,CAAC,OAAO,CAAC,KAAK;gBACf,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;gBACjB,CAAC,CAAC,EAAE,CAAC;QAEP,uCACK,OAAO,KACV,WAAW;YACX,WAAW;YACX,kBAAkB;YAClB,IAAI;YACJ,YAAY,IACZ;IACJ,CAAC;CAAA;AAED,SAAS,QAAQ,CAAC,IAAU,EAAE,OAAyB;IACrD,MAAM,eAAe,+DAChB,OAAO,GACP,OAAO,CAAC,IAAI,GACZ,IAAA,cAAK,EAAC,OAAO,CAAC,IAAI,CAAC,KACtB,cAAc,EAAE,IAAA,uBAAc,EAAC,OAAO,CAAC,WAAW,CAAC,EACnD,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;IACF,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IACrD,IAAI,YAAY,EAAE,CAAC;QACjB,mDAAmD;QACnD,6CAA6C;QAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAC9C,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE;YACxB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAElD,MAAM,KAAK,GAAG;gBACZ,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,cAC7B,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAC9C,EAAE;gBACF,MAAM,EAAE,WAAW,CAAC,QAAQ,KAAK,QAAQ;gBACzC,YAAY,EAAE,KAAK;gBACnB,WAAW,EAAE,EAAE;aAChB,CAAC;YAEF,8DAA8D;YAC9D,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,KAAK,CAAC,WAAW,GAAG;oBAClB,CAAC,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC,EAAE,WAAW,CAAC,QAAQ;iBAClD,CAAC;YACJ,CAAC;YAED,uCACK,SAAS,KACZ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,KAAK,IAC5B;QACJ,CAAC,EACD,EAAE,CACH,CAAC;QACF,IAAA,kBAAS,EAAC,IAAI,EAAE,GAAG,OAAO,CAAC,WAAW,kBAAkB,EAAE,YAAY,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAGD,mBAA+B,IAAU,EAAE,OAAkC;;;QAC3E,MAAM,iBAAiB,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEhE,MAAM,EAAE,oBAAoB,EAAE,WAAW,EAAE,GAAG,2CAC5C,wBAAwB,EACzB,CAAC;QACF,MAAM,WAAW,CAAC,IAAI,EAAE;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,iBAAiB,CAAC,WAAW;YACrC,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,iBAAiB,CAAC,WAAW;YACxC,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QAEH,IAAA,qCAA4B,EAC1B,IAAI,EACJ;YACE,2BAA2B,EAAE,OAAO;YACpC,sBAAsB,EAAE,OAAO;YAC/B,6BAA6B,EAAE,QAAQ;YACvC,uBAAuB,EAAE,QAAQ;YACjC,kBAAkB,EAAE,SAAS;YAC7B,aAAa,EAAE,SAAS;YACxB,SAAS,EAAE,SAAS;SACrB,EACD,EAAE,CACH,CAAC;QAEF,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAErD,IAAA,+BAAqB,EAAC,IAAI,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAC3D,IAAA,2BAAiB,EAAC,IAAI,CAAC,CAAC;QAExB,gFAAgF;QAChF,8DAA8D;QAC9D,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,CAAC,EAAE,CAAC;YACrF,IAAI,CAAC,MAAM,CAAC,GAAG,iBAAiB,CAAC,WAAW,YAAY,IAAI,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAE5D,+EAA+E;QAC/E,0DAA0D;QAC1D,IAAI,MAAA,MAAA,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,0CAAE,UAAU,0CAAE,gBAAgB,EAAE,CAAC;YACtE,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,gBAAgB,CAAC;QACzE,CAAC;QAED,mFAAmF;QACnF,IAAI,MAAA,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,0CAAE,UAAU,EAAE,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,OAAO,GAAG;gBACvD,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE;gBAC/D,EAAE,IAAI,EAAE,mBAAmB,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE;aAC3E,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,mCACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,KAC/B,SAAS,EAAE,CAAC,SAAS,CAAC,EACtB,MAAM,EAAE;gBACN,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM;gBACtC,GAAG,iBAAiB,CAAC,WAAW,4BAA4B;gBAC5D;oBACE,IAAI,EAAE,YAAY;oBAClB,KAAK,EAAE,iBAAiB,CAAC,WAAW;oBACpC,MAAM,EAAE,IAAI;iBACb;aACF,GACF,CAAC;QAEF,IAAI,UAAU,EAAE,CAAC;YACf,oEAAoE;YACpE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,mCACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,KAC/B,WAAW,EAAE,GAAG,iBAAiB,CAAC,WAAW,kBAAkB,GAChE,CAAC;QACJ,CAAC;QAED,IAAA,mCAA0B,EAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAEvD,IAAA,0BAAgB,EAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;QAExB,IAAI,iBAAiB,CAAC,IAAI,EAAE,CAAC;YAC3B,MAAM,WAAW,GAAG,MAAA,iBAAiB,CAAC,IAAI,CAAC,WAAW,mCAAI,OAAO,CAAC,WAAW,CAAC;YAC9E,MAAM,QAAQ,GAAG,WAAW,iBAAiB,CAAC,IAAI,CAAC,MAAM,IAAI,iBAAiB,CAAC,WAAW,EAAE,CAAC;YAC7F,MAAM,IAAA,mCAAkB,EACtB,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,EACvC,iBAAiB,CAAC,IAAI,CAAC,WAAW,EAClC,QAAQ,EACR,WAAW,CACZ,CAAC;YACF,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;gBAC5B,MAAM,IAAA,qCAAoB,EACxB,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,EACvC,iBAAiB,CAAC,IAAI,CAAC,WAAW,EAClC,QAAQ,EACR,OAAO,CAAC,eAAe,EACvB,WAAW,CACZ,CAAC;gBACF,MAAM,IAAA,sCAAqB,EACzB,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,EACvC,iBAAiB,CAAC,IAAI,CAAC,WAAW,EAClC,QAAQ,EACR,OAAO,CAAC,eAAe,EACvB,cAAc,EACd,WAAW,CACZ,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,iBAAiB,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YACjD,MAAM,WAAW,GAAG,MAAA,iBAAiB,CAAC,IAAI,CAAC,WAAW,mCAAI,OAAO,CAAC,WAAW,CAAC;YAC9E,MAAM,cAAc,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,WAAW,2BAA2B,CAAC,0CAAE,QAAQ,EAAE,mCAAI,EAAE,CAAC;YAChH,MAAM,gBAAgB,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,WAAW,6BAA6B,CAAC,0CAAE,QAAQ,EAAE,mCAAI,EAAE,CAAC;YACpH,MAAM,WAAW,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,WAAW,wBAAwB,CAAC,0CAAE,QAAQ,EAAE,mCAAI,EAAE,CAAC;YAC1G,MAAM,WAAW,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,WAAW,wBAAwB,CAAC,0CAAE,QAAQ,EAAE,mCAAI,EAAE,CAAC;YAC1G,MAAM,aAAa,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,WAAW,kCAAkC,CAAC,0CAAE,QAAQ,EAAE,mCAAI,EAAE,CAAC;YACtH,MAAM,IAAA,kCAA0B,EAAC,MAAM,IAAA,oBAAY,EACjD,iBAAiB,CAAC,IAAI,CAAC,mBAAmB,EAC1C,WAAW,EACX;gBACE,WAAW,EAAE,iBAAiB,CAAC,WAAW;gBAC1C,WAAW,EAAE,aAAa;gBAC1B,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,MAAM;gBACrC,aAAa,EAAE,+BAAc;gBAC7B,aAAa,EAAE;oBACb,0BAA0B,EAAE,cAAc;oBAC1C,4BAA4B,EAAE,gBAAgB;oBAC9C,uBAAuB,EAAE,WAAW;oBACpC,uBAAuB,EAAE,WAAW;oBACpC,iCAAiC,EAAE,aAAa;iBACjD;aACF,EACD,IAAI,EACJ,iBAAiB,CAAC,WAAW,CAC9B,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAA,2BAAmB,EAAC,IAAI,kCACzB,iBAAiB,KACpB,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,iBAAiB,CAAC,WAAW,IACtC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,IAAA,4BAAmB,EAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC;CAAA"}
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
GoabMicrositeHeader,
|
|
10
10
|
} from '@abgov/angular-components';
|
|
11
11
|
import Keycloak from 'keycloak-js';
|
|
12
|
-
import { getAccessToken } from './user.slice';
|
|
13
12
|
|
|
14
13
|
@Component({
|
|
15
14
|
selector: '<%= projectName %>-root',
|
|
@@ -39,7 +38,8 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
39
38
|
error: () => (this.publicResource = 'Error loading data'),
|
|
40
39
|
});
|
|
41
40
|
if (this.isLoggedIn) {
|
|
42
|
-
|
|
41
|
+
this.keycloak.updateToken(30).then(() => {
|
|
42
|
+
const token = this.keycloak.token ?? '';
|
|
43
43
|
this.http.get<{ message: string }>('/api/v1/private', {
|
|
44
44
|
headers: { Authorization: `Bearer ${token}` },
|
|
45
45
|
}).subscribe({
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const devkit_1 = require("@nx/devkit");
|
|
6
|
+
const nx_oc_1 = require("@abgov/nx-oc");
|
|
7
|
+
const angular_app_1 = require("../angular-app/angular-app");
|
|
8
|
+
const express_service_1 = require("../express-service/express-service");
|
|
9
|
+
const agent_1 = require("../../utils/agent");
|
|
10
|
+
const keycloak_admin_1 = require("../../utils/keycloak-admin");
|
|
11
|
+
const plugin_version_1 = require("../../utils/plugin-version");
|
|
12
|
+
function normalizeOptions(host, options) {
|
|
13
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
14
|
+
var _a;
|
|
15
|
+
const adsp = yield (0, nx_oc_1.getAdspConfiguration)(host, options);
|
|
16
|
+
// Propagate the token from adsp to the Schema-level accessToken so that
|
|
17
|
+
// sub-generators (express-service, angular-app) that check options.accessToken
|
|
18
|
+
// see it and skip their own realmLogin fallback.
|
|
19
|
+
return Object.assign(Object.assign({}, options), { accessToken: (_a = adsp.accessToken) !== null && _a !== void 0 ? _a : options.accessToken, adsp });
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function default_1(host, options) {
|
|
23
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
25
|
+
const normalizedOptions = yield normalizeOptions(host, options);
|
|
26
|
+
const projectName = (0, devkit_1.names)(options.name).fileName;
|
|
27
|
+
const serviceName = `${projectName}-service`;
|
|
28
|
+
const appName = `${projectName}-app`;
|
|
29
|
+
const appsDir = (0, devkit_1.getWorkspaceLayout)(host).appsDir;
|
|
30
|
+
const serviceRoot = `${appsDir}/${serviceName}`;
|
|
31
|
+
const appRoot = `${appsDir}/${appName}`;
|
|
32
|
+
// Scaffold both projects before the agent interaction so files exist to upload.
|
|
33
|
+
yield (0, express_service_1.default)(host, Object.assign(Object.assign({}, normalizedOptions), { name: serviceName, skipAgent: true, database: 'postgres' }));
|
|
34
|
+
yield (0, angular_app_1.default)(host, Object.assign(Object.assign({}, normalizedOptions), { name: appName, proxy: {
|
|
35
|
+
location: '/api/',
|
|
36
|
+
proxyPass: `http://${serviceName}:3333/${serviceName}/`,
|
|
37
|
+
}, skipAgent: true }));
|
|
38
|
+
if (normalizedOptions.adsp) {
|
|
39
|
+
const accessToken = (_a = normalizedOptions.adsp.accessToken) !== null && _a !== void 0 ? _a : normalizedOptions.accessToken;
|
|
40
|
+
const serviceClientId = `urn:ads:${normalizedOptions.adsp.tenant}:${serviceName}`;
|
|
41
|
+
const appClientId = `urn:ads:${normalizedOptions.adsp.tenant}:${appName}`;
|
|
42
|
+
yield (0, keycloak_admin_1.ensureAudienceMapper)(normalizedOptions.adsp.accessServiceUrl, normalizedOptions.adsp.tenantRealm, appClientId, serviceClientId, accessToken);
|
|
43
|
+
yield (0, keycloak_admin_1.ensureClientRoleScope)(normalizedOptions.adsp.accessServiceUrl, normalizedOptions.adsp.tenantRealm, appClientId, serviceClientId, 'example-role', accessToken);
|
|
44
|
+
}
|
|
45
|
+
if (normalizedOptions.adsp && !normalizedOptions.skipAgent) {
|
|
46
|
+
// Single conversation covering the full stack. Files from both projects are
|
|
47
|
+
// uploaded with service/ and app/ prefixes so the agent can write to both,
|
|
48
|
+
// and are routed to the correct project root when applied.
|
|
49
|
+
// Use the token from --tenant login if available; fall back to a realm login
|
|
50
|
+
// when the interactive flow was used (which only obtains a core-realm token).
|
|
51
|
+
const accessToken = (_b = normalizedOptions.adsp.accessToken) !== null && _b !== void 0 ? _b : (yield (0, nx_oc_1.realmLogin)(normalizedOptions.adsp.accessServiceUrl, normalizedOptions.adsp.tenantRealm).catch((err) => {
|
|
52
|
+
var _a;
|
|
53
|
+
process.stdout.write(`\n[nx-adsp] Agent sign-in failed (${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}) — skipping agent interaction.\n`);
|
|
54
|
+
return undefined;
|
|
55
|
+
}));
|
|
56
|
+
yield (0, agent_1.confirmAfterAgentInterrupt)(yield (0, agent_1.consultAgent)(normalizedOptions.adsp.directoryServiceUrl, accessToken, {
|
|
57
|
+
projectName,
|
|
58
|
+
projectType: 'pean',
|
|
59
|
+
tenant: normalizedOptions.adsp.tenant,
|
|
60
|
+
pluginVersion: plugin_version_1.PLUGIN_VERSION,
|
|
61
|
+
existingFiles: {
|
|
62
|
+
'service/src/main.ts': (_d = (_c = host.read(`${serviceRoot}/src/main.ts`)) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '',
|
|
63
|
+
'service/src/environment.ts': (_f = (_e = host.read(`${serviceRoot}/src/environment.ts`)) === null || _e === void 0 ? void 0 : _e.toString()) !== null && _f !== void 0 ? _f : '',
|
|
64
|
+
'service/src/database.ts': (_h = (_g = host.read(`${serviceRoot}/src/database.ts`)) === null || _g === void 0 ? void 0 : _g.toString()) !== null && _h !== void 0 ? _h : '',
|
|
65
|
+
'service/src/events.ts': (_k = (_j = host.read(`${serviceRoot}/src/events.ts`)) === null || _j === void 0 ? void 0 : _j.toString()) !== null && _k !== void 0 ? _k : '',
|
|
66
|
+
'app/src/app/app.component.ts': (_m = (_l = host.read(`${appRoot}/src/app/app.component.ts`)) === null || _l === void 0 ? void 0 : _l.toString()) !== null && _m !== void 0 ? _m : '',
|
|
67
|
+
'app/src/app/app.component.html': (_p = (_o = host.read(`${appRoot}/src/app/app.component.html`)) === null || _o === void 0 ? void 0 : _o.toString()) !== null && _p !== void 0 ? _p : '',
|
|
68
|
+
'app/src/app/app.config.ts': (_r = (_q = host.read(`${appRoot}/src/app/app.config.ts`)) === null || _q === void 0 ? void 0 : _q.toString()) !== null && _r !== void 0 ? _r : '',
|
|
69
|
+
'app/src/app/app.routes.ts': (_t = (_s = host.read(`${appRoot}/src/app/app.routes.ts`)) === null || _s === void 0 ? void 0 : _s.toString()) !== null && _t !== void 0 ? _t : '',
|
|
70
|
+
'app/src/environments/environment.ts': (_v = (_u = host.read(`${appRoot}/src/environments/environment.ts`)) === null || _u === void 0 ? void 0 : _u.toString()) !== null && _v !== void 0 ? _v : '',
|
|
71
|
+
},
|
|
72
|
+
}, host, serviceRoot, { additionalRoots: { 'app': appRoot } }));
|
|
73
|
+
}
|
|
74
|
+
yield (0, devkit_1.formatFiles)(host);
|
|
75
|
+
return () => {
|
|
76
|
+
(0, devkit_1.installPackagesTask)(host);
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=pean.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pean.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/pean/pean.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readProjectConfiguration } from '@nx/devkit';
|
|
2
|
+
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
|
3
|
+
|
|
4
|
+
import * as utils from '@abgov/nx-oc';
|
|
5
|
+
import { environments } from '@abgov/nx-oc';
|
|
6
|
+
import { Schema } from './schema';
|
|
7
|
+
import generator from './pean';
|
|
8
|
+
|
|
9
|
+
jest.mock('@nx/devkit', () => ({ ...jest.requireActual('@nx/devkit'), formatFiles: jest.fn().mockResolvedValue(undefined) }));
|
|
10
|
+
jest.mock('@abgov/nx-oc');
|
|
11
|
+
jest.mock('../../utils/agent', () => ({
|
|
12
|
+
consultAgent: jest.fn().mockResolvedValue(null),
|
|
13
|
+
confirmAfterAgentInterrupt: jest.fn().mockResolvedValue(undefined),
|
|
14
|
+
}));
|
|
15
|
+
const utilsMock = utils as jest.Mocked<typeof utils>;
|
|
16
|
+
utilsMock.getAdspConfiguration.mockResolvedValue({
|
|
17
|
+
tenant: 'test',
|
|
18
|
+
tenantRealm: 'test',
|
|
19
|
+
accessServiceUrl: environments.test.accessServiceUrl,
|
|
20
|
+
directoryServiceUrl: environments.test.directoryServiceUrl,
|
|
21
|
+
});
|
|
22
|
+
utilsMock.realmLogin.mockResolvedValue('test-token');
|
|
23
|
+
|
|
24
|
+
describe('PEAN Generator', () => {
|
|
25
|
+
const options: Schema = {
|
|
26
|
+
name: 'test',
|
|
27
|
+
env: 'dev',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
it('can run', async () => {
|
|
31
|
+
const host = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
32
|
+
await generator(host, options);
|
|
33
|
+
|
|
34
|
+
const appConfig = readProjectConfiguration(host, 'test-app');
|
|
35
|
+
expect(appConfig.root).toBe('apps/test-app');
|
|
36
|
+
|
|
37
|
+
const serviceConfig = readProjectConfiguration(host, 'test-service');
|
|
38
|
+
expect(serviceConfig.root).toBe('apps/test-service');
|
|
39
|
+
|
|
40
|
+
expect(host.exists('apps/test-app/nginx.conf')).toBeTruthy();
|
|
41
|
+
const nginxConf = host.read('apps/test-app/nginx.conf').toString();
|
|
42
|
+
expect(nginxConf).toContain('http://test-service:3333/');
|
|
43
|
+
|
|
44
|
+
expect(host.exists('apps/test-service/prisma/schema.prisma')).toBeTruthy();
|
|
45
|
+
}, 30000);
|
|
46
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AdspConfiguration, EnvironmentName } from '@abgov/nx-oc';
|
|
2
|
+
|
|
3
|
+
export interface Schema {
|
|
4
|
+
name: string;
|
|
5
|
+
env: EnvironmentName;
|
|
6
|
+
accessToken?: string;
|
|
7
|
+
tenant?: string;
|
|
8
|
+
tenantRealm?: string;
|
|
9
|
+
skipAgent?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface NormalizedSchema extends Schema {
|
|
13
|
+
adsp: AdspConfiguration;
|
|
14
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"id": "NxAdspPean",
|
|
4
|
+
"title": "PEAN Stack ADSP Solution",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Name of the PEAN stack solution.",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "argv",
|
|
12
|
+
"index": 0
|
|
13
|
+
},
|
|
14
|
+
"x-prompt": "What name would you like to use?"
|
|
15
|
+
},
|
|
16
|
+
"env": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Environment to target.",
|
|
19
|
+
"$default": {
|
|
20
|
+
"$source": "argv",
|
|
21
|
+
"index": 1
|
|
22
|
+
},
|
|
23
|
+
"alias": "e",
|
|
24
|
+
"x-prompt": {
|
|
25
|
+
"message": "Which ADSP environment do you want to target?",
|
|
26
|
+
"type": "list",
|
|
27
|
+
"items": [
|
|
28
|
+
"dev",
|
|
29
|
+
"test",
|
|
30
|
+
"prod"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"tenant": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "ADSP tenant name. Enables a single browser login for the full stack — service and frontend agent interactions both use the same tenant-realm token.",
|
|
37
|
+
"alias": "t"
|
|
38
|
+
},
|
|
39
|
+
"tenantRealm": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Keycloak realm UUID. Optional when --tenant is provided — overrides the realm looked up from the tenant service.",
|
|
42
|
+
"alias": "tr"
|
|
43
|
+
},
|
|
44
|
+
"accessToken": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "Access token for retrieving configuration from ADSP APIs.",
|
|
47
|
+
"alias": "at"
|
|
48
|
+
},
|
|
49
|
+
"skipAgent": {
|
|
50
|
+
"type": "boolean",
|
|
51
|
+
"description": "Skip the consultAgent interaction and generate base scaffolding only.",
|
|
52
|
+
"default": false
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"required": [
|
|
56
|
+
"name",
|
|
57
|
+
"env"
|
|
58
|
+
],
|
|
59
|
+
"additionalProperties": false
|
|
60
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const devkit_1 = require("@nx/devkit");
|
|
6
|
+
const nx_oc_1 = require("@abgov/nx-oc");
|
|
7
|
+
const express_service_1 = require("../express-service/express-service");
|
|
8
|
+
const react_app_1 = require("../react-app/react-app");
|
|
9
|
+
const agent_1 = require("../../utils/agent");
|
|
10
|
+
const keycloak_admin_1 = require("../../utils/keycloak-admin");
|
|
11
|
+
const plugin_version_1 = require("../../utils/plugin-version");
|
|
12
|
+
function normalizeOptions(host, options) {
|
|
13
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
14
|
+
var _a;
|
|
15
|
+
const adsp = yield (0, nx_oc_1.getAdspConfiguration)(host, options);
|
|
16
|
+
// Propagate the token from adsp to the Schema-level accessToken so that
|
|
17
|
+
// sub-generators (express-service, react-app) that check options.accessToken
|
|
18
|
+
// see it and skip their own realmLogin fallback.
|
|
19
|
+
return Object.assign(Object.assign({}, options), { accessToken: (_a = adsp.accessToken) !== null && _a !== void 0 ? _a : options.accessToken, adsp });
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function default_1(host, options) {
|
|
23
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
25
|
+
const normalizedOptions = yield normalizeOptions(host, options);
|
|
26
|
+
const projectName = (0, devkit_1.names)(options.name).fileName;
|
|
27
|
+
const serviceName = `${projectName}-service`;
|
|
28
|
+
const appName = `${projectName}-app`;
|
|
29
|
+
const appsDir = (0, devkit_1.getWorkspaceLayout)(host).appsDir;
|
|
30
|
+
const serviceRoot = `${appsDir}/${serviceName}`;
|
|
31
|
+
const appRoot = `${appsDir}/${appName}`;
|
|
32
|
+
// Scaffold both projects before the agent interaction so files exist to upload.
|
|
33
|
+
yield (0, express_service_1.default)(host, Object.assign(Object.assign({}, normalizedOptions), { name: serviceName, skipAgent: true, database: 'postgres' }));
|
|
34
|
+
yield (0, react_app_1.default)(host, Object.assign(Object.assign({}, normalizedOptions), { name: appName, proxy: {
|
|
35
|
+
location: '/api/',
|
|
36
|
+
proxyPass: `http://${serviceName}:3333/${serviceName}/`,
|
|
37
|
+
}, skipAgent: true }));
|
|
38
|
+
if (normalizedOptions.adsp) {
|
|
39
|
+
const accessToken = (_a = normalizedOptions.adsp.accessToken) !== null && _a !== void 0 ? _a : normalizedOptions.accessToken;
|
|
40
|
+
const serviceClientId = `urn:ads:${normalizedOptions.adsp.tenant}:${serviceName}`;
|
|
41
|
+
const appClientId = `urn:ads:${normalizedOptions.adsp.tenant}:${appName}`;
|
|
42
|
+
yield (0, keycloak_admin_1.ensureAudienceMapper)(normalizedOptions.adsp.accessServiceUrl, normalizedOptions.adsp.tenantRealm, appClientId, serviceClientId, accessToken);
|
|
43
|
+
yield (0, keycloak_admin_1.ensureClientRoleScope)(normalizedOptions.adsp.accessServiceUrl, normalizedOptions.adsp.tenantRealm, appClientId, serviceClientId, 'example-role', accessToken);
|
|
44
|
+
}
|
|
45
|
+
if (normalizedOptions.adsp && !normalizedOptions.skipAgent) {
|
|
46
|
+
// Single conversation covering the full stack. Files from both projects are
|
|
47
|
+
// uploaded with service/ and app/ prefixes so the agent can write to both,
|
|
48
|
+
// and are routed to the correct project root when applied.
|
|
49
|
+
// Use the token from --tenant login if available; fall back to a realm login
|
|
50
|
+
// when the interactive flow was used (which only obtains a core-realm token).
|
|
51
|
+
const accessToken = (_b = normalizedOptions.adsp.accessToken) !== null && _b !== void 0 ? _b : (yield (0, nx_oc_1.realmLogin)(normalizedOptions.adsp.accessServiceUrl, normalizedOptions.adsp.tenantRealm).catch((err) => {
|
|
52
|
+
var _a;
|
|
53
|
+
process.stdout.write(`\n[nx-adsp] Agent sign-in failed (${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}) — skipping agent interaction.\n`);
|
|
54
|
+
return undefined;
|
|
55
|
+
}));
|
|
56
|
+
yield (0, agent_1.confirmAfterAgentInterrupt)(yield (0, agent_1.consultAgent)(normalizedOptions.adsp.directoryServiceUrl, accessToken, {
|
|
57
|
+
projectName,
|
|
58
|
+
projectType: 'pern',
|
|
59
|
+
tenant: normalizedOptions.adsp.tenant,
|
|
60
|
+
pluginVersion: plugin_version_1.PLUGIN_VERSION,
|
|
61
|
+
existingFiles: {
|
|
62
|
+
'service/src/main.ts': (_d = (_c = host.read(`${serviceRoot}/src/main.ts`)) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '',
|
|
63
|
+
'service/src/environment.ts': (_f = (_e = host.read(`${serviceRoot}/src/environment.ts`)) === null || _e === void 0 ? void 0 : _e.toString()) !== null && _f !== void 0 ? _f : '',
|
|
64
|
+
'service/src/database.ts': (_h = (_g = host.read(`${serviceRoot}/src/database.ts`)) === null || _g === void 0 ? void 0 : _g.toString()) !== null && _h !== void 0 ? _h : '',
|
|
65
|
+
'service/src/events.ts': (_k = (_j = host.read(`${serviceRoot}/src/events.ts`)) === null || _j === void 0 ? void 0 : _j.toString()) !== null && _k !== void 0 ? _k : '',
|
|
66
|
+
'app/src/app/app.tsx': (_m = (_l = host.read(`${appRoot}/src/app/app.tsx`)) === null || _l === void 0 ? void 0 : _l.toString()) !== null && _m !== void 0 ? _m : '',
|
|
67
|
+
'app/src/store.ts': (_p = (_o = host.read(`${appRoot}/src/store.ts`)) === null || _o === void 0 ? void 0 : _o.toString()) !== null && _p !== void 0 ? _p : '',
|
|
68
|
+
'app/src/environments/environment.ts': (_r = (_q = host.read(`${appRoot}/src/environments/environment.ts`)) === null || _q === void 0 ? void 0 : _q.toString()) !== null && _r !== void 0 ? _r : '',
|
|
69
|
+
'app/src/app/config.slice.ts': (_t = (_s = host.read(`${appRoot}/src/app/config.slice.ts`)) === null || _s === void 0 ? void 0 : _s.toString()) !== null && _t !== void 0 ? _t : '',
|
|
70
|
+
'app/src/app/intake.slice.ts': (_v = (_u = host.read(`${appRoot}/src/app/intake.slice.ts`)) === null || _u === void 0 ? void 0 : _u.toString()) !== null && _v !== void 0 ? _v : '',
|
|
71
|
+
},
|
|
72
|
+
}, host, serviceRoot, { additionalRoots: { 'app': appRoot } }));
|
|
73
|
+
}
|
|
74
|
+
yield (0, devkit_1.formatFiles)(host);
|
|
75
|
+
return () => {
|
|
76
|
+
(0, devkit_1.installPackagesTask)(host);
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=pern.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pern.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/pern/pern.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readProjectConfiguration } from '@nx/devkit';
|
|
2
|
+
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
|
3
|
+
|
|
4
|
+
import * as utils from '@abgov/nx-oc';
|
|
5
|
+
import { environments } from '@abgov/nx-oc';
|
|
6
|
+
import { Schema } from './schema';
|
|
7
|
+
import generator from './pern';
|
|
8
|
+
|
|
9
|
+
jest.mock('@nx/devkit', () => ({ ...jest.requireActual('@nx/devkit'), formatFiles: jest.fn().mockResolvedValue(undefined) }));
|
|
10
|
+
jest.mock('@abgov/nx-oc');
|
|
11
|
+
jest.mock('../../utils/agent', () => ({
|
|
12
|
+
consultAgent: jest.fn().mockResolvedValue(null),
|
|
13
|
+
confirmAfterAgentInterrupt: jest.fn().mockResolvedValue(undefined),
|
|
14
|
+
}));
|
|
15
|
+
const utilsMock = utils as jest.Mocked<typeof utils>;
|
|
16
|
+
utilsMock.getAdspConfiguration.mockResolvedValue({
|
|
17
|
+
tenant: 'test',
|
|
18
|
+
tenantRealm: 'test',
|
|
19
|
+
accessServiceUrl: environments.test.accessServiceUrl,
|
|
20
|
+
directoryServiceUrl: environments.test.directoryServiceUrl,
|
|
21
|
+
});
|
|
22
|
+
utilsMock.realmLogin.mockResolvedValue('test-token');
|
|
23
|
+
|
|
24
|
+
describe('PERN Generator', () => {
|
|
25
|
+
const options: Schema = {
|
|
26
|
+
name: 'test',
|
|
27
|
+
env: 'dev',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
it('can run', async () => {
|
|
31
|
+
const host = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
32
|
+
await generator(host, options);
|
|
33
|
+
|
|
34
|
+
const appConfig = readProjectConfiguration(host, 'test-app');
|
|
35
|
+
expect(appConfig.root).toBe('apps/test-app');
|
|
36
|
+
|
|
37
|
+
const serviceConfig = readProjectConfiguration(host, 'test-service');
|
|
38
|
+
expect(serviceConfig.root).toBe('apps/test-service');
|
|
39
|
+
|
|
40
|
+
expect(host.exists('apps/test-app/nginx.conf')).toBeTruthy();
|
|
41
|
+
const nginxConf = host.read('apps/test-app/nginx.conf').toString();
|
|
42
|
+
expect(nginxConf).toContain('http://test-service:3333/');
|
|
43
|
+
|
|
44
|
+
expect(host.exists('apps/test-service/prisma/schema.prisma')).toBeTruthy();
|
|
45
|
+
}, 30000);
|
|
46
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AdspConfiguration, EnvironmentName } from '@abgov/nx-oc';
|
|
2
|
+
|
|
3
|
+
export interface Schema {
|
|
4
|
+
name: string;
|
|
5
|
+
env: EnvironmentName;
|
|
6
|
+
accessToken?: string;
|
|
7
|
+
tenant?: string;
|
|
8
|
+
tenantRealm?: string;
|
|
9
|
+
skipAgent?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface NormalizedSchema extends Schema {
|
|
13
|
+
adsp: AdspConfiguration;
|
|
14
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"id": "NxAdspPern",
|
|
4
|
+
"title": "PERN Stack ADSP Solution",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Name of the PERN stack solution.",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "argv",
|
|
12
|
+
"index": 0
|
|
13
|
+
},
|
|
14
|
+
"x-prompt": "What name would you like to use?"
|
|
15
|
+
},
|
|
16
|
+
"env": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Environment to target.",
|
|
19
|
+
"$default": {
|
|
20
|
+
"$source": "argv",
|
|
21
|
+
"index": 1
|
|
22
|
+
},
|
|
23
|
+
"alias": "e",
|
|
24
|
+
"x-prompt": {
|
|
25
|
+
"message": "Which ADSP environment do you want to target?",
|
|
26
|
+
"type": "list",
|
|
27
|
+
"items": [
|
|
28
|
+
"dev",
|
|
29
|
+
"test",
|
|
30
|
+
"prod"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"tenant": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "ADSP tenant name. Enables a single browser login for the full stack — service and frontend agent interactions both use the same tenant-realm token.",
|
|
37
|
+
"alias": "t"
|
|
38
|
+
},
|
|
39
|
+
"tenantRealm": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Keycloak realm UUID. Optional when --tenant is provided — overrides the realm looked up from the tenant service.",
|
|
42
|
+
"alias": "tr"
|
|
43
|
+
},
|
|
44
|
+
"accessToken": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "Access token for retrieving configuration from ADSP APIs.",
|
|
47
|
+
"alias": "at"
|
|
48
|
+
},
|
|
49
|
+
"skipAgent": {
|
|
50
|
+
"type": "boolean",
|
|
51
|
+
"description": "Skip the consultAgent interaction and generate base scaffolding only.",
|
|
52
|
+
"default": false
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"required": [
|
|
56
|
+
"name",
|
|
57
|
+
"env"
|
|
58
|
+
],
|
|
59
|
+
"additionalProperties": false
|
|
60
|
+
}
|
package/src/utils/agent.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export declare function confirmAfterAgentInterrupt(result: AgentResult | null):
|
|
|
41
41
|
*/
|
|
42
42
|
export declare function consultAgent(directoryServiceUrl: string, accessToken: string, projectContext: {
|
|
43
43
|
projectName: string;
|
|
44
|
-
projectType: 'express-service' | 'react-app' | 'angular-app' | 'mern' | 'mean';
|
|
44
|
+
projectType: 'express-service' | 'react-app' | 'angular-app' | 'mern' | 'mean' | 'pern' | 'pean';
|
|
45
45
|
tenant: string;
|
|
46
46
|
pluginVersion: string;
|
|
47
47
|
/** Content of key integration files for the agent to read and potentially modify. */
|