@dudousxd/nestjs-authz-codegen 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # @dudousxd/nestjs-authz-codegen
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#2](https://github.com/DavideCarvalho/nestjs-authz/pull/2) [`2ecb0f4`](https://github.com/DavideCarvalho/nestjs-authz/commit/2ecb0f46342fa4527fc01f1097720f2e7bcf9aa7) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Initial release of `@dudousxd/nestjs-authz-codegen`: a `@dudousxd/nestjs-codegen` extension that
8
+ discovers `@Can(ability, Resource?)` decorators on your controllers (and, optionally, `@Policy`
9
+ method abilities) and emits a typed `can()` helper into your generated `api.ts`. The discovered
10
+ abilities become a string-literal `AuthzAbility` union, so calling `can()` with an ability that
11
+ doesn't exist on the server is a compile-time error. Routes carrying a `@Can` also expose a
12
+ route-pinned `can()` handle member when a client layer is active.
13
+
14
+ ### Patch Changes
15
+
16
+ - [#2](https://github.com/DavideCarvalho/nestjs-authz/pull/2) [`2ecb0f4`](https://github.com/DavideCarvalho/nestjs-authz/commit/2ecb0f46342fa4527fc01f1097720f2e7bcf9aa7) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - The emitted `can()` now delegates to `@dudousxd/nestjs-authz-client` instead of a
17
+ hand-rolled POST. The generated `api.ts` imports `AbilityStore` + `createCan`, exports a
18
+ shared `authzStore` you hydrate once, and `can()` is a thin typed wrapper over the store's
19
+ `createCan` resolver — so a hydrated decision is answered synchronously with NO request,
20
+ and a cache miss uses the same configurable `'fetch'` fallback to the `endpoint`. The
21
+ compile-time `AuthzAbility` string-literal union is unchanged (a wrong ability is still a
22
+ type error). Adds `@dudousxd/nestjs-authz-client` as an optional peer dependency.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Davi Carvalho
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # @dudousxd/nestjs-authz-codegen
2
+
3
+ A [`@dudousxd/nestjs-codegen`](https://www.npmjs.com/package/@dudousxd/nestjs-codegen) **extension**
4
+ that discovers the authorization abilities declared with
5
+ [`@dudousxd/nestjs-authz`](https://github.com/DavideCarvalho/nestjs-authz)'s
6
+ `@Can(ability, Resource?)` (and, optionally, `@Policy` method abilities) and emits a typed `can()`
7
+ helper into your generated `api.ts` — so checking a permission on the frontend is a compile-time
8
+ type, not a magic string.
9
+
10
+ The discovered abilities become a string-literal union (`AuthzAbility`). Calling `can()` with an
11
+ ability that doesn't exist on the server is a **type error**.
12
+
13
+ ```bash
14
+ pnpm add -D @dudousxd/nestjs-authz-codegen
15
+ ```
16
+
17
+ ```ts title="nestjs-codegen.config.ts"
18
+ import { defineConfig } from '@dudousxd/nestjs-codegen';
19
+ import { zodAdapter } from '@dudousxd/nestjs-codegen-zod';
20
+ import { nestjsAuthzCodegen } from '@dudousxd/nestjs-authz-codegen';
21
+
22
+ export default defineConfig({
23
+ validation: zodAdapter,
24
+ extensions: [
25
+ nestjsAuthzCodegen({ endpoint: '/authz/can' }),
26
+ // ...other extensions (tanstack, filter, notifications)
27
+ ],
28
+ });
29
+ ```
30
+
31
+ ## What it emits
32
+
33
+ Given controllers decorated with `@Can(...)`:
34
+
35
+ ```ts
36
+ @Controller('posts')
37
+ export class PostsController {
38
+ @Patch(':id')
39
+ @Can('update', Post)
40
+ update() {}
41
+
42
+ @Post(':id/publish')
43
+ @Can('access-admin')
44
+ publish() {}
45
+ }
46
+ ```
47
+
48
+ the generated `api.ts` gains:
49
+
50
+ ```ts
51
+ /** Every authorization ability discovered from `@Can`/`@Policy` in your NestJS app. */
52
+ export type AuthzAbility = 'update' | 'access-admin';
53
+
54
+ /** Map of resource class name → the abilities declared against it. */
55
+ export const authzAbilities = { Post: ['update'] } as const;
56
+
57
+ /** Ask the server whether the current user `can` perform `ability`. */
58
+ export async function can(
59
+ ability: AuthzAbility,
60
+ resource?: { type: string; id?: string | number } | null,
61
+ init?: RequestInit,
62
+ ): Promise<boolean> {
63
+ /* POSTs { ability, resource } to '/authz/can', returns the server's `allowed` boolean */
64
+ }
65
+ ```
66
+
67
+ ```ts
68
+ await can('update', { type: 'Post', id: 42 }); // ✅
69
+ await can('destroy'); // ✗ type error — 'destroy' is not an AuthzAbility
70
+ ```
71
+
72
+ Routes carrying a `@Can` also expose a route-pinned `can()` handle member when a client layer
73
+ (e.g. TanStack) is active: `api.posts.update.can({ type: 'Post', id: 42 })`.
74
+
75
+ ## Server side
76
+
77
+ > **Per-instance decisions must be hydrated, not fetched.** The fetch fallback (`POST /authz/can`)
78
+ > only resolves **class-level abilities and ad-hoc gates** — the `{ type, id }` resource shim it
79
+ > sends never matches a `@Policy` by constructor. A **resource-bound** ability
80
+ > (`can('update', { type: 'Post', id })`) that misses the hydrated cache and falls through to the
81
+ > endpoint will **deny** (and logs a one-time `console.warn`). Hydrate per-instance decisions via
82
+ > shared props / `authorizeResource` (tiers 1-2 of `@dudousxd/nestjs-authz-inertia`) instead.
83
+
84
+ The runtime `can()` POSTs `{ ability, resource? }` to the configured `endpoint` and expects
85
+ `{ allowed: boolean }` back. Expose a tiny controller in your NestJS app that delegates to the
86
+ `Gate`:
87
+
88
+ ```ts
89
+ @Post('authz/can')
90
+ async can(@Body() body: { ability: string; resource?: { type: string; id?: string } | null }) {
91
+ return { allowed: await this.gate.allows(body.ability, body.resource ?? undefined) };
92
+ }
93
+ ```
94
+
95
+ ## Options
96
+
97
+ | Option | Default | Description |
98
+ | --- | --- | --- |
99
+ | `endpoint` | `'/authz/can'` | Server endpoint the generated `can()` POSTs to (expects `{ allowed }`). |
100
+ | `discoverPolicies` | `true` | Also treat `@Policy(Resource)` method names as class-level abilities. |
101
+
102
+ ## Caveats
103
+
104
+ Decorators are discovered by their **canonical names** — import `@Can` / `@Policy` under their real
105
+ names. An aliased import (`import { Can as Authorize } from '@dudousxd/nestjs-authz'`) is NOT
106
+ discovered, because codegen matches the decorator identifier (`Can` / `Policy`) syntactically and
107
+ does not resolve aliases.
@@ -0,0 +1,49 @@
1
+ import type { CodegenExtension } from '@dudousxd/nestjs-codegen/extension';
2
+ /**
3
+ * The `@Can(ability, Resource?)` descriptor discovered on a controller route, plus the optional
4
+ * class-level abilities discovered on `@Policy(Resource)` classes. Mirrors the shapes stored by
5
+ * `@dudousxd/nestjs-authz`'s `CAN_METADATA` / `POLICY_RESOURCE_METADATA` — read statically from
6
+ * the AST rather than from reflect-metadata (which isn't available at codegen time).
7
+ */
8
+ export interface AuthzAbilityInfo {
9
+ /** The ability string, e.g. `'update'` or `'access-admin'`. */
10
+ ability: string;
11
+ /** The resource class name the ability targets, when `@Can(ability, Resource)` names one. */
12
+ resource?: string;
13
+ }
14
+ /** Options for {@link nestjsAuthzCodegen}. */
15
+ export interface AuthzCodegenOptions {
16
+ /**
17
+ * Server endpoint the generated `can()` helper falls back to when an ability/resource is not
18
+ * already hydrated in the shared store. Default `'/authz/can'`. Wired through to
19
+ * `@dudousxd/nestjs-authz-client`'s `createCan` as its `'fetch'` fallback endpoint; expose a tiny
20
+ * controller in your app that delegates to the `Gate` (`gate.allows(ability, resource)`).
21
+ */
22
+ endpoint?: string;
23
+ /**
24
+ * Also discover `@Policy(Resource)` classes and treat their public method names as class-level
25
+ * abilities (so e.g. `PostPolicy.publish` contributes `'publish'` to the union even when no
26
+ * route is decorated with it yet). Default `true`.
27
+ */
28
+ discoverPolicies?: boolean;
29
+ }
30
+ /**
31
+ * `@dudousxd/nestjs-authz` codegen extension. Discovers every `@Can(ability, Resource?)` decorator
32
+ * on your controllers (and, optionally, `@Policy` method abilities) and emits a typed `can()` helper
33
+ * into your generated `api.ts`: `ability` is a string-literal union of the discovered abilities, so a
34
+ * wrong ability is a compile error. The runtime `can()` delegates to `@dudousxd/nestjs-authz-client`
35
+ * (a shared `AbilityStore` + `createCan`) — so a hydrated decision answers with no request, and a
36
+ * cache miss falls back to the configured endpoint. Routes carrying a `@Can` also expose a `can()`
37
+ * handle member (when a client layer such as TanStack is active).
38
+ *
39
+ * Register it in your codegen config:
40
+ *
41
+ * ```ts
42
+ * defineConfig({
43
+ * extensions: [nestjsAuthzCodegen({ endpoint: '/authz/can' })],
44
+ * });
45
+ * ```
46
+ */
47
+ export declare function nestjsAuthzCodegen(options?: AuthzCodegenOptions): CodegenExtension;
48
+ export default nestjsAuthzCodegen;
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAGjB,MAAM,oCAAoC,CAAC;AAG5C;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD,8CAA8C;AAC9C,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAyKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,gBAAgB,CAkEtF;AAED,eAAe,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,245 @@
1
+ import { Node } from 'ts-morph';
2
+ const DEFAULT_ENDPOINT = '/authz/can';
3
+ /** Read the ability + resource from a single `@Can(...)` decorator's arguments. */
4
+ function readCanDecorator(args) {
5
+ const abilityArg = args[0];
6
+ if (!abilityArg || !Node.isStringLiteral(abilityArg))
7
+ return null;
8
+ const info = { ability: abilityArg.getLiteralValue() };
9
+ const resourceArg = args[1];
10
+ // `@Can('update', Post)` — second arg is the resource class identifier.
11
+ if (resourceArg && Node.isIdentifier(resourceArg)) {
12
+ info.resource = resourceArg.getText();
13
+ }
14
+ return info;
15
+ }
16
+ /**
17
+ * Discover the `@Can(...)` ability on the controller method backing a route. Opens the route's
18
+ * controller source via the shared ts-morph project, finds the method, and reads its (or its
19
+ * class's) `@Can` decorator. Class-level `@Can` applies when the method has none.
20
+ */
21
+ function discoverRouteAbility(route, project) {
22
+ const ref = route.controllerRef;
23
+ if (!ref)
24
+ return null;
25
+ let sourceFile;
26
+ try {
27
+ sourceFile = project.addSourceFileAtPathIfExists(ref.filePath) ?? undefined;
28
+ }
29
+ catch {
30
+ sourceFile = undefined;
31
+ }
32
+ if (!sourceFile)
33
+ sourceFile = project.getSourceFile(ref.filePath);
34
+ if (!sourceFile)
35
+ return null;
36
+ const classDecl = sourceFile.getClass(ref.className);
37
+ if (!classDecl)
38
+ return null;
39
+ const method = classDecl.getMethod(ref.methodName);
40
+ if (method) {
41
+ const dec = method.getDecorators().find((d) => d.getName() === 'Can');
42
+ if (dec) {
43
+ const info = readCanDecorator(dec.getArguments());
44
+ if (info)
45
+ return info;
46
+ }
47
+ }
48
+ // Fall back to a class-level `@Can(...)` guarding the whole controller.
49
+ const classDec = classDecl.getDecorators().find((d) => d.getName() === 'Can');
50
+ if (classDec)
51
+ return readCanDecorator(classDec.getArguments());
52
+ return null;
53
+ }
54
+ /**
55
+ * Discover class-level abilities from `@Policy(Resource)` classes: each public, non-lifecycle
56
+ * method name is an ability keyed to that resource. Mirrors how the authz `PolicyRegistry`
57
+ * dispatches `PostPolicy.update(user, post)` for `@Can('update', Post)`.
58
+ */
59
+ function discoverPolicyAbilities(project) {
60
+ const found = [];
61
+ for (const sourceFile of project.getSourceFiles()) {
62
+ for (const classDecl of sourceFile.getClasses()) {
63
+ const policyDec = classDecl.getDecorators().find((d) => d.getName() === 'Policy');
64
+ if (!policyDec)
65
+ continue;
66
+ const resource = resourceNameFromPolicy(policyDec.getArguments(), classDecl);
67
+ for (const method of classDecl.getMethods()) {
68
+ if (method.isStatic())
69
+ continue;
70
+ const name = method.getName();
71
+ // Skip the optional `before(user, ability)` hook — it isn't an ability itself.
72
+ if (name === 'before')
73
+ continue;
74
+ const ability = { ability: name };
75
+ if (resource)
76
+ ability.resource = resource;
77
+ found.push(ability);
78
+ }
79
+ }
80
+ }
81
+ return found;
82
+ }
83
+ /** `@Policy(Post)` → `'Post'`; derive from the class name (`PostPolicy` → `Post`) as a fallback. */
84
+ function resourceNameFromPolicy(args, classDecl) {
85
+ const arg = args[0];
86
+ if (arg && Node.isIdentifier(arg))
87
+ return arg.getText();
88
+ const className = classDecl.getName();
89
+ if (className?.endsWith('Policy'))
90
+ return className.slice(0, -'Policy'.length);
91
+ return undefined;
92
+ }
93
+ /** The string-literal union of all discovered abilities, e.g. `"update" | "create"` (or `never`). */
94
+ function abilityUnion(abilities) {
95
+ if (abilities.size === 0)
96
+ return 'never';
97
+ return [...abilities].map((a) => JSON.stringify(a)).join(' | ');
98
+ }
99
+ /** The `{ "Post": ["update", "create"] }` literal mapping each resource to its abilities. */
100
+ function resourceAbilityMapLiteral(byResource) {
101
+ if (byResource.size === 0)
102
+ return '{}';
103
+ const entries = [...byResource.entries()].map(([resource, abilities]) => `${JSON.stringify(resource)}: [${[...abilities].map((a) => JSON.stringify(a)).join(', ')}]`);
104
+ return `{ ${entries.join(', ')} }`;
105
+ }
106
+ /** The `import { ... } from '@dudousxd/nestjs-authz-client'` line the header contributes. */
107
+ function canHelperImports() {
108
+ return [
109
+ "import { AbilityStore, createCan } from '@dudousxd/nestjs-authz-client';",
110
+ "import type { ResourceRef } from '@dudousxd/nestjs-authz-client';",
111
+ ];
112
+ }
113
+ /**
114
+ * The top-level `can()` helper + `AuthzAbility` type contributed to `api.ts`. Rather than a
115
+ * hand-rolled POST, this DELEGATES to `@dudousxd/nestjs-authz-client`: it exports a shared
116
+ * `authzStore` ({@link AbilityStore}) you hydrate once (e.g. from Inertia props), and `can()` is a
117
+ * thin typed wrapper over the store's `createCan` resolver — so a hydrated decision is answered
118
+ * SYNCHRONOUSLY with NO request, and a cache miss uses the same configurable `'fetch'` fallback to
119
+ * {@link AuthzCodegenOptions.endpoint}. `ability` is a compile-time-checked union of discovered
120
+ * abilities, so a typo'd ability is a type error.
121
+ */
122
+ function canHelperStatements(union, mapLiteral, endpoint) {
123
+ return [
124
+ '/** Every authorization ability discovered from `@Can`/`@Policy` in your NestJS app. */',
125
+ `export type AuthzAbility = ${union};`,
126
+ '',
127
+ '/** Map of resource class name → the abilities declared against it. */',
128
+ `export const authzAbilities = ${mapLiteral} as const;`,
129
+ '',
130
+ '/**',
131
+ ' * The shared ability store backing `can()`. Hydrate it once from your server-shared',
132
+ " * decisions (e.g. `hydrateFromInertiaProps(authzStore, props)` from '@dudousxd/nestjs-authz-client')",
133
+ ' * so checks resolve with no network request.',
134
+ ' */',
135
+ 'export const authzStore = new AbilityStore();',
136
+ '',
137
+ '/**',
138
+ " * Resolver from '@dudousxd/nestjs-authz-client', bound to `authzStore`. Peek-first: a hydrated",
139
+ ` * decision returns synchronously; a cache miss POSTs to \`${endpoint}\` and reads \`{ allowed }\`.`,
140
+ ' */',
141
+ 'const authzCan = createCan(authzStore, {',
142
+ ` fallback: 'fetch',`,
143
+ ` endpoint: ${JSON.stringify(endpoint)},`,
144
+ '});',
145
+ '',
146
+ '/**',
147
+ ' * Whether the current user `can` perform `ability` (optionally on a resource identified by',
148
+ ' * `resource`). Typed against the abilities discovered at build time, so an unknown ability is a',
149
+ " * compile error. Delegates to `@dudousxd/nestjs-authz-client`'s store/`createCan`: a hydrated",
150
+ ' * decision is returned synchronously (no request); otherwise it falls back to the configured',
151
+ ' * endpoint. Returns a `boolean` on a cache hit or a `Promise<boolean>` on a fetch fallback.',
152
+ ' *',
153
+ ' * NOTE: per-instance decisions MUST be hydrated into `authzStore` (e.g. via shared props /',
154
+ ' * `authorizeResource`). The fetch fallback only resolves class-level abilities and ad-hoc',
155
+ ' * gates — a resource-bound ability that misses the cache will deny.',
156
+ ' */',
157
+ 'export function can(',
158
+ ' ability: AuthzAbility,',
159
+ ' resource?: ResourceRef | null,',
160
+ '): boolean | Promise<boolean> {',
161
+ ' return authzCan(ability, resource ?? undefined);',
162
+ '}',
163
+ ];
164
+ }
165
+ function markerOf(route) {
166
+ return route.contract?.contractSource?.authz;
167
+ }
168
+ /**
169
+ * `@dudousxd/nestjs-authz` codegen extension. Discovers every `@Can(ability, Resource?)` decorator
170
+ * on your controllers (and, optionally, `@Policy` method abilities) and emits a typed `can()` helper
171
+ * into your generated `api.ts`: `ability` is a string-literal union of the discovered abilities, so a
172
+ * wrong ability is a compile error. The runtime `can()` delegates to `@dudousxd/nestjs-authz-client`
173
+ * (a shared `AbilityStore` + `createCan`) — so a hydrated decision answers with no request, and a
174
+ * cache miss falls back to the configured endpoint. Routes carrying a `@Can` also expose a `can()`
175
+ * handle member (when a client layer such as TanStack is active).
176
+ *
177
+ * Register it in your codegen config:
178
+ *
179
+ * ```ts
180
+ * defineConfig({
181
+ * extensions: [nestjsAuthzCodegen({ endpoint: '/authz/can' })],
182
+ * });
183
+ * ```
184
+ */
185
+ export function nestjsAuthzCodegen(options = {}) {
186
+ const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;
187
+ const discoverPolicies = options.discoverPolicies ?? true;
188
+ // Discovered once during transformRoutes, then read by apiHeader/apiMembers.
189
+ const abilities = new Set();
190
+ const byResource = new Map();
191
+ function record(info) {
192
+ abilities.add(info.ability);
193
+ if (info.resource) {
194
+ const set = byResource.get(info.resource) ?? new Set();
195
+ set.add(info.ability);
196
+ byResource.set(info.resource, set);
197
+ }
198
+ }
199
+ const ext = {
200
+ name: 'nestjs-authz',
201
+ transformRoutes(routes, ctx) {
202
+ const project = ctx.project();
203
+ const out = routes.map((route) => {
204
+ const info = discoverRouteAbility(route, project);
205
+ if (!info)
206
+ return route;
207
+ record(info);
208
+ const marker = { ability: info.ability };
209
+ if (info.resource)
210
+ marker.resource = info.resource;
211
+ // Attach the marker to the route's contract so apiMembers can read it later.
212
+ const contractSource = { ...(route.contract?.contractSource ?? {}), authz: marker };
213
+ return { ...route, contract: { ...route.contract, contractSource } };
214
+ });
215
+ if (discoverPolicies) {
216
+ for (const info of discoverPolicyAbilities(project))
217
+ record(info);
218
+ }
219
+ return out;
220
+ },
221
+ apiHeader() {
222
+ if (abilities.size === 0)
223
+ return undefined;
224
+ return {
225
+ imports: canHelperImports(),
226
+ statements: canHelperStatements(abilityUnion(abilities), resourceAbilityMapLiteral(byResource), endpoint),
227
+ };
228
+ },
229
+ apiMembers(leaf) {
230
+ const marker = markerOf(leaf.route);
231
+ if (!marker)
232
+ return undefined;
233
+ const resourceArg = marker.resource ? 'resource: ResourceRef | null = null' : '';
234
+ const callResource = marker.resource ? ', resource' : '';
235
+ return {
236
+ // A typed `can()` pinned to THIS route's ability — no argument needed, can't be wrong.
237
+ can: `(${resourceArg}) => can(${JSON.stringify(marker.ability)}${callResource})`,
238
+ ability: JSON.stringify(marker.ability),
239
+ };
240
+ },
241
+ };
242
+ return ext;
243
+ }
244
+ export default nestjsAuthzCodegen;
245
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAyB,IAAI,EAAiC,MAAM,UAAU,CAAC;AAsCtF,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAEtC,mFAAmF;AACnF,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,MAAM,IAAI,GAAqB,EAAE,OAAO,EAAE,UAAU,CAAC,eAAe,EAAE,EAAE,CAAC;IACzE,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5B,wEAAwE;IACxE,IAAI,WAAW,IAAI,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,KAAsB,EAAE,OAAgB;IACpE,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,CAAC;IAChC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,UAAkC,CAAC;IACvC,IAAI,CAAC;QACH,UAAU,GAAG,OAAO,CAAC,2BAA2B,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,GAAG,SAAS,CAAC;IACzB,CAAC;IACD,IAAI,CAAC,UAAU;QAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClE,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAE7B,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACrD,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAE5B,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,KAAK,CAAC,CAAC;QACtE,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;YAClD,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,MAAM,QAAQ,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,KAAK,CAAC,CAAC;IAC9E,IAAI,QAAQ;QAAE,OAAO,gBAAgB,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;IAE/D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAS,uBAAuB,CAAC,OAAgB;IAC/C,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,MAAM,UAAU,IAAI,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;QAClD,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,UAAU,EAAE,EAAE,CAAC;YAChD,MAAM,SAAS,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC;YAClF,IAAI,CAAC,SAAS;gBAAE,SAAS;YACzB,MAAM,QAAQ,GAAG,sBAAsB,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,CAAC,CAAC;YAC7E,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;gBAC5C,IAAI,MAAM,CAAC,QAAQ,EAAE;oBAAE,SAAS;gBAChC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC9B,+EAA+E;gBAC/E,IAAI,IAAI,KAAK,QAAQ;oBAAE,SAAS;gBAChC,MAAM,OAAO,GAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBACpD,IAAI,QAAQ;oBAAE,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBAC1C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,oGAAoG;AACpG,SAAS,sBAAsB,CAAC,IAAY,EAAE,SAA2B;IACvE,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,OAAO,EAAE,CAAC;IACxD,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;IACtC,IAAI,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,qGAAqG;AACrG,SAAS,YAAY,CAAC,SAAsB;IAC1C,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACzC,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAED,6FAA6F;AAC7F,SAAS,yBAAyB,CAAC,UAAoC;IACrE,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,OAAO,GAAG,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAC3C,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,CACxB,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC9F,CAAC;IACF,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACrC,CAAC;AAED,6FAA6F;AAC7F,SAAS,gBAAgB;IACvB,OAAO;QACL,0EAA0E;QAC1E,mEAAmE;KACpE,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,mBAAmB,CAAC,KAAa,EAAE,UAAkB,EAAE,QAAgB;IAC9E,OAAO;QACL,yFAAyF;QACzF,8BAA8B,KAAK,GAAG;QACtC,EAAE;QACF,wEAAwE;QACxE,iCAAiC,UAAU,YAAY;QACvD,EAAE;QACF,KAAK;QACL,sFAAsF;QACtF,uGAAuG;QACvG,+CAA+C;QAC/C,KAAK;QACL,+CAA+C;QAC/C,EAAE;QACF,KAAK;QACL,iGAAiG;QACjG,8DAA8D,QAAQ,+BAA+B;QACrG,KAAK;QACL,0CAA0C;QAC1C,sBAAsB;QACtB,eAAe,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG;QAC1C,KAAK;QACL,EAAE;QACF,KAAK;QACL,6FAA6F;QAC7F,kGAAkG;QAClG,gGAAgG;QAChG,+FAA+F;QAC/F,8FAA8F;QAC9F,IAAI;QACJ,6FAA6F;QAC7F,4FAA4F;QAC5F,sEAAsE;QACtE,KAAK;QACL,sBAAsB;QACtB,0BAA0B;QAC1B,kCAAkC;QAClC,iCAAiC;QACjC,oDAAoD;QACpD,GAAG;KACJ,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAsB;IACtC,OAAQ,KAAK,CAAC,QAAQ,EAAE,cAA2D,EAAE,KAAK,CAAC;AAC7F,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAA+B,EAAE;IAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,gBAAgB,CAAC;IACtD,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAE1D,6EAA6E;IAC7E,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;IAElD,SAAS,MAAM,CAAC,IAAsB;QACpC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;YAC/D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAqB;QAC5B,IAAI,EAAE,cAAc;QAEpB,eAAe,CAAC,MAAM,EAAE,GAAG;YACzB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC/B,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAClD,IAAI,CAAC,IAAI;oBAAE,OAAO,KAAK,CAAC;gBACxB,MAAM,CAAC,IAAI,CAAC,CAAC;gBACb,MAAM,MAAM,GAAqB,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC3D,IAAI,IAAI,CAAC,QAAQ;oBAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;gBACnD,6EAA6E;gBAC7E,MAAM,cAAc,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,cAAc,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;gBACpF,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAqB,CAAC;YAC1F,CAAC,CAAC,CAAC;YAEH,IAAI,gBAAgB,EAAE,CAAC;gBACrB,KAAK,MAAM,IAAI,IAAI,uBAAuB,CAAC,OAAO,CAAC;oBAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YACpE,CAAC;YAED,OAAO,GAAG,CAAC;QACb,CAAC;QAED,SAAS;YACP,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC3C,OAAO;gBACL,OAAO,EAAE,gBAAgB,EAAE;gBAC3B,UAAU,EAAE,mBAAmB,CAC7B,YAAY,CAAC,SAAS,CAAC,EACvB,yBAAyB,CAAC,UAAU,CAAC,EACrC,QAAQ,CACT;aACF,CAAC;QACJ,CAAC;QAED,UAAU,CAAC,IAAe;YACxB,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,CAAC,MAAM;gBAAE,OAAO,SAAS,CAAC;YAC9B,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,EAAE,CAAC;YACjF,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO;gBACL,uFAAuF;gBACvF,GAAG,EAAE,IAAI,WAAW,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,YAAY,GAAG;gBAChF,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC;aACxC,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,eAAe,kBAAkB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@dudousxd/nestjs-authz-codegen",
3
+ "version": "0.1.0",
4
+ "description": "nestjs-codegen extension for @dudousxd/nestjs-authz — discovers @Can abilities and emits a typed can() into your generated client.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/DavideCarvalho/nestjs-authz.git",
9
+ "directory": "packages/codegen"
10
+ },
11
+ "author": "Davi Carvalho <davi@goflip.ai>",
12
+ "type": "module",
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js",
19
+ "default": "./dist/index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist/",
24
+ "README.md",
25
+ "CHANGELOG.md"
26
+ ],
27
+ "peerDependencies": {
28
+ "@dudousxd/nestjs-authz": ">=0.2.0",
29
+ "@dudousxd/nestjs-authz-client": ">=0.0.0",
30
+ "@dudousxd/nestjs-codegen": ">=0.4.0"
31
+ },
32
+ "peerDependenciesMeta": {
33
+ "@dudousxd/nestjs-authz-client": {
34
+ "optional": true
35
+ }
36
+ },
37
+ "devDependencies": {
38
+ "@dudousxd/nestjs-codegen": "0.4.0",
39
+ "ts-morph": "^28.0.0",
40
+ "typescript": "^5.4.0",
41
+ "vitest": "^3.0.0",
42
+ "@dudousxd/nestjs-authz": "^0.3.0",
43
+ "@dudousxd/nestjs-authz-client": "^0.1.0"
44
+ },
45
+ "engines": {
46
+ "node": ">=20"
47
+ },
48
+ "keywords": [
49
+ "nestjs",
50
+ "authorization",
51
+ "authz",
52
+ "codegen",
53
+ "extension",
54
+ "can",
55
+ "policy"
56
+ ],
57
+ "scripts": {
58
+ "build": "tsc -p tsconfig.json",
59
+ "test": "vitest run --passWithNoTests",
60
+ "test:watch": "vitest",
61
+ "typecheck": "tsc -p tsconfig.json --noEmit"
62
+ }
63
+ }