@veloxts/auth 0.6.92 → 0.6.93

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # @veloxts/auth
2
2
 
3
+ ## 0.6.93
4
+
5
+ ### Patch Changes
6
+
7
+ - feat(router): add Resource API with phantom types for context-dependent outputs
8
+ - Updated dependencies
9
+ - @veloxts/core@0.6.93
10
+ - @veloxts/router@0.6.93
11
+
3
12
  ## 0.6.92
4
13
 
5
14
  ### Patch Changes
package/GUIDE.md CHANGED
@@ -86,6 +86,45 @@ const adminWithPermission = procedure()
86
86
  .mutation(handler);
87
87
  ```
88
88
 
89
+ ## Resource API Integration
90
+
91
+ Guards work seamlessly with the Resource API for context-dependent outputs:
92
+
93
+ ```typescript
94
+ import { resource, resourceSchema } from '@veloxts/router';
95
+ import { authenticatedNarrow, adminNarrow } from '@veloxts/auth';
96
+
97
+ const UserSchema = resourceSchema()
98
+ .public('id', z.string())
99
+ .public('name', z.string())
100
+ .authenticated('email', z.string())
101
+ .admin('internalNotes', z.string().nullable())
102
+ .build();
103
+
104
+ // Anonymous - returns { id, name }
105
+ const getPublicUser = procedure()
106
+ .query(async ({ input, ctx }) => {
107
+ const user = await ctx.db.user.findUnique({ where: { id: input.id } });
108
+ return resource(user, UserSchema).forAnonymous();
109
+ });
110
+
111
+ // Authenticated - returns { id, name, email }
112
+ const getUser = procedure()
113
+ .guardNarrow(authenticatedNarrow)
114
+ .query(async ({ input, ctx }) => {
115
+ const user = await ctx.db.user.findUnique({ where: { id: input.id } });
116
+ return resource(user, UserSchema).for(ctx); // Auto-detects level
117
+ });
118
+
119
+ // Admin - returns all fields
120
+ const getFullUser = procedure()
121
+ .guardNarrow(adminNarrow)
122
+ .query(async ({ input, ctx }) => {
123
+ const user = await ctx.db.user.findUnique({ where: { id: input.id } });
124
+ return resource(user, UserSchema).forAdmin();
125
+ });
126
+ ```
127
+
89
128
  ## Password Hashing
90
129
 
91
130
  ```typescript
@@ -5,18 +5,26 @@
5
5
  * When using `guardNarrow(authenticatedNarrow)`, the context type
6
6
  * is narrowed to guarantee `ctx.user` is non-null.
7
7
  *
8
+ * Additionally, these guards add phantom type tags for use with the
9
+ * Resource API, enabling context-dependent output types.
10
+ *
8
11
  * EXPERIMENTAL: This API may change. The current recommended approach
9
12
  * is to use middleware for context type extension.
10
13
  *
11
14
  * @module auth/guards-narrowing
12
15
  */
16
+ import type { AccessLevel, ADMIN, AUTHENTICATED, TaggedContext } from '@veloxts/router';
13
17
  import type { AuthContext, GuardFunction, User } from './types.js';
18
+ export type { AccessLevel, ADMIN, AUTHENTICATED, TaggedContext };
14
19
  /**
15
20
  * A guard that narrows the context type after passing.
16
21
  *
17
22
  * The `_narrows` phantom type indicates what the guard guarantees
18
23
  * about the context after it passes.
19
24
  *
25
+ * The `accessLevel` property is used by the procedure builder to
26
+ * automatically set `ctx.__accessLevel` for resource auto-projection.
27
+ *
20
28
  * @template TRequired - Context properties required to run the guard
21
29
  * @template TGuaranteed - Context properties guaranteed after guard passes
22
30
  */
@@ -35,18 +43,41 @@ export interface NarrowingGuard<TRequired, TGuaranteed> {
35
43
  * @internal
36
44
  */
37
45
  readonly _narrows: TGuaranteed;
46
+ /**
47
+ * Runtime access level for automatic resource projection.
48
+ *
49
+ * When set, the procedure builder will automatically assign this
50
+ * value to `ctx.__accessLevel` after the guard passes, enabling
51
+ * auto-projection with `.resource()`.
52
+ */
53
+ accessLevel?: AccessLevel;
38
54
  }
39
55
  /**
40
56
  * Context type with a guaranteed authenticated user.
41
57
  *
42
58
  * After `authenticatedNarrow` passes, the context is narrowed to this type.
59
+ * Includes a phantom tag for the Resource API.
43
60
  */
44
- export interface AuthenticatedContext {
61
+ export interface AuthenticatedContext extends TaggedContext<typeof AUTHENTICATED> {
45
62
  auth: AuthContext & {
46
63
  isAuthenticated: true;
47
64
  };
48
65
  user: User;
49
66
  }
67
+ /**
68
+ * Context type with a guaranteed user having admin role.
69
+ *
70
+ * After `adminNarrow` passes, the context is narrowed to this type.
71
+ * Includes a phantom tag for the Resource API.
72
+ */
73
+ export interface AdminContext extends TaggedContext<typeof ADMIN> {
74
+ auth: AuthContext & {
75
+ isAuthenticated: true;
76
+ };
77
+ user: User & {
78
+ roles: string[];
79
+ };
80
+ }
50
81
  /**
51
82
  * Context type with a guaranteed user having specific roles.
52
83
  */
@@ -88,6 +119,30 @@ export interface RoleNarrowedContext {
88
119
  export declare const authenticatedNarrow: NarrowingGuard<{
89
120
  auth?: AuthContext;
90
121
  }, AuthenticatedContext>;
122
+ /**
123
+ * Admin guard with type narrowing and phantom tag.
124
+ *
125
+ * When used with `guardNarrow()`, narrows `ctx.user` to a User with admin role
126
+ * and tags the context with ADMIN for use with the Resource API.
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * import { adminNarrow } from '@veloxts/auth';
131
+ * import { resource, UserSchema } from '@veloxts/router';
132
+ *
133
+ * procedure()
134
+ * .guardNarrow(adminNarrow)
135
+ * .query(({ ctx }) => {
136
+ * // ctx.user is typed as User with roles: string[]
137
+ * // When used with resource(), returns all fields including admin-only
138
+ * const user = await ctx.db.user.findUnique({ where: { id } });
139
+ * return resource(user, UserSchema).forAdmin();
140
+ * });
141
+ * ```
142
+ */
143
+ export declare const adminNarrow: NarrowingGuard<{
144
+ user?: User;
145
+ }, AdminContext>;
91
146
  /**
92
147
  * Creates a role-checking guard with type narrowing.
93
148
  *
@@ -5,6 +5,9 @@
5
5
  * When using `guardNarrow(authenticatedNarrow)`, the context type
6
6
  * is narrowed to guarantee `ctx.user` is non-null.
7
7
  *
8
+ * Additionally, these guards add phantom type tags for use with the
9
+ * Resource API, enabling context-dependent output types.
10
+ *
8
11
  * EXPERIMENTAL: This API may change. The current recommended approach
9
12
  * is to use middleware for context type extension.
10
13
  *
@@ -49,6 +52,36 @@ export const authenticatedNarrow = {
49
52
  // Phantom type: value is never used at runtime, only carries type info.
50
53
  // The `undefined as unknown as T` pattern is standard for phantom types.
51
54
  _narrows: undefined,
55
+ // Runtime access level for auto-projection with .resource()
56
+ accessLevel: 'authenticated',
57
+ };
58
+ /**
59
+ * Admin guard with type narrowing and phantom tag.
60
+ *
61
+ * When used with `guardNarrow()`, narrows `ctx.user` to a User with admin role
62
+ * and tags the context with ADMIN for use with the Resource API.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * import { adminNarrow } from '@veloxts/auth';
67
+ * import { resource, UserSchema } from '@veloxts/router';
68
+ *
69
+ * procedure()
70
+ * .guardNarrow(adminNarrow)
71
+ * .query(({ ctx }) => {
72
+ * // ctx.user is typed as User with roles: string[]
73
+ * // When used with resource(), returns all fields including admin-only
74
+ * const user = await ctx.db.user.findUnique({ where: { id } });
75
+ * return resource(user, UserSchema).forAdmin();
76
+ * });
77
+ * ```
78
+ */
79
+ export const adminNarrow = {
80
+ ...hasRoleBase('admin'),
81
+ // Phantom type: carries type info for guardNarrow() and Resource API
82
+ _narrows: undefined,
83
+ // Runtime access level for auto-projection with .resource()
84
+ accessLevel: 'admin',
52
85
  };
53
86
  /**
54
87
  * Creates a role-checking guard with type narrowing.
package/dist/index.d.ts CHANGED
@@ -15,8 +15,8 @@ export type { TokenStore } from './jwt.js';
15
15
  export { createInMemoryTokenStore, generateTokenId, isValidTimespan, JwtManager, jwtManager, parseTimeToSeconds, validateTokenExpiration, } from './jwt.js';
16
16
  export type { EnhancedTokenStore, EnhancedTokenStoreOptions } from './token-store.js';
17
17
  export { createEnhancedTokenStore, DEFAULT_ALLOWED_ROLES, parseUserRoles, } from './token-store.js';
18
- export type { AuthenticatedContext, InferNarrowedContext, NarrowingGuard, RoleNarrowedContext, } from './guards-narrowing.js';
19
- export { authenticatedNarrow, hasRoleNarrow } from './guards-narrowing.js';
18
+ export type { ADMIN, AdminContext, AUTHENTICATED, AuthenticatedContext, InferNarrowedContext, NarrowingGuard, RoleNarrowedContext, TaggedContext, } from './guards-narrowing.js';
19
+ export { adminNarrow, authenticatedNarrow, hasRoleNarrow, } from './guards-narrowing.js';
20
20
  export { DEFAULT_HASH_CONFIG, hashPassword, PasswordHasher, passwordHasher, verifyPassword, } from './hash.js';
21
21
  export type { GuardBuilder } from './guards.js';
22
22
  export { allOf, anyOf, authenticated, defineGuard, emailVerified, executeGuard, executeGuards, guard, hasAnyPermission, hasPermission, hasRole, not, userCan, } from './guards.js';
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ export { AuthError } from './types.js';
18
18
  export { AUTH_REGISTERED, checkDoubleRegistration, decorateAuth, getRequestAuth, getRequestUser, setRequestAuth, } from './decoration.js';
19
19
  export { createInMemoryTokenStore, generateTokenId, isValidTimespan, JwtManager, jwtManager, parseTimeToSeconds, validateTokenExpiration, } from './jwt.js';
20
20
  export { createEnhancedTokenStore, DEFAULT_ALLOWED_ROLES, parseUserRoles, } from './token-store.js';
21
- export { authenticatedNarrow, hasRoleNarrow } from './guards-narrowing.js';
21
+ export { adminNarrow, authenticatedNarrow, hasRoleNarrow, } from './guards-narrowing.js';
22
22
  // ============================================================================
23
23
  // Password Hashing
24
24
  // ============================================================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veloxts/auth",
3
- "version": "0.6.92",
3
+ "version": "0.6.93",
4
4
  "description": "Authentication and authorization system for VeloxTS framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -61,8 +61,8 @@
61
61
  "dependencies": {
62
62
  "@fastify/cookie": "11.0.2",
63
63
  "fastify": "5.7.2",
64
- "@veloxts/core": "0.6.92",
65
- "@veloxts/router": "0.6.92"
64
+ "@veloxts/core": "0.6.93",
65
+ "@veloxts/router": "0.6.93"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "argon2": ">=0.30.0",
@@ -86,8 +86,8 @@
86
86
  "fastify-plugin": "5.1.0",
87
87
  "typescript": "5.9.3",
88
88
  "vitest": "4.0.18",
89
- "@veloxts/testing": "0.6.92",
90
- "@veloxts/validation": "0.6.92"
89
+ "@veloxts/testing": "0.6.93",
90
+ "@veloxts/validation": "0.6.93"
91
91
  },
92
92
  "keywords": [
93
93
  "velox",