ideal-auth 0.6.0 → 0.7.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/README.md +0 -12
- package/dist/auth.d.ts +12 -5
- package/dist/auth.js +10 -0
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
- package/skills/ideal-auth/SKILL.md +27 -33
package/README.md
CHANGED
|
@@ -552,18 +552,6 @@ cookie: {
|
|
|
552
552
|
|
|
553
553
|
Zero framework imports. Works in Node, Bun, Deno, and edge runtimes.
|
|
554
554
|
|
|
555
|
-
## Claude Code
|
|
556
|
-
|
|
557
|
-
If you use [Claude Code](https://claude.com/claude-code), install the ideal-auth plugin so your AI assistant knows the full API, cookie bridge patterns, security best practices, and implementation guides:
|
|
558
|
-
|
|
559
|
-
```bash
|
|
560
|
-
claude plugin install github:ramonmalcolm10/ideal-auth
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
After installing, Claude Code will automatically help with auth setup, login/registration flows, middleware, 2FA, password reset, rate limiting, and more — using the correct patterns for your framework.
|
|
564
|
-
|
|
565
|
-
---
|
|
566
|
-
|
|
567
555
|
## Support
|
|
568
556
|
|
|
569
557
|
If this saved you time, consider supporting the project:
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import type { AnyUser, AuthInstance,
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { AnyUser, AuthInstance, AuthConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Create an auth factory.
|
|
4
|
+
*
|
|
5
|
+
* `TUser` is the session user type — what `user()` returns.
|
|
6
|
+
* Do not include sensitive fields like password in this type.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* type SessionUser = { id: string; email: string; name: string };
|
|
10
|
+
* createAuth<SessionUser>({ ... })
|
|
11
|
+
*/
|
|
12
|
+
export declare function createAuth<TUser extends AnyUser>(config: AuthConfig<TUser>): () => AuthInstance<TUser>;
|
package/dist/auth.js
CHANGED
|
@@ -4,6 +4,16 @@ const SESSION_DEFAULTS = {
|
|
|
4
4
|
maxAge: 60 * 60 * 24 * 7, // 7 days
|
|
5
5
|
rememberMaxAge: 60 * 60 * 24 * 30, // 30 days
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Create an auth factory.
|
|
9
|
+
*
|
|
10
|
+
* `TUser` is the session user type — what `user()` returns.
|
|
11
|
+
* Do not include sensitive fields like password in this type.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* type SessionUser = { id: string; email: string; name: string };
|
|
15
|
+
* createAuth<SessionUser>({ ... })
|
|
16
|
+
*/
|
|
7
17
|
export function createAuth(config) {
|
|
8
18
|
if (!config.secret || config.secret.length < 32) {
|
|
9
19
|
throw new Error('secret must be at least 32 characters');
|
package/dist/types.d.ts
CHANGED
|
@@ -78,13 +78,13 @@ export type AuthConfig<TUser extends AnyUser = AnyUser> = AuthConfigWithResolveU
|
|
|
78
78
|
export interface HashConfig {
|
|
79
79
|
rounds?: number;
|
|
80
80
|
}
|
|
81
|
-
export interface AuthInstance<TUser extends AnyUser = AnyUser
|
|
81
|
+
export interface AuthInstance<TUser extends AnyUser = AnyUser> {
|
|
82
82
|
login(user: TUser, options?: LoginOptions): Promise<void>;
|
|
83
83
|
loginById(id: string, options?: LoginOptions): Promise<void>;
|
|
84
84
|
attempt(credentials: Record<string, any>, options?: LoginOptions): Promise<boolean>;
|
|
85
85
|
logout(): Promise<void>;
|
|
86
86
|
check(): Promise<boolean>;
|
|
87
|
-
user(): Promise<
|
|
87
|
+
user(): Promise<TUser | null>;
|
|
88
88
|
id(): Promise<string | null>;
|
|
89
89
|
}
|
|
90
90
|
export interface HashInstance {
|
package/package.json
CHANGED
|
@@ -71,33 +71,28 @@ Returns a factory function. Call `auth()` per request to get an `AuthInstance` s
|
|
|
71
71
|
#### AuthConfig
|
|
72
72
|
|
|
73
73
|
```typescript
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
type
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
resolveUserByCredentials?: (credentials: Record<string, any>) => Promise<AnyUser | null | undefined>;
|
|
97
|
-
hash?: HashInstance;
|
|
98
|
-
attemptUser?: (credentials: Record<string, any>) => Promise<TUser | null | undefined>;
|
|
99
|
-
// ...session options
|
|
100
|
-
};
|
|
74
|
+
// TUser = session user type — what user() returns. Do not include password.
|
|
75
|
+
// Provide exactly ONE of resolveUser or sessionFields.
|
|
76
|
+
// TypeScript will error if you provide both or neither.
|
|
77
|
+
|
|
78
|
+
type AuthConfig<TUser> =
|
|
79
|
+
| {
|
|
80
|
+
resolveUser: (id: string) => Promise<TUser | null | undefined>;
|
|
81
|
+
sessionFields?: never;
|
|
82
|
+
// resolveUserByCredentials can return any shape — only needs id + passwordField
|
|
83
|
+
resolveUserByCredentials?: (credentials: Record<string, any>) => Promise<AnyUser | null | undefined>;
|
|
84
|
+
hash?: HashInstance;
|
|
85
|
+
attemptUser?: (credentials: Record<string, any>) => Promise<TUser | null | undefined>;
|
|
86
|
+
// ...session, secret, cookie
|
|
87
|
+
}
|
|
88
|
+
| {
|
|
89
|
+
resolveUser?: never;
|
|
90
|
+
sessionFields: (keyof TUser & string)[];
|
|
91
|
+
resolveUserByCredentials?: (credentials: Record<string, any>) => Promise<AnyUser | null | undefined>;
|
|
92
|
+
hash?: HashInstance;
|
|
93
|
+
attemptUser?: (credentials: Record<string, any>) => Promise<TUser | null | undefined>;
|
|
94
|
+
// ...session, secret, cookie
|
|
95
|
+
};
|
|
101
96
|
```
|
|
102
97
|
|
|
103
98
|
#### Session Modes
|
|
@@ -124,25 +119,24 @@ const auth = createAuth<SafeUser>({
|
|
|
124
119
|
const user = await auth().user(); // Type: SafeUser | null
|
|
125
120
|
```
|
|
126
121
|
|
|
127
|
-
**Cookie-backed (`sessionFields`):** Cookie stores user ID + declared fields. `user()` returns `
|
|
122
|
+
**Cookie-backed (`sessionFields`):** Cookie stores user ID + declared fields. `user()` returns `TUser | null`. Since `TUser` should not include password, the type is already safe.
|
|
128
123
|
|
|
129
124
|
```typescript
|
|
130
|
-
type
|
|
125
|
+
type SessionUser = { id: string; email: string; name: string; role: string }; // no password
|
|
131
126
|
|
|
132
|
-
const auth = createAuth<
|
|
127
|
+
const auth = createAuth<SessionUser>({
|
|
133
128
|
secret: process.env.IDEAL_AUTH_SECRET!,
|
|
134
129
|
cookie: createCookieBridge(),
|
|
135
130
|
sessionFields: ['email', 'name', 'role'],
|
|
136
131
|
resolveUserByCredentials: async (creds) => db.user.findFirst({ where: { email: creds.email } }),
|
|
137
132
|
hash,
|
|
138
133
|
});
|
|
139
|
-
const user = await auth().user(); // Type:
|
|
134
|
+
const user = await auth().user(); // Type: SessionUser | null
|
|
140
135
|
```
|
|
141
136
|
|
|
142
137
|
Key rules:
|
|
138
|
+
- `TUser` is the session user type — what `user()` returns. Do not include password.
|
|
143
139
|
- Provide exactly one of `resolveUser` or `sessionFields` — TypeScript errors if both or neither
|
|
144
|
-
- `resolveUser` mode: `TUser` is the safe type. Only select non-sensitive fields in your query
|
|
145
|
-
- `sessionFields` mode: `user()` type is `Pick<TUser, 'id' | ...fields>` — password excluded automatically
|
|
146
140
|
- `resolveUserByCredentials` returns `AnyUser` — doesn't need to match `TUser`, only needs `id` + password field
|
|
147
141
|
- Password is stripped from the cached user after `attempt()` — even same-request `user()` won't expose it
|
|
148
142
|
- Cookie limit is ~4KB — store basic fields only
|