ideal-auth 0.6.1 → 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-instance.d.ts +1 -1
- package/dist/auth.d.ts +6 -7
- package/dist/auth.js +5 -6
- package/dist/types.d.ts +3 -3
- package/package.json +1 -1
- package/skills/ideal-auth/SKILL.md +28 -38
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-instance.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ interface AuthInstanceDeps<TUser extends AnyUser> {
|
|
|
7
7
|
rememberMaxAge: number;
|
|
8
8
|
cookieOptions: ConfigurableCookieOptions;
|
|
9
9
|
resolveUser?: (id: string) => Promise<TUser | null | undefined>;
|
|
10
|
-
sessionFields?:
|
|
10
|
+
sessionFields?: (keyof TUser & string)[];
|
|
11
11
|
hash?: HashInstance;
|
|
12
12
|
resolveUserByCredentials?: (credentials: Record<string, any>) => Promise<AnyUser | null | undefined>;
|
|
13
13
|
credentialKey: string;
|
package/dist/auth.d.ts
CHANGED
|
@@ -2,12 +2,11 @@ import type { AnyUser, AuthInstance, AuthConfig } from './types';
|
|
|
2
2
|
/**
|
|
3
3
|
* Create an auth factory.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* createAuth<SafeUser>({ resolveUser: ... })
|
|
5
|
+
* `TUser` is the session user type — what `user()` returns.
|
|
6
|
+
* Do not include sensitive fields like password in this type.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* createAuth<
|
|
8
|
+
* @example
|
|
9
|
+
* type SessionUser = { id: string; email: string; name: string };
|
|
10
|
+
* createAuth<SessionUser>({ ... })
|
|
12
11
|
*/
|
|
13
|
-
export declare function createAuth<TUser extends AnyUser
|
|
12
|
+
export declare function createAuth<TUser extends AnyUser>(config: AuthConfig<TUser>): () => AuthInstance<TUser>;
|
package/dist/auth.js
CHANGED
|
@@ -7,13 +7,12 @@ const SESSION_DEFAULTS = {
|
|
|
7
7
|
/**
|
|
8
8
|
* Create an auth factory.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* createAuth<SafeUser>({ resolveUser: ... })
|
|
10
|
+
* `TUser` is the session user type — what `user()` returns.
|
|
11
|
+
* Do not include sensitive fields like password in this type.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* createAuth<
|
|
13
|
+
* @example
|
|
14
|
+
* type SessionUser = { id: string; email: string; name: string };
|
|
15
|
+
* createAuth<SessionUser>({ ... })
|
|
17
16
|
*/
|
|
18
17
|
export function createAuth(config) {
|
|
19
18
|
if (!config.secret || config.secret.length < 32) {
|
package/dist/types.d.ts
CHANGED
|
@@ -72,19 +72,19 @@ export interface AuthConfigWithResolveUser<TUser extends AnyUser> extends AuthCo
|
|
|
72
72
|
export interface AuthConfigWithSessionFields<TUser extends AnyUser, K extends keyof TUser & string = keyof TUser & string> extends AuthConfigBase<TUser> {
|
|
73
73
|
/** Cannot use `resolveUser` together with `sessionFields`. */
|
|
74
74
|
resolveUser?: never;
|
|
75
|
-
sessionFields:
|
|
75
|
+
sessionFields: K[];
|
|
76
76
|
}
|
|
77
77
|
export type AuthConfig<TUser extends AnyUser = AnyUser> = AuthConfigWithResolveUser<TUser> | AuthConfigWithSessionFields<TUser>;
|
|
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,29 +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 `
|
|
128
|
-
|
|
129
|
-
Define fields once as `const` and derive the type with `(typeof sessionFields)[number]`:
|
|
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.
|
|
130
123
|
|
|
131
124
|
```typescript
|
|
132
|
-
type
|
|
133
|
-
|
|
134
|
-
const sessionFields = ['email', 'name', 'role'] as const;
|
|
125
|
+
type SessionUser = { id: string; email: string; name: string; role: string }; // no password
|
|
135
126
|
|
|
136
|
-
const auth = createAuth<
|
|
127
|
+
const auth = createAuth<SessionUser>({
|
|
137
128
|
secret: process.env.IDEAL_AUTH_SECRET!,
|
|
138
129
|
cookie: createCookieBridge(),
|
|
139
|
-
sessionFields,
|
|
130
|
+
sessionFields: ['email', 'name', 'role'],
|
|
140
131
|
resolveUserByCredentials: async (creds) => db.user.findFirst({ where: { email: creds.email } }),
|
|
141
132
|
hash,
|
|
142
133
|
});
|
|
143
|
-
const user = await auth().user(); // Type:
|
|
134
|
+
const user = await auth().user(); // Type: SessionUser | null
|
|
144
135
|
```
|
|
145
136
|
|
|
146
137
|
Key rules:
|
|
138
|
+
- `TUser` is the session user type — what `user()` returns. Do not include password.
|
|
147
139
|
- Provide exactly one of `resolveUser` or `sessionFields` — TypeScript errors if both or neither
|
|
148
|
-
- `resolveUser` mode: `TUser` is the safe type. Only select non-sensitive fields in your query
|
|
149
|
-
- `sessionFields` mode: `user()` type is `Pick<TUser, 'id' | ...fields>` — password excluded automatically
|
|
150
140
|
- `resolveUserByCredentials` returns `AnyUser` — doesn't need to match `TUser`, only needs `id` + password field
|
|
151
141
|
- Password is stripped from the cached user after `attempt()` — even same-request `user()` won't expose it
|
|
152
142
|
- Cookie limit is ~4KB — store basic fields only
|