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 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, AuthConfigWithResolveUser, AuthConfigWithSessionFields } from './types';
2
- /** Database-backed: `user()` returns `TUser` (the safe type from `resolveUser`). */
3
- export declare function createAuth<TUser extends AnyUser>(config: AuthConfigWithResolveUser<TUser>): () => AuthInstance<TUser>;
4
- /** Cookie-backed: `user()` returns only `id` + the declared `sessionFields`. */
5
- export declare function createAuth<TUser extends AnyUser, K extends keyof TUser & string>(config: AuthConfigWithSessionFields<TUser, K>): () => AuthInstance<TUser, Pick<TUser, 'id' | K>>;
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, TSessionUser = TUser> {
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<TSessionUser | null>;
87
+ user(): Promise<TUser | null>;
88
88
  id(): Promise<string | null>;
89
89
  }
90
90
  export interface HashInstance {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideal-auth",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Auth primitives for the JS ecosystem. Zero framework dependencies.",
5
5
  "scripts": {
6
6
  "build": "tsc",
@@ -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
- // Session modeprovide exactly ONE of resolveUser or sessionFields
75
- // TypeScript will error if you provide both or neither
76
-
77
- // resolveUser mode: TUser is the safe type returned by resolveUser and user()
78
- type AuthConfigWithResolveUser<TUser> = {
79
- secret: string;
80
- cookie: CookieBridge;
81
- resolveUser: (id: string) => Promise<TUser | null | undefined>;
82
- sessionFields?: never;
83
- // resolveUserByCredentials can return any shape only needs id + passwordField
84
- resolveUserByCredentials?: (credentials: Record<string, any>) => Promise<AnyUser | null | undefined>;
85
- hash?: HashInstance;
86
- attemptUser?: (credentials: Record<string, any>) => Promise<TUser | null | undefined>;
87
- // ...session options
88
- };
89
-
90
- // sessionFields mode: user() returns Pick<TUser, 'id' | K>
91
- type AuthConfigWithSessionFields<TUser, K extends keyof TUser> = {
92
- secret: string;
93
- cookie: CookieBridge;
94
- resolveUser?: never;
95
- sessionFields: K[];
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 `Pick<TUser, 'id' | K>` password excluded from the type.
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 DbUser = { id: string; email: string; name: string; role: string; password: string };
125
+ type SessionUser = { id: string; email: string; name: string; role: string }; // no password
131
126
 
132
- const auth = createAuth<DbUser>({
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: Pick<DbUser, 'id' | 'email' | 'name' | 'role'> | null
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