@postxl/generators 1.18.0 → 1.20.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/dist/backend-actions/actions.generator.d.ts +1 -0
- package/dist/backend-actions/actions.generator.js +6 -0
- package/dist/backend-actions/actions.generator.js.map +1 -1
- package/dist/backend-actions/generators/actions-module.generator.js +3 -2
- package/dist/backend-actions/generators/actions-module.generator.js.map +1 -1
- package/dist/backend-actions/generators/authorization-policy-service.generator.d.ts +2 -0
- package/dist/backend-actions/generators/authorization-policy-service.generator.js +334 -0
- package/dist/backend-actions/generators/authorization-policy-service.generator.js.map +1 -0
- package/dist/backend-actions/generators/authorization-service.generator.d.ts +1 -1
- package/dist/backend-actions/generators/authorization-service.generator.js +20 -8
- package/dist/backend-actions/generators/authorization-service.generator.js.map +1 -1
- package/dist/backend-actions/generators/dispatcher-service.generator.js +10 -3
- package/dist/backend-actions/generators/dispatcher-service.generator.js.map +1 -1
- package/dist/backend-actions/generators/execution-class.generator.js +25 -4
- package/dist/backend-actions/generators/execution-class.generator.js.map +1 -1
- package/dist/backend-actions/generators/execution-interface.generator.js +4 -2
- package/dist/backend-actions/generators/execution-interface.generator.js.map +1 -1
- package/dist/backend-ai/generators/ai-route.generator.js +3 -3
- package/dist/backend-authentication/authentication.generator.js +22 -1
- package/dist/backend-authentication/authentication.generator.js.map +1 -1
- package/dist/backend-authentication/generators/auth-guard.generator.js +5 -8
- package/dist/backend-authentication/generators/auth-guard.generator.js.map +1 -1
- package/dist/backend-authentication/generators/authentication-module.generator.js +1 -1
- package/dist/backend-authentication/generators/authentication-service.generator.js +11 -8
- package/dist/backend-authentication/generators/authentication-service.generator.js.map +1 -1
- package/dist/backend-authentication/generators/authentication-types.generator.js +4 -3
- package/dist/backend-authentication/generators/authentication-types.generator.js.map +1 -1
- package/dist/backend-authentication/template/src/authentication.config.ts +9 -0
- package/dist/backend-authentication/template/src/authentication.mock.service.ts +77 -13
- package/dist/backend-authentication/template/src/utils.ts +45 -0
- package/dist/backend-core/backend.generator.js +17 -1
- package/dist/backend-core/backend.generator.js.map +1 -1
- package/dist/backend-core/generators/api-config.generator.js +5 -0
- package/dist/backend-core/generators/api-config.generator.js.map +1 -1
- package/dist/backend-core/types.d.ts +4 -0
- package/dist/backend-excel-io/generators/excel-io-service.generator.js +27 -11
- package/dist/backend-excel-io/generators/excel-io-service.generator.js.map +1 -1
- package/dist/backend-excel-io/template/excel-io.controller.ts +3 -3
- package/dist/backend-rest-api/generators/model-controller.generator.js +9 -5
- package/dist/backend-rest-api/generators/model-controller.generator.js.map +1 -1
- package/dist/backend-rest-api/template/restApi/src/restApi.utils.ts +9 -0
- package/dist/backend-router-trpc/generators/audit-log-route.generator.js +2 -2
- package/dist/backend-router-trpc/generators/excel-io-route.generator.js +1 -1
- package/dist/backend-router-trpc/generators/middleware.generator.js +8 -5
- package/dist/backend-router-trpc/generators/middleware.generator.js.map +1 -1
- package/dist/backend-router-trpc/generators/model-routes.generator.js +27 -7
- package/dist/backend-router-trpc/generators/model-routes.generator.js.map +1 -1
- package/dist/backend-router-trpc/generators/trpc-plugin.generator.js +9 -6
- package/dist/backend-router-trpc/generators/trpc-plugin.generator.js.map +1 -1
- package/dist/backend-router-trpc/generators/trpc-shared.generator.js +4 -24
- package/dist/backend-router-trpc/generators/trpc-shared.generator.js.map +1 -1
- package/dist/backend-router-trpc/router-trpc.generator.d.ts +4 -0
- package/dist/backend-router-trpc/router-trpc.generator.js +1 -0
- package/dist/backend-router-trpc/router-trpc.generator.js.map +1 -1
- package/dist/backend-router-trpc/template/viewer.router.ts +1 -6
- package/dist/backend-update/model-update-service.generator.js +72 -9
- package/dist/backend-update/model-update-service.generator.js.map +1 -1
- package/dist/backend-update/update-actions.decoders.d.ts +4 -4
- package/dist/backend-upload/template/src/upload.controller.ts +1 -1
- package/dist/backend-upload/template/src/upload.service.ts +11 -5
- package/dist/backend-view/model-view-service.generator.js +110 -52
- package/dist/backend-view/model-view-service.generator.js.map +1 -1
- package/dist/backend-view/view.generator.d.ts +2 -1
- package/dist/backend-view/view.generator.js +8 -1
- package/dist/backend-view/view.generator.js.map +1 -1
- package/dist/base/base.generator.js +2 -0
- package/dist/base/base.generator.js.map +1 -1
- package/dist/e2e/template/e2e/specs/example.spec.ts-snapshots/Navigate-to-homepage-and-take-snapshot-1-chromium-linux.png +0 -0
- package/dist/frontend-admin/admin.generator.js +2 -0
- package/dist/frontend-admin/admin.generator.js.map +1 -1
- package/dist/frontend-admin/generators/authorization-utils.generator.d.ts +1 -0
- package/dist/frontend-admin/generators/authorization-utils.generator.js +20 -0
- package/dist/frontend-admin/generators/authorization-utils.generator.js.map +1 -0
- package/dist/frontend-admin/generators/comment-sidebar.generator.js +9 -1
- package/dist/frontend-admin/generators/comment-sidebar.generator.js.map +1 -1
- package/dist/frontend-admin/generators/model-admin-page.generator.js +347 -184
- package/dist/frontend-admin/generators/model-admin-page.generator.js.map +1 -1
- package/dist/frontend-core/frontend.generator.d.ts +6 -0
- package/dist/frontend-core/frontend.generator.js +10 -3
- package/dist/frontend-core/frontend.generator.js.map +1 -1
- package/dist/frontend-core/template/README.md +2 -0
- package/dist/frontend-core/template/src/context-providers/auth-context-provider.tsx +1 -2
- package/dist/frontend-core/template/src/pages/dashboard/dashboard.page.tsx +10 -1
- package/dist/frontend-core/template/src/pages/login/login.page.tsx +1 -1
- package/dist/frontend-core/template/vite.config.ts +5 -0
- package/dist/frontend-core/types/component.d.ts +1 -1
- package/dist/frontend-core/types/contextprovider.d.ts +1 -1
- package/dist/frontend-core/types/hook.d.ts +1 -1
- package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js +1 -1
- package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js.map +1 -1
- package/dist/frontend-forms/generators/enum/inputs.generator.js +1 -1
- package/dist/frontend-forms/generators/enum/inputs.generator.js.map +1 -1
- package/dist/frontend-trpc-client/generators/model-hook.generator.js +104 -39
- package/dist/frontend-trpc-client/generators/model-hook.generator.js.map +1 -1
- package/dist/frontend-trpc-client/trpc-client.generator.js +28 -14
- package/dist/frontend-trpc-client/trpc-client.generator.js.map +1 -1
- package/dist/types/types.generator.d.ts +7 -0
- package/dist/types/types.generator.js +80 -0
- package/dist/types/types.generator.js.map +1 -1
- package/package.json +3 -3
|
@@ -11,7 +11,8 @@ function generateActionExecutionInterface({ actions, types }) {
|
|
|
11
11
|
.from(execution.interface.location)
|
|
12
12
|
.addType(actions.summary.action)
|
|
13
13
|
.addType(types.modelNames)
|
|
14
|
-
.addType(types.user)
|
|
14
|
+
.addType(types.user)
|
|
15
|
+
.addType(types.userRoles);
|
|
15
16
|
return /* ts */ `
|
|
16
17
|
${imports.generate()}
|
|
17
18
|
|
|
@@ -28,7 +29,8 @@ export const ${execution.interface.toBrandedActionOperationId.name} = (id: strin
|
|
|
28
29
|
export interface ${execution.interface.name} {
|
|
29
30
|
name: string
|
|
30
31
|
user: User
|
|
31
|
-
|
|
32
|
+
userRoles: UserRoles
|
|
33
|
+
init({ action, user, userRoles }: { action: Action; user: User; userRoles: UserRoles }): Promise<void>
|
|
32
34
|
|
|
33
35
|
/**
|
|
34
36
|
* Marks the ActionExecution as finished successfully.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-interface.generator.js","sourceRoot":"","sources":["../../../src/backend-actions/generators/execution-interface.generator.ts"],"names":[],"mappings":";;AAIA,
|
|
1
|
+
{"version":3,"file":"execution-interface.generator.js","sourceRoot":"","sources":["../../../src/backend-actions/generators/execution-interface.generator.ts"],"names":[],"mappings":";;AAIA,4EA2OC;AA/OD,iDAAmD;AAInD,SAAgB,gCAAgC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAiB;IAChF,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAC7B,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,GAAG,SAAS,CAAA;IAC/D,MAAM,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAA;IAErD,MAAM,OAAO,GAAG,2BAAe;QAC7B,EAAE;SACD,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC;SAClC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;SAC/B,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;SACzB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;SACnB,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAE3B,OAAO,QAAQ,CAAC;EAChB,OAAO,CAAC,QAAQ,EAAE;;cAEN,EAAE;;;iCAGiB,EAAE;;eAEpB,SAAS,CAAC,SAAS,CAAC,0BAA0B,CAAC,IAAI,oBAAoB,EAAE,aAAa,EAAE;;;;;mBAKpF,SAAS,CAAC,SAAS,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;IAoBvC,SAAS,CAAC,MAAM,CAAC,KAAK;;;;;;gBAMV,EAAE;;IAEd,SAAS,CAAC,UAAU,CAAC,KAAK;;;;;;gBAMd,EAAE;;IAEd,SAAS,CAAC,MAAM,CAAC,KAAK;;;;;;;;;;gBAUV,EAAE;;IAEd,SAAS,CAAC,UAAU,CAAC,KAAK;;;;;;;;gBAQd,EAAE;;IAEd,SAAS,CAAC,MAAM,CAAC,KAAK;;;;;;;;gBAQV,EAAE;;IAEd,SAAS,CAAC,UAAU,CAAC,KAAK;;;;;;;;gBAQd,EAAE;;IAEd,SAAS,CAAC,KAAK,CAAC,KAAK;;;;;;;;gBAQT,EAAE;;IAEd,SAAS,CAAC,MAAM,CAAC,MAAM;;;;;yBAKF,EAAE;;;;;IAKvB,SAAS,CAAC,UAAU,CAAC,MAAM;;;;;yBAKN,EAAE;;;;;IAKvB,SAAS,CAAC,MAAM,CAAC,MAAM,+DAA+D,EAAE;;IAExF,SAAS,CAAC,UAAU,CAAC,MAAM,gEAAgE,EAAE;;IAE7F,SAAS,CAAC,MAAM,CAAC,MAAM,gDAAgD,EAAE;;IAEzE,SAAS,CAAC,UAAU,CAAC,MAAM,gDAAgD,EAAE;;IAE7E,SAAS,CAAC,KAAK,CAAC,MAAM,8DAA8D,EAAE;;IAEtF,cAAc,CAAC,eAAe;;;;IAI9B,cAAc,CAAC,eAAe;;;;;;;IAO9B,cAAc,CAAC,eAAe;;;;;;;;IAQ9B,cAAc,CAAC,eAAe;;;;;;;;;IAS9B,cAAc,CAAC,eAAe;;;;;;;;;;IAU9B,cAAc,CAAC,eAAe;;;;;;;;;;;IAW9B,cAAc,CAAC,eAAe;;;;;;;;;;;;;IAa9B,cAAc,CAAC,aAAa;;;;;;;;;;IAU5B,cAAc,CAAC,KAAK;;;;;;gBAMR,EAAE;;IAEd,cAAc,CAAC,MAAM;;;;yBAIA,EAAE;;;;IAIvB,cAAc,uDAAuD,EAAE;;CAE1E,CAAA;AACD,CAAC"}
|
|
@@ -14,15 +14,15 @@ export const ai = router({
|
|
|
14
14
|
ask: procedure
|
|
15
15
|
.use(authMiddleware)
|
|
16
16
|
.input(zAskTaskInput)
|
|
17
|
-
.mutation(async ({ input, ctx }) => ctx.aiAgent.startExecution(input, ctx.user.id)),
|
|
17
|
+
.mutation(async ({ input, ctx }) => ctx.aiAgent.startExecution(input, ctx.viewer.user.id)),
|
|
18
18
|
step: procedure
|
|
19
19
|
.use(authMiddleware)
|
|
20
20
|
.input(zAskStepInput)
|
|
21
|
-
.mutation(async ({ input, ctx }) => ctx.aiAgent.continueExecution(input, ctx.user.id)),
|
|
21
|
+
.mutation(async ({ input, ctx }) => ctx.aiAgent.continueExecution(input, ctx.viewer.user.id)),
|
|
22
22
|
cancel: procedure
|
|
23
23
|
.use(authMiddleware)
|
|
24
24
|
.input(z.object({ conversation: z.string() }))
|
|
25
|
-
.mutation(({ input, ctx }) => ctx.aiAgent.cancelExecution(input.conversation, ctx.user.id)),
|
|
25
|
+
.mutation(({ input, ctx }) => ctx.aiAgent.cancelExecution(input.conversation, ctx.viewer.user.id)),
|
|
26
26
|
})
|
|
27
27
|
`;
|
|
28
28
|
}
|
|
@@ -63,6 +63,7 @@ exports.generator = {
|
|
|
63
63
|
code: Generator.ts(`AuthenticationModule.forRoot(config.auth)`),
|
|
64
64
|
},
|
|
65
65
|
envConfig: {
|
|
66
|
+
imports: [Generator.ts(`import { parseStringList } from '@authentication/utils'`)],
|
|
66
67
|
decoder: Generator.ts(`
|
|
67
68
|
AUTH: zEnvBoolean.optional().default(true),
|
|
68
69
|
KEYCLOAK_URL: z.string().url().transform((val) => new URL(val)),
|
|
@@ -70,10 +71,17 @@ exports.generator = {
|
|
|
70
71
|
KEYCLOAK_CLIENT_SECRET: z.string(),
|
|
71
72
|
KEYCLOAK_REALM: z.string(),
|
|
72
73
|
KEYCLOAK_REDIRECT_URL: z.string().url().transform((val) => new URL(val)),
|
|
73
|
-
KEYCLOAK_LOGOUT_REDIRECT_URL: z.string().url().transform((val) => new URL(val))
|
|
74
|
+
KEYCLOAK_LOGOUT_REDIRECT_URL: z.string().url().transform((val) => new URL(val)),
|
|
75
|
+
AUTH_MOCK_SUB: z.string().optional(),
|
|
76
|
+
AUTH_MOCK_NAME: z.string().optional(),
|
|
77
|
+
AUTH_MOCK_EMAIL: z.string().optional(),
|
|
78
|
+
AUTH_MOCK_ROLES: z.string().optional(),
|
|
79
|
+
AUTH_MOCK_GROUPS: z.string().optional(),
|
|
80
|
+
AUTH_TEST_OVERRIDES: zEnvBoolean.optional().default(false),`),
|
|
74
81
|
transformer: Generator.ts(`
|
|
75
82
|
auth: val.AUTH ? {
|
|
76
83
|
enableAuthentication: true as const,
|
|
84
|
+
roleClaimPath: ${JSON.stringify(context.schema.auth?.roleClaimPath ?? 'realm_access.roles')},
|
|
77
85
|
url: val.API_URL,
|
|
78
86
|
urlPrefix: val.API_PREFIX,
|
|
79
87
|
|
|
@@ -89,6 +97,14 @@ exports.generator = {
|
|
|
89
97
|
postLogoutRedirectUrl: val.KEYCLOAK_LOGOUT_REDIRECT_URL,
|
|
90
98
|
} : {
|
|
91
99
|
enableAuthentication: false as const,
|
|
100
|
+
mockIdentity: {
|
|
101
|
+
sub: val.AUTH_MOCK_SUB ?? 'test',
|
|
102
|
+
name: val.AUTH_MOCK_NAME ?? 'Test User',
|
|
103
|
+
email: val.AUTH_MOCK_EMAIL ?? 'test@postxl.com',
|
|
104
|
+
roles: parseStringList(val.AUTH_MOCK_ROLES, ['viewer']),
|
|
105
|
+
groups: parseStringList(val.AUTH_MOCK_GROUPS),
|
|
106
|
+
},
|
|
107
|
+
allowTestOverrides: val.AUTH_TEST_OVERRIDES,
|
|
92
108
|
}`),
|
|
93
109
|
dotEnvExample: `
|
|
94
110
|
KEYCLOAK_URL=http://localhost:8080
|
|
@@ -97,6 +113,11 @@ exports.generator = {
|
|
|
97
113
|
KEYCLOAK_REALM=postxl
|
|
98
114
|
KEYCLOAK_REDIRECT_URL=\${API_URL}/auth/callback
|
|
99
115
|
KEYCLOAK_LOGOUT_REDIRECT_URL=\${FRONTEND_URL}
|
|
116
|
+
AUTH_MOCK_SUB=test
|
|
117
|
+
AUTH_MOCK_NAME="Test User"
|
|
118
|
+
AUTH_MOCK_EMAIL=test@postxl.com
|
|
119
|
+
AUTH_MOCK_GROUPS=
|
|
120
|
+
AUTH_TEST_OVERRIDES=false
|
|
100
121
|
`,
|
|
101
122
|
},
|
|
102
123
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authentication.generator.js","sourceRoot":"","sources":["../../src/backend-authentication/authentication.generator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAmC;AAEnC,6DAA8C;AAE9C,wDAA2E;AAC3E,kDAA+E;AAC/E,kDAAkE;AAClE,kCAAmD;AAGnD,4EAAqE;AACrE,kGAA2F;AAC3F,oGAA6F;AAC7F,gGAAyF;AAiB5E,QAAA,WAAW,GAAG,SAAS,CAAC,sBAAsB,CAAC,wBAAwB,CAAC,CAAA;AAExE,QAAA,SAAS,GAAiC;IACrD,EAAE,EAAE,mBAAW;IACf,QAAQ,EAAE,CAAC,iCAAkB,EAAE,sBAAe,EAAE,qCAAsB,EAAE,2CAAyB,CAAC;IAElG,QAAQ,EAAE,CAAsC,OAAgB,EAAiB,EAAE;QACjF,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC3G,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,CAC3C,EAAE,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE,EACrD,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE,EACnD,EAAE,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE,EACrD,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,EACjD,EAAE,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,CACpD,CAAA;QAED,MAAM,MAAM,GAAiE;YAC3E,IAAI,EAAE,SAAS,CAAC,WAAW,CAAC,sBAAsB,CAAC;YACnD,QAAQ,EAAE,SAAS,CAAC,uBAAuB,CAAC,uCAAuC,CAAC;YACpF,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,yBAAyB,CAAC;SAC3D,CAAA;QACD,MAAM,oBAAoB,GAAiB;YACzC,IAAI,EAAE,SAAS,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;YACrD,WAAW,EAAE,MAAM;YACnB,qBAAqB,EAAE;gBACrB,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC,2CAA2C,CAAC;aAChE;YACD,SAAS,EAAE;gBACT,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC
|
|
1
|
+
{"version":3,"file":"authentication.generator.js","sourceRoot":"","sources":["../../src/backend-authentication/authentication.generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,7 +39,6 @@ function generateAuthGuard(context) {
|
|
|
39
39
|
const imports = Generator.ImportGenerator.from(context.authentication.guard._filePath);
|
|
40
40
|
imports.add(context.view.service);
|
|
41
41
|
imports.add(context.actions.dispatcher);
|
|
42
|
-
imports.add(context.types.user);
|
|
43
42
|
imports.add({ name: context.authentication.service.name, location: context.authentication.service._filePath });
|
|
44
43
|
return /* ts */ `
|
|
45
44
|
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'
|
|
@@ -48,9 +47,10 @@ import { FastifyRequest } from 'fastify'
|
|
|
48
47
|
|
|
49
48
|
${imports.generate()}
|
|
50
49
|
|
|
51
|
-
import {
|
|
50
|
+
import type { AuthorizationContext } from '@types'
|
|
51
|
+
import { UserInfo } from './authentication.types'
|
|
52
52
|
|
|
53
|
-
export type Viewer =
|
|
53
|
+
export type Viewer = AuthorizationContext
|
|
54
54
|
|
|
55
55
|
export type FastifyRequestWithViewer = FastifyRequest & { viewer: Viewer }
|
|
56
56
|
@Injectable()
|
|
@@ -68,10 +68,7 @@ export class ${context.authentication.guard.name} implements CanActivate {
|
|
|
68
68
|
let viewer: Viewer | null = null
|
|
69
69
|
|
|
70
70
|
let userInfo: UserInfo | null = null
|
|
71
|
-
let userRoles:
|
|
72
|
-
|
|
73
|
-
// TODO: Add authorization check
|
|
74
|
-
const isAuthorized = true
|
|
71
|
+
let userRoles: Viewer['userRoles'] = []
|
|
75
72
|
|
|
76
73
|
const associatedUserInfo = await this.authService.getUserInfoFromRequest(req)
|
|
77
74
|
|
|
@@ -105,7 +102,7 @@ export class ${context.authentication.guard.name} implements CanActivate {
|
|
|
105
102
|
}
|
|
106
103
|
}
|
|
107
104
|
|
|
108
|
-
viewer = {
|
|
105
|
+
viewer = { userRoles, user }
|
|
109
106
|
}
|
|
110
107
|
|
|
111
108
|
if (!viewer) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-guard.generator.js","sourceRoot":"","sources":["../../../src/backend-authentication/generators/auth-guard.generator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,
|
|
1
|
+
{"version":3,"file":"auth-guard.generator.js","sourceRoot":"","sources":["../../../src/backend-authentication/generators/auth-guard.generator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,8CAgFC;AApFD,6DAA8C;AAI9C,SAAgB,iBAAiB,CAAC,OAAsB;IACtD,MAAM,OAAO,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAEtF,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACjC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACvC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;IAC9G,OAAO,QAAQ,CAAC;;;;;EAKhB,OAAO,CAAC,QAAQ,EAAE;;;;;;;;;eASL,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI;;oCAEZ,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI;oCACnC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;0CACnB,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuDvE,CAAA;AACF,CAAC"}
|
|
@@ -14,9 +14,12 @@ import jwt from 'jsonwebtoken'
|
|
|
14
14
|
import { JwksClient } from 'jwks-rsa'
|
|
15
15
|
import { OidcClient } from 'oidc-client-ts'
|
|
16
16
|
|
|
17
|
+
import { USER_ROLES } from '@types'
|
|
18
|
+
import type { UserRole, UserRoles } from '@types'
|
|
19
|
+
|
|
17
20
|
import type { AuthenticationConfig_EnabledKeycloak } from './authentication.config'
|
|
18
|
-
import { authenticationCookieName, UserInfo,
|
|
19
|
-
import { unknownToErrorMessage } from './utils'
|
|
21
|
+
import { authenticationCookieName, UserInfo, zUserInfo } from './authentication.types'
|
|
22
|
+
import { getByPath, parseStringList, unknownToErrorMessage } from './utils'
|
|
20
23
|
|
|
21
24
|
/**
|
|
22
25
|
* State object for the authentication service.
|
|
@@ -282,14 +285,14 @@ export class ${context.authentication.service.name} implements OnModuleInit {
|
|
|
282
285
|
const decoded = await _jwtVerify(accessToken, getKey, { algorithms: ['RS256'] })
|
|
283
286
|
|
|
284
287
|
if (typeof decoded === 'object' && decoded !== null) {
|
|
285
|
-
const rawUserRoles = decoded.
|
|
288
|
+
const rawUserRoles = getByPath(decoded, this.config.roleClaimPath)
|
|
289
|
+
const normalizedUserRoles = Array.isArray(rawUserRoles) ? rawUserRoles : parseStringList(rawUserRoles)
|
|
286
290
|
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
+
const filteredRoles = normalizedUserRoles.filter(
|
|
292
|
+
(role): role is UserRole => typeof role === 'string' && USER_ROLES.includes(role as UserRole),
|
|
293
|
+
)
|
|
291
294
|
|
|
292
|
-
return { ok:
|
|
295
|
+
return { ok: true, userRoles: filteredRoles }
|
|
293
296
|
}
|
|
294
297
|
|
|
295
298
|
return { ok: true, userRoles: [] }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authentication-service.generator.js","sourceRoot":"","sources":["../../../src/backend-authentication/generators/authentication-service.generator.ts"],"names":[],"mappings":";;AAEA,
|
|
1
|
+
{"version":3,"file":"authentication-service.generator.js","sourceRoot":"","sources":["../../../src/backend-authentication/generators/authentication-service.generator.ts"],"names":[],"mappings":";;AAEA,sEAuYC;AAvYD,SAAgB,6BAA6B,CAAC,OAAsB;IAClE,OAAO,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAgCH,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI;yCACT,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoW1E,CAAA;AACF,CAAC"}
|
|
@@ -5,6 +5,7 @@ function generateAuthenticationTypes(context) {
|
|
|
5
5
|
return /* ts */ `
|
|
6
6
|
import { z } from 'zod'
|
|
7
7
|
import { Result } from '@postxl/utils'
|
|
8
|
+
import { USER_ROLES } from '@types'
|
|
8
9
|
import { Viewer } from '@authentication/auth.guard'
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -42,12 +43,12 @@ export const z${context.authentication.types.userInfo.name} = z.object({
|
|
|
42
43
|
*/
|
|
43
44
|
export type ${context.authentication.types.userInfo.name} = z.infer<typeof z${context.authentication.types.userInfo.name}>
|
|
44
45
|
|
|
45
|
-
export const
|
|
46
|
+
export const zUserRole = z.enum(USER_ROLES)
|
|
46
47
|
|
|
47
|
-
export
|
|
48
|
+
export const z${context.authentication.types.userRoles.name} = z.array(zUserRole)
|
|
48
49
|
|
|
49
50
|
export type ViewerResult = Result<
|
|
50
|
-
|
|
51
|
+
Viewer,
|
|
51
52
|
| {
|
|
52
53
|
type: 'redirect'
|
|
53
54
|
redirectUrl: string
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authentication-types.generator.js","sourceRoot":"","sources":["../../../src/backend-authentication/generators/authentication-types.generator.ts"],"names":[],"mappings":";;AAEA,
|
|
1
|
+
{"version":3,"file":"authentication-types.generator.js","sourceRoot":"","sources":["../../../src/backend-authentication/generators/authentication-types.generator.ts"],"names":[],"mappings":";;AAEA,kEA4DC;AA5DD,SAAgB,2BAA2B,CAAC,OAAsB;IAChE,OAAO,QAAQ,CAAC;;;;;;;KAOb,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI;;;gBAG/B,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2BrD,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI;;cAEjC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,sBAAsB,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI;;;;gBAIxG,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI;;;;;;;;;;;;;;;CAe1D,CAAA;AACD,CAAC"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
export type AuthenticationConfig = AuthenticationConfig_Disabled | AuthenticationConfig_EnabledKeycloak
|
|
2
2
|
export type AuthenticationConfig_Disabled = {
|
|
3
3
|
enableAuthentication: false
|
|
4
|
+
mockIdentity: {
|
|
5
|
+
sub: string
|
|
6
|
+
name: string
|
|
7
|
+
email: string
|
|
8
|
+
roles: string[]
|
|
9
|
+
groups: string[]
|
|
10
|
+
}
|
|
11
|
+
allowTestOverrides: boolean
|
|
4
12
|
}
|
|
5
13
|
export type AuthenticationConfig_EnabledKeycloak = {
|
|
6
14
|
enableAuthentication: true
|
|
15
|
+
roleClaimPath: string
|
|
7
16
|
/**
|
|
8
17
|
* The URL of the backend server.
|
|
9
18
|
*/
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// We import Fastify cookie here to ensure that the cookie plugin and its types are registered.
|
|
2
2
|
import '@fastify/cookie'
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { FastifyRequest } from 'fastify'
|
|
5
|
+
|
|
6
|
+
import type { UserRoles } from '@types'
|
|
7
|
+
|
|
8
|
+
import type { AuthenticationConfig_Disabled } from './authentication.config'
|
|
9
|
+
import { zUserRoles } from './authentication.types'
|
|
10
|
+
import type { UserInfo } from './authentication.types'
|
|
11
|
+
import { parseStringList } from './utils'
|
|
5
12
|
|
|
6
13
|
type MockAuthenticationResult = {
|
|
7
14
|
/**
|
|
@@ -49,6 +56,54 @@ const mockResult: MockAuthenticationResult = {
|
|
|
49
56
|
|
|
50
57
|
export class MockAuthenticationService {
|
|
51
58
|
public readonly cookieDomain = 'localhost'
|
|
59
|
+
private readonly mockResult: MockAuthenticationResult
|
|
60
|
+
|
|
61
|
+
constructor(private readonly config: AuthenticationConfig_Disabled) {
|
|
62
|
+
const parsedConfigRoles = zUserRoles.safeParse(config.mockIdentity.roles)
|
|
63
|
+
|
|
64
|
+
this.mockResult = {
|
|
65
|
+
...mockResult,
|
|
66
|
+
userInfo: {
|
|
67
|
+
...mockResult.userInfo,
|
|
68
|
+
sub: config.mockIdentity.sub,
|
|
69
|
+
name: config.mockIdentity.name,
|
|
70
|
+
preferred_username: config.mockIdentity.email,
|
|
71
|
+
given_name: config.mockIdentity.name.split(' ').at(0) ?? config.mockIdentity.name,
|
|
72
|
+
family_name: config.mockIdentity.name.split(' ').slice(1).join(' ') || config.mockIdentity.name,
|
|
73
|
+
email: config.mockIdentity.email,
|
|
74
|
+
groups: config.mockIdentity.groups,
|
|
75
|
+
},
|
|
76
|
+
userRoles: parsedConfigRoles.success ? parsedConfigRoles.data : mockResult.userRoles,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private parseHeaderRoles(raw: unknown): UserRoles {
|
|
81
|
+
const parsed = zUserRoles.safeParse(parseStringList(raw, this.mockResult.userRoles))
|
|
82
|
+
return parsed.success ? parsed.data : this.mockResult.userRoles
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private getTestOverrideRoles(req: FastifyRequest | undefined): UserRoles | null {
|
|
86
|
+
// Test override headers are only honored when:
|
|
87
|
+
// - authentication is disabled (`AUTH=false`) and
|
|
88
|
+
// - explicit test overrides are enabled (`AUTH_TEST_OVERRIDES=true`) and
|
|
89
|
+
// - runtime is test (`NODE_ENV=test`)
|
|
90
|
+
if (!this.config.allowTestOverrides || process.env.NODE_ENV !== 'test' || !req) {
|
|
91
|
+
return null
|
|
92
|
+
}
|
|
93
|
+
const rawRoles = req.headers['x-pxl-test-roles']
|
|
94
|
+
return this.parseHeaderRoles(rawRoles)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private getTestOverrideSub(req: FastifyRequest | undefined): string | undefined {
|
|
98
|
+
if (!this.config.allowTestOverrides || process.env.NODE_ENV !== 'test' || !req) {
|
|
99
|
+
return undefined
|
|
100
|
+
}
|
|
101
|
+
const rawSub = req.headers['x-pxl-test-sub']
|
|
102
|
+
if (typeof rawSub !== 'string' || rawSub.trim().length === 0) {
|
|
103
|
+
return undefined
|
|
104
|
+
}
|
|
105
|
+
return rawSub.trim()
|
|
106
|
+
}
|
|
52
107
|
|
|
53
108
|
public refreshAccessToken(): Promise<
|
|
54
109
|
| {
|
|
@@ -62,7 +117,7 @@ export class MockAuthenticationService {
|
|
|
62
117
|
error: unknown
|
|
63
118
|
}
|
|
64
119
|
> {
|
|
65
|
-
return Promise.resolve({ ok: true, accessToken: mockResult.accessToken, state: null }) // NOSONAR - We want to adhere to the interface
|
|
120
|
+
return Promise.resolve({ ok: true, accessToken: this.mockResult.accessToken, state: null }) // NOSONAR - We want to adhere to the interface
|
|
66
121
|
}
|
|
67
122
|
public getAccessTokenFromURL(): Promise<
|
|
68
123
|
| {
|
|
@@ -75,36 +130,45 @@ export class MockAuthenticationService {
|
|
|
75
130
|
error: unknown
|
|
76
131
|
}
|
|
77
132
|
> {
|
|
78
|
-
return Promise.resolve({ ok: true, accessToken: mockResult.accessToken, state: null }) // NOSONAR - We want to adhere to the interface
|
|
133
|
+
return Promise.resolve({ ok: true, accessToken: this.mockResult.accessToken, state: null }) // NOSONAR - We want to adhere to the interface
|
|
79
134
|
}
|
|
80
135
|
public getAuthenticationUrl(): Promise<string> {
|
|
81
|
-
return Promise.resolve(mockResult.authRedirectUrl) // NOSONAR - We want to adhere to the interface
|
|
136
|
+
return Promise.resolve(this.mockResult.authRedirectUrl) // NOSONAR - We want to adhere to the interface
|
|
82
137
|
}
|
|
83
138
|
|
|
84
|
-
public async getUserInfoFromRequest(): Promise<{ ok: true; userInfo: UserInfo } | { ok: false }> {
|
|
85
|
-
const info = await this.getUserInfo()
|
|
139
|
+
public async getUserInfoFromRequest(req?: FastifyRequest): Promise<{ ok: true; userInfo: UserInfo } | { ok: false }> {
|
|
140
|
+
const info = await this.getUserInfo(req)
|
|
86
141
|
|
|
87
142
|
return info
|
|
88
143
|
}
|
|
89
144
|
|
|
90
|
-
public getUserInfo(): Promise<{ ok: true; userInfo: UserInfo } | { ok: false }> {
|
|
145
|
+
public getUserInfo(req?: FastifyRequest): Promise<{ ok: true; userInfo: UserInfo } | { ok: false }> {
|
|
146
|
+
const overrideSub = this.getTestOverrideSub(req)
|
|
91
147
|
// NOSONAR - We want to keep all validations async to adhere to the same interface
|
|
92
148
|
return Promise.resolve({
|
|
93
149
|
ok: true,
|
|
94
|
-
userInfo:
|
|
150
|
+
userInfo: {
|
|
151
|
+
...this.mockResult.userInfo,
|
|
152
|
+
sub: overrideSub ?? this.mockResult.userInfo.sub,
|
|
153
|
+
},
|
|
95
154
|
})
|
|
96
155
|
}
|
|
97
156
|
|
|
98
|
-
public async getUserRolesFromRequest(
|
|
99
|
-
|
|
157
|
+
public async getUserRolesFromRequest(
|
|
158
|
+
req?: FastifyRequest,
|
|
159
|
+
): Promise<{ ok: true; userRoles: UserRoles } | { ok: false }> {
|
|
160
|
+
const roles = await this.getUserRoles(req)
|
|
100
161
|
|
|
101
162
|
return roles
|
|
102
163
|
}
|
|
103
164
|
|
|
104
|
-
public getUserRoles(): Promise<{ ok: true; userRoles: UserRoles } | { ok: false }> {
|
|
105
|
-
return Promise.resolve({
|
|
165
|
+
public getUserRoles(req?: FastifyRequest): Promise<{ ok: true; userRoles: UserRoles } | { ok: false }> {
|
|
166
|
+
return Promise.resolve({
|
|
167
|
+
ok: true,
|
|
168
|
+
userRoles: this.getTestOverrideRoles(req) ?? this.mockResult.userRoles,
|
|
169
|
+
}) // NOSONAR - We want to adhere to the interface
|
|
106
170
|
}
|
|
107
171
|
public getLogoutUrl(): Promise<string> {
|
|
108
|
-
return Promise.resolve(mockResult.logoutRedirectUrl) // NOSONAR - We want to adhere to the interface
|
|
172
|
+
return Promise.resolve(this.mockResult.logoutRedirectUrl) // NOSONAR - We want to adhere to the interface
|
|
109
173
|
}
|
|
110
174
|
}
|
|
@@ -11,3 +11,48 @@ export function unknownToErrorMessage(error: unknown, message: string): string {
|
|
|
11
11
|
export const normalizeUrl = (url: string): string => {
|
|
12
12
|
return url.endsWith('/') ? url : `${url}/`
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parses role/group lists from JSON-array or CSV strings.
|
|
17
|
+
*/
|
|
18
|
+
export function parseStringList(raw: unknown, fallback: string[] = []): string[] {
|
|
19
|
+
if (typeof raw !== 'string' || raw.trim().length === 0) {
|
|
20
|
+
return fallback
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const parsed = JSON.parse(raw)
|
|
25
|
+
if (Array.isArray(parsed)) {
|
|
26
|
+
return parsed
|
|
27
|
+
.filter((entry): entry is string => typeof entry === 'string')
|
|
28
|
+
.map((entry) => entry.trim())
|
|
29
|
+
.filter(Boolean)
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
// ignore and use csv fallback
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return raw
|
|
36
|
+
.split(',')
|
|
37
|
+
.map((entry) => entry.trim())
|
|
38
|
+
.filter(Boolean)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Resolves a nested value by dot-path (e.g. "realm_access.roles").
|
|
43
|
+
*/
|
|
44
|
+
export function getByPath(input: unknown, path: string): unknown {
|
|
45
|
+
if (!path) {
|
|
46
|
+
return undefined
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let current: unknown = input
|
|
50
|
+
for (const segment of path.split('.').filter(Boolean)) {
|
|
51
|
+
if (typeof current !== 'object' || current === null || !(segment in current)) {
|
|
52
|
+
return undefined
|
|
53
|
+
}
|
|
54
|
+
current = (current as Record<string, unknown>)[segment]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return current
|
|
58
|
+
}
|
|
@@ -78,7 +78,23 @@ const baseScripts = [
|
|
|
78
78
|
{ name: 'start', command: 'node ./dist/apps/api/apps/api/src/main.js' },
|
|
79
79
|
{
|
|
80
80
|
name: 'dev',
|
|
81
|
-
command: 'dotenvx run -f ./apps/api/.env --env STATEFUL=false --env AUTH=false -- nest start --debug --watch',
|
|
81
|
+
command: 'dotenvx run -f ./apps/api/.env --env STATEFUL=false --env AUTH=false --env AUTH_MOCK_ROLES=admin -- nest start --debug --watch',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'dev:viewer',
|
|
85
|
+
command: 'dotenvx run -f ./apps/api/.env --env STATEFUL=false --env AUTH=false --env AUTH_MOCK_ROLES=viewer -- nest start --debug --watch',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'dev:editor',
|
|
89
|
+
command: 'dotenvx run -f ./apps/api/.env --env STATEFUL=false --env AUTH=false --env AUTH_MOCK_ROLES=editor -- nest start --debug --watch',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'dev:admin',
|
|
93
|
+
command: 'dotenvx run -f ./apps/api/.env --env STATEFUL=false --env AUTH=false --env AUTH_MOCK_ROLES=admin -- nest start --debug --watch',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'dev:superadmin',
|
|
97
|
+
command: 'dotenvx run -f ./apps/api/.env --env STATEFUL=false --env AUTH=false --env AUTH_MOCK_ROLES=superadmin -- nest start --debug --watch',
|
|
82
98
|
},
|
|
83
99
|
{
|
|
84
100
|
name: 'dev:auth',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.generator.js","sourceRoot":"","sources":["../../src/backend-core/backend.generator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAiC;AAEjC,6DAA8C;AAE9C,4EAAqE;AACrE,4EAAqE;AACrE,oFAA6E;AAC7E,8EAAuE;AACvE,gEAA0D;AAC1D,wEAAkE;AAGlE,MAAM,gBAAgB,GAAkC;IACtD,EAAE,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACrD,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE;IACnD,EAAE,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACrD,EAAE,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE;IACrD,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE;IACnD,EAAE,WAAW,EAAE,0BAA0B,EAAE,OAAO,EAAE,SAAS,EAAE;IAC/D,EAAE,WAAW,EAAE,oBAAoB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACxD,EAAE,WAAW,EAAE,SAAS,CAAC,mBAAmB,CAAC,eAAe,CAAC,EAAE;IAC/D,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE;IAC3C,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE;IACjD,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE;IAC7C,8FAA8F;IAC9F,EAAE,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,EAAE;IACpD,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE;IACxC,EAAE,WAAW,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO,EAAE;CAC1D,CAAA;AACD,MAAM,mBAAmB,GAAkC;IACzD,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE;IAC5C,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE;IAC5C,EAAE,WAAW,EAAE,kBAAkB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACtD,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE;IACnD,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE;IAClD,EAAE,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE;IACnD,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE;IACjD,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC1C,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC7C,EAAE,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE;IACnD,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE;IAC/C,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE;CAC/C,CAAA;AAED,MAAM,WAAW,GAA8B;IAC7C,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE;IACxC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,2CAA2C,EAAE;IACvE;QACE,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"backend.generator.js","sourceRoot":"","sources":["../../src/backend-core/backend.generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateApiConfig = generateApiConfig;
|
|
4
4
|
function generateApiConfig({ backend: { modules } }) {
|
|
5
|
+
const envConfigImports = Array.from(new Set(modules
|
|
6
|
+
.flatMap((module) => module.envConfig?.imports ?? [])
|
|
7
|
+
.map((statement) => statement.trim())
|
|
8
|
+
.filter(Boolean)));
|
|
5
9
|
return /*ts*/ `
|
|
6
10
|
import z from 'zod'
|
|
11
|
+
${envConfigImports.join('\n')}
|
|
7
12
|
|
|
8
13
|
const zEnvBoolean = z.union([
|
|
9
14
|
//
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-config.generator.js","sourceRoot":"","sources":["../../../src/backend-core/generators/api-config.generator.ts"],"names":[],"mappings":";;AAEA,
|
|
1
|
+
{"version":3,"file":"api-config.generator.js","sourceRoot":"","sources":["../../../src/backend-core/generators/api-config.generator.ts"],"names":[],"mappings":";;AAEA,8CA0EC;AA1ED,SAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAe;IACrE,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CACjC,IAAI,GAAG,CACL,OAAO;SACJ,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,IAAI,EAAE,CAAC;SACpD,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;SACpC,MAAM,CAAC,OAAO,CAAC,CACnB,CACF,CAAA;IAED,OAAO,MAAM,CAAC;;EAEd,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA6BvB,OAAO;SACN,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;SAC1B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,SAAU,CAAC,OAAO,CAAC,EAAE,CAAC;SAC1D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;SACvB,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;MAeZ,OAAO;SACN,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;SAC1B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,SAAU,CAAC,WAAW,CAAC,EAAE,CAAC;SAC9D,IAAI,CAAC,KAAK,CAAC;;;;;;EAMhB,OAAO;SACN,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,SAAU,CAAC,IAAK,CAAC,EAAE,CAAC,CAAC,qDAAqD;SAC9G,IAAI,CAAC,IAAI,CAAC;CACZ,CAAA;AACD,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;AACnC,CAAC"}
|
|
@@ -100,6 +100,10 @@ export type NestJSModule = {
|
|
|
100
100
|
vfs?: Generator.VirtualFileSystem;
|
|
101
101
|
};
|
|
102
102
|
export type EnvConfig = {
|
|
103
|
+
/**
|
|
104
|
+
* Optional import statements required by decoder/transformer code.
|
|
105
|
+
*/
|
|
106
|
+
imports?: Generator.Typescript[];
|
|
103
107
|
/**
|
|
104
108
|
* Example:
|
|
105
109
|
* AWS_ACCESS_KEY: z.string(),
|