nova-auth 0.1.0 → 0.1.2

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/dist/index.d.mts CHANGED
@@ -1,6 +1,3 @@
1
- import { ZodRawShape, ZodObject } from 'zod';
2
- import { Redis } from '@upstash/redis';
3
-
4
1
  type Cookies = {
5
2
  set: (key: string, value: string, options: {
6
3
  secure?: boolean;
@@ -15,14 +12,11 @@ type Cookies = {
15
12
  delete: (key: string) => void;
16
13
  };
17
14
 
18
- type AuthInstance<T extends ZodRawShape = ZodRawShape> = {
19
- _schema: ZodObject<T>;
20
- _redis: Redis;
21
- ttl: number;
22
- getCurrentUser(cookies: Pick<Cookies, "get">): Promise<unknown | null>;
23
- createUserSession(user: unknown, cookies: Pick<Cookies, "set">): Promise<void>;
24
- updateUserSession(user: unknown, cookies: Pick<Cookies, "get">): Promise<void | null>;
25
- removeUserFromSession(cookies: Pick<Cookies, "get" | "delete">): Promise<void | null>;
15
+ type AuthPublic<UserType extends Record<string, unknown>> = {
16
+ getCurrentUser(cookies: Pick<Cookies, "get">): Promise<Partial<UserType> | null>;
17
+ createUserSession(user: UserType, cookies: Pick<Cookies, "set">): Promise<void>;
18
+ updateUserSession(user: UserType, cookies: Pick<Cookies, "get" | "set">): Promise<void>;
19
+ removeUserFromSession(cookies: Pick<Cookies, "get" | "delete">): Promise<void>;
26
20
  hashPassword(password: string, salt: string): Promise<string>;
27
21
  generateSalt(): string;
28
22
  comparePassword(params: {
@@ -32,14 +26,25 @@ type AuthInstance<T extends ZodRawShape = ZodRawShape> = {
32
26
  }): Promise<boolean>;
33
27
  };
34
28
 
35
- type CreateAuthOptions<T extends ZodRawShape> = {
36
- sessionSchema: ZodObject<T>;
29
+ /**
30
+ * Options for creating an auth instance
31
+ */
32
+ type CreateAuthOptions<UserType extends Record<string, unknown>> = {
37
33
  ttl: number;
38
34
  redis: {
39
35
  url: string;
40
36
  token: string;
41
37
  };
38
+ /**
39
+ * List of user fields to store in session.
40
+ * Must include 'id'.
41
+ */
42
+ sessionFields: (keyof UserType)[];
42
43
  };
43
- declare function createAuth<T extends ZodRawShape>(options: CreateAuthOptions<T>): AuthInstance<T>;
44
+ /**
45
+ * Create an authentication instance
46
+ * Only exposes public methods, internal fields (_redis, _sessionFields, ttl) are private
47
+ */
48
+ declare function createAuth<UserType extends Record<string, unknown>>(options: CreateAuthOptions<UserType>): AuthPublic<UserType>;
44
49
 
45
50
  export { createAuth };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,3 @@
1
- import { ZodRawShape, ZodObject } from 'zod';
2
- import { Redis } from '@upstash/redis';
3
-
4
1
  type Cookies = {
5
2
  set: (key: string, value: string, options: {
6
3
  secure?: boolean;
@@ -15,14 +12,11 @@ type Cookies = {
15
12
  delete: (key: string) => void;
16
13
  };
17
14
 
18
- type AuthInstance<T extends ZodRawShape = ZodRawShape> = {
19
- _schema: ZodObject<T>;
20
- _redis: Redis;
21
- ttl: number;
22
- getCurrentUser(cookies: Pick<Cookies, "get">): Promise<unknown | null>;
23
- createUserSession(user: unknown, cookies: Pick<Cookies, "set">): Promise<void>;
24
- updateUserSession(user: unknown, cookies: Pick<Cookies, "get">): Promise<void | null>;
25
- removeUserFromSession(cookies: Pick<Cookies, "get" | "delete">): Promise<void | null>;
15
+ type AuthPublic<UserType extends Record<string, unknown>> = {
16
+ getCurrentUser(cookies: Pick<Cookies, "get">): Promise<Partial<UserType> | null>;
17
+ createUserSession(user: UserType, cookies: Pick<Cookies, "set">): Promise<void>;
18
+ updateUserSession(user: UserType, cookies: Pick<Cookies, "get" | "set">): Promise<void>;
19
+ removeUserFromSession(cookies: Pick<Cookies, "get" | "delete">): Promise<void>;
26
20
  hashPassword(password: string, salt: string): Promise<string>;
27
21
  generateSalt(): string;
28
22
  comparePassword(params: {
@@ -32,14 +26,25 @@ type AuthInstance<T extends ZodRawShape = ZodRawShape> = {
32
26
  }): Promise<boolean>;
33
27
  };
34
28
 
35
- type CreateAuthOptions<T extends ZodRawShape> = {
36
- sessionSchema: ZodObject<T>;
29
+ /**
30
+ * Options for creating an auth instance
31
+ */
32
+ type CreateAuthOptions<UserType extends Record<string, unknown>> = {
37
33
  ttl: number;
38
34
  redis: {
39
35
  url: string;
40
36
  token: string;
41
37
  };
38
+ /**
39
+ * List of user fields to store in session.
40
+ * Must include 'id'.
41
+ */
42
+ sessionFields: (keyof UserType)[];
42
43
  };
43
- declare function createAuth<T extends ZodRawShape>(options: CreateAuthOptions<T>): AuthInstance<T>;
44
+ /**
45
+ * Create an authentication instance
46
+ * Only exposes public methods, internal fields (_redis, _sessionFields, ttl) are private
47
+ */
48
+ declare function createAuth<UserType extends Record<string, unknown>>(options: CreateAuthOptions<UserType>): AuthPublic<UserType>;
44
49
 
45
50
  export { createAuth };
package/dist/index.js CHANGED
@@ -80,31 +80,42 @@ async function getUserFromSession(auth, cookies) {
80
80
  if (!sessionId) return null;
81
81
  const data = await auth._redis.get(`session:${sessionId}`);
82
82
  if (!data) return null;
83
- return auth._schema.parse(JSON.parse(data));
83
+ const sessionData = JSON.parse(data);
84
+ const result = {};
85
+ for (const key of auth._sessionFields) {
86
+ if (key in sessionData) result[key] = sessionData[key];
87
+ }
88
+ return result;
84
89
  }
85
90
  async function createUserSession(auth, user, cookies) {
86
91
  const sessionId = generateSessionId();
87
- const data = auth._schema.parse(user);
92
+ const sessionData = {};
93
+ for (const key of auth._sessionFields) {
94
+ if (key in user) sessionData[key] = user[key];
95
+ }
88
96
  await auth._redis.set(
89
97
  `session:${sessionId}`,
90
- stringifyBigInt(data),
91
- { ex: auth.ttl }
98
+ stringifyBigInt(sessionData),
99
+ { ex: auth._ttl }
92
100
  );
93
101
  cookies.set(COOKIE_SESSION_KEY, sessionId, {
94
102
  httpOnly: true,
95
103
  secure: true,
96
104
  sameSite: "lax",
97
- expires: Math.floor(Date.now() / 1e3) + auth.ttl
105
+ expires: Math.floor(Date.now() / 1e3) + auth._ttl
98
106
  });
99
107
  }
100
108
  async function updateUserSession(auth, user, cookies) {
101
109
  const sessionId = getSessionId(cookies);
102
- if (!sessionId) return null;
103
- const data = auth._schema.parse(user);
110
+ if (!sessionId) return;
111
+ const sessionData = {};
112
+ for (const key of auth._sessionFields) {
113
+ if (key in user) sessionData[key] = user[key];
114
+ }
104
115
  await auth._redis.set(
105
116
  `session:${sessionId}`,
106
- stringifyBigInt(data),
107
- { ex: auth.ttl }
117
+ stringifyBigInt(sessionData),
118
+ { ex: auth._ttl }
108
119
  );
109
120
  }
110
121
  async function removeUserFromSession(auth, cookies) {
@@ -116,27 +127,42 @@ async function removeUserFromSession(auth, cookies) {
116
127
 
117
128
  // src/create-auth.ts
118
129
  function createAuth(options) {
119
- if (!("id" in options.sessionSchema.shape)) {
120
- throw new Error("sessionSchema must include an `id` field");
130
+ if (!options.sessionFields.includes("id")) {
131
+ throw new Error("sessionFields must include `id`");
121
132
  }
122
- const redis = createRedisClient(options.redis);
133
+ const _redis = createRedisClient(options.redis);
134
+ const _sessionFields = options.sessionFields;
135
+ const _ttl = options.ttl;
123
136
  const auth = {
124
- _schema: options.sessionSchema,
125
- _redis: redis,
126
- ttl: options.ttl,
137
+ _redis,
138
+ _sessionFields,
139
+ _ttl,
140
+ // -------------------
141
+ // Session operations
142
+ // -------------------
127
143
  getCurrentUser(cookies) {
128
- return getUserFromSession(auth, cookies);
144
+ return getUserFromSession({ _redis, _sessionFields, _ttl }, cookies);
129
145
  },
130
146
  createUserSession(user, cookies) {
131
- return createUserSession(auth, user, cookies);
147
+ const sessionData = {};
148
+ for (const key of _sessionFields) {
149
+ if (key in user) sessionData[key] = user[key];
150
+ }
151
+ return createUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);
132
152
  },
133
153
  updateUserSession(user, cookies) {
134
- return updateUserSession(auth, user, cookies);
154
+ const sessionData = {};
155
+ for (const key of _sessionFields) {
156
+ if (key in user) sessionData[key] = user[key];
157
+ }
158
+ return updateUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);
135
159
  },
136
- removeUserFromSession(cookies) {
137
- return removeUserFromSession(auth, cookies);
160
+ async removeUserFromSession(cookies) {
161
+ await removeUserFromSession({ _redis, _sessionFields, _ttl }, cookies);
138
162
  },
139
- // 🔒 Add password helpers
163
+ // -------------------
164
+ // Password helpers
165
+ // -------------------
140
166
  hashPassword(password, salt) {
141
167
  return new Promise((resolve, reject) => {
142
168
  import_crypto.default.scrypt(
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/create-auth.ts","../src/internal/redis-client.ts","../src/internal/utils.ts","../src/internal/keys.ts","../src/internal/cookie.ts","../src/internal/session.ts"],"sourcesContent":["export { createAuth } from \"./create-auth\";","import crypto from \"crypto\";\r\nimport { ZodObject, ZodRawShape } from \"zod\";\r\nimport { createRedisClient } from \"./internal/redis-client\";\r\nimport {\r\n getUserFromSession,\r\n createUserSession,\r\n updateUserSession,\r\n removeUserFromSession,\r\n} from \"./internal/session\";\r\nimport { AuthInstance } from \"./internal/types\";\r\n\r\ntype CreateAuthOptions<T extends ZodRawShape> = {\r\n sessionSchema: ZodObject<T>;\r\n ttl: number;\r\n redis: {\r\n url: string;\r\n token: string;\r\n };\r\n};\r\n\r\nexport function createAuth<T extends ZodRawShape>(\r\n options: CreateAuthOptions<T>\r\n): AuthInstance<T> {\r\n if (!(\"id\" in options.sessionSchema.shape)) {\r\n throw new Error(\"sessionSchema must include an `id` field\");\r\n }\r\n\r\n const redis = createRedisClient(options.redis);\r\n\r\n const auth: AuthInstance<T> = {\r\n _schema: options.sessionSchema,\r\n _redis: redis,\r\n ttl: options.ttl,\r\n\r\n getCurrentUser(cookies) {\r\n return getUserFromSession(auth, cookies);\r\n },\r\n\r\n createUserSession(user, cookies) {\r\n return createUserSession(auth, user, cookies);\r\n },\r\n\r\n updateUserSession(user, cookies) {\r\n return updateUserSession(auth, user, cookies);\r\n },\r\n\r\n removeUserFromSession(cookies) {\r\n return removeUserFromSession(auth, cookies);\r\n },\r\n\r\n // 🔒 Add password helpers\r\n hashPassword(password: string, salt: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n crypto.scrypt(\r\n password.normalize(),\r\n salt,\r\n 64,\r\n (err: Error | null, derivedKey: Buffer) => {\r\n if (err) return reject(err);\r\n resolve(derivedKey.toString(\"hex\").normalize());\r\n }\r\n );\r\n });\r\n },\r\n\r\n generateSalt(): string {\r\n return crypto.randomBytes(16).toString(\"hex\").normalize();\r\n },\r\n\r\n async comparePassword({\r\n password,\r\n salt,\r\n hashedPassword,\r\n }: {\r\n password: string;\r\n salt: string;\r\n hashedPassword: string;\r\n }): Promise<boolean> {\r\n const inputHashed = await auth.hashPassword(password, salt);\r\n return crypto.timingSafeEqual(\r\n Buffer.from(inputHashed, \"hex\"),\r\n Buffer.from(hashedPassword, \"hex\")\r\n );\r\n },\r\n };\r\n\r\n return auth;\r\n}\r\n","import { Redis } from \"@upstash/redis\";\r\n\r\nexport type CreateRedisClientOptions = {\r\n url: string;\r\n token: string;\r\n};\r\n\r\nexport const createRedisClient = ({ url, token }: CreateRedisClientOptions) => {\r\n if (!url || !token) {\r\n throw new Error(\"Both REDIS URL and TOKEN are required to create Redis client\");\r\n }\r\n\r\n const redisClient = new Redis({\r\n url,\r\n token,\r\n });\r\n\r\n return redisClient;\r\n};\r\n","export function stringifyBigInt<T>(obj: T): string {\r\n return JSON.stringify(obj, (_, value) =>\r\n typeof value === \"bigint\" ? value.toString() : value\r\n );\r\n}\r\n\r\nexport function generateSessionId(): string {\r\n const array = new Uint8Array(512);\r\n crypto.getRandomValues(array);\r\n\r\n return Array.from(array)\r\n .map((b) => b.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n}","export const COOKIE_SESSION_KEY = \"session-id\"","import { COOKIE_SESSION_KEY } from \"./keys\";\r\nimport { AuthInstance } from \"./types\";\r\n\r\nexport type Cookies = {\r\n set: (\r\n key: string,\r\n value: string,\r\n options: {\r\n secure?: boolean;\r\n httpOnly?: boolean;\r\n sameSite?: \"strict\" | \"lax\";\r\n expires?: number;\r\n }\r\n ) => void;\r\n get: (key: string) => { name: string; value: string } | undefined;\r\n delete: (key: string) => void;\r\n};\r\n\r\nexport function setSessionCookie(\r\n auth: AuthInstance,\r\n sessionId: string,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n secure: true,\r\n httpOnly: true,\r\n sameSite: \"lax\",\r\n expires: Date.now() + Number(auth.ttl) * 1000,\r\n });\r\n}\r\n\r\nexport function getSessionId(\r\n cookies: Pick<Cookies, \"get\">\r\n): string | null {\r\n return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;\r\n}\r\n\r\nexport function deleteSessionCookie(\r\n cookies: Pick<Cookies, \"delete\">\r\n) {\r\n cookies.delete(COOKIE_SESSION_KEY);\r\n}\r\n","import { stringifyBigInt, generateSessionId } from \"./utils\";\r\nimport {\r\n getSessionId,\r\n deleteSessionCookie,\r\n Cookies,\r\n} from \"./cookie\";\r\nimport { AuthInstance } from \"./types\";\r\nimport { COOKIE_SESSION_KEY } from \"./keys\";\r\n\r\nexport async function getUserFromSession(\r\n auth: AuthInstance,\r\n cookies: Pick<Cookies, \"get\">\r\n) {\r\n const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;\r\n if (!sessionId) return null;\r\n\r\n const data = await auth._redis.get<string>(`session:${sessionId}`)\r\n if (!data) return null;\r\n\r\n return auth._schema.parse(JSON.parse(data));\r\n}\r\n\r\nexport async function createUserSession<T>(\r\n auth: AuthInstance,\r\n user: T,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n const sessionId = generateSessionId();\r\n const data = auth._schema.parse(user);\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(data),\r\n { ex: auth.ttl }\r\n );\r\n\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n expires: Math.floor(Date.now() / 1000) + auth.ttl,\r\n });\r\n}\r\n\r\nexport async function updateUserSession<T>(\r\n auth: AuthInstance,\r\n user: T,\r\n cookies: Pick<Cookies, \"get\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n const data = auth._schema.parse(user);\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(data),\r\n { ex: auth.ttl }\r\n );\r\n}\r\n\r\nexport async function removeUserFromSession(\r\n auth: AuthInstance,\r\n cookies: Pick<Cookies, \"get\" | \"delete\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n await auth._redis.del(`session:${sessionId}`);\r\n deleteSessionCookie(cookies);\r\n}\r\n"],"mappings":"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","names":["crypto"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/create-auth.ts","../src/internal/redis-client.ts","../src/internal/utils.ts","../src/internal/keys.ts","../src/internal/cookie.ts","../src/internal/session.ts"],"sourcesContent":["export { createAuth } from \"./create-auth\";","import crypto from \"crypto\";\r\nimport { createRedisClient } from \"./internal/redis-client\";\r\nimport {\r\n getUserFromSession,\r\n createUserSession as internalCreateUserSession,\r\n updateUserSession as internalUpdateUserSession,\r\n removeUserFromSession as internalRemoveUserFromSession,\r\n} from \"./internal/session\";\r\nimport { AuthInstance, AuthPublic } from \"./internal/types\";\r\nimport { Cookies } from \"./internal/cookie\";\r\n\r\n/**\r\n * Options for creating an auth instance\r\n */\r\nexport type CreateAuthOptions<UserType extends Record<string, unknown>> = {\r\n ttl: number;\r\n redis: {\r\n url: string;\r\n token: string;\r\n };\r\n /**\r\n * List of user fields to store in session.\r\n * Must include 'id'.\r\n */\r\n sessionFields: (keyof UserType)[];\r\n};\r\n\r\n/**\r\n * Create an authentication instance\r\n * Only exposes public methods, internal fields (_redis, _sessionFields, ttl) are private\r\n */\r\nexport function createAuth<UserType extends Record<string, unknown>>(\r\n options: CreateAuthOptions<UserType>\r\n): AuthPublic<UserType> {\r\n // Ensure 'id' is included in sessionFields\r\n if (!options.sessionFields.includes(\"id\" as keyof UserType)) {\r\n throw new Error(\"sessionFields must include `id`\");\r\n }\r\n\r\n // Internal fields (not exposed)\r\n const _redis = createRedisClient(options.redis);\r\n const _sessionFields = options.sessionFields;\r\n const _ttl = options.ttl;\r\n\r\n // The public API\r\n const auth: AuthInstance<UserType> = {\r\n _redis,\r\n _sessionFields,\r\n _ttl,\r\n // -------------------\r\n // Session operations\r\n // -------------------\r\n getCurrentUser(cookies) {\r\n return getUserFromSession({ _redis, _sessionFields, _ttl: _ttl }, cookies);\r\n },\r\n\r\n createUserSession(user, cookies) {\r\n const sessionData: Partial<UserType> = {} as any;\r\n for (const key of _sessionFields) {\r\n if (key in user) sessionData[key] = user[key];\r\n }\r\n return internalCreateUserSession({ _redis, _sessionFields, _ttl: _ttl }, sessionData, cookies);\r\n },\r\n\r\n updateUserSession(user, cookies: Pick<Cookies, \"get\" | \"set\">) {\r\n const sessionData: Partial<UserType> = {};\r\n for (const key of _sessionFields) {\r\n if (key in user) sessionData[key] = user[key];\r\n }\r\n return internalUpdateUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);\r\n },\r\n\r\n async removeUserFromSession(cookies) {\r\n await internalRemoveUserFromSession({ _redis, _sessionFields, _ttl: _ttl }, cookies);\r\n },\r\n\r\n // -------------------\r\n // Password helpers\r\n // -------------------\r\n hashPassword(password: string, salt: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n crypto.scrypt(\r\n password.normalize(),\r\n salt,\r\n 64,\r\n (err: Error | null, derivedKey: Buffer) => {\r\n if (err) return reject(err);\r\n resolve(derivedKey.toString(\"hex\").normalize());\r\n }\r\n );\r\n });\r\n },\r\n\r\n generateSalt(): string {\r\n return crypto.randomBytes(16).toString(\"hex\").normalize();\r\n },\r\n\r\n async comparePassword({\r\n password,\r\n salt,\r\n hashedPassword,\r\n }: {\r\n password: string;\r\n salt: string;\r\n hashedPassword: string;\r\n }): Promise<boolean> {\r\n const inputHashed = await auth.hashPassword(password, salt);\r\n return crypto.timingSafeEqual(\r\n Buffer.from(inputHashed, \"hex\"),\r\n Buffer.from(hashedPassword, \"hex\")\r\n );\r\n },\r\n };\r\n\r\n return auth;\r\n}","import { Redis } from \"@upstash/redis\";\r\n\r\nexport type CreateRedisClientOptions = {\r\n url: string;\r\n token: string;\r\n};\r\n\r\nexport const createRedisClient = ({ url, token }: CreateRedisClientOptions) => {\r\n if (!url || !token) {\r\n throw new Error(\"Both REDIS URL and TOKEN are required to create Redis client\");\r\n }\r\n\r\n const redisClient = new Redis({\r\n url,\r\n token,\r\n });\r\n\r\n return redisClient;\r\n};\r\n","export function stringifyBigInt<T>(obj: T): string {\r\n return JSON.stringify(obj, (_, value) =>\r\n typeof value === \"bigint\" ? value.toString() : value\r\n );\r\n}\r\n\r\nexport function generateSessionId(): string {\r\n const array = new Uint8Array(512);\r\n crypto.getRandomValues(array);\r\n\r\n return Array.from(array)\r\n .map((b) => b.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n}","export const COOKIE_SESSION_KEY = \"session-id\"","import { COOKIE_SESSION_KEY } from \"./keys\";\r\nimport { AuthInstance } from \"./types\";\r\n\r\nexport type Cookies = {\r\n set: (\r\n key: string,\r\n value: string,\r\n options: {\r\n secure?: boolean;\r\n httpOnly?: boolean;\r\n sameSite?: \"strict\" | \"lax\";\r\n expires?: number;\r\n }\r\n ) => void;\r\n get: (key: string) => { name: string; value: string } | undefined;\r\n delete: (key: string) => void;\r\n};\r\n\r\nexport function setSessionCookie<UserType extends Record<string, unknown>>(\r\n auth: AuthInstance<UserType>,\r\n sessionId: string,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n secure: true,\r\n httpOnly: true,\r\n sameSite: \"lax\",\r\n expires: Date.now() + Number(auth._ttl) * 1000,\r\n });\r\n}\r\n\r\nexport function getSessionId(\r\n cookies: Pick<Cookies, \"get\">\r\n): string | null {\r\n return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;\r\n}\r\n\r\nexport function deleteSessionCookie(\r\n cookies: Pick<Cookies, \"delete\">\r\n) {\r\n cookies.delete(COOKIE_SESSION_KEY);\r\n}\r\n","import { stringifyBigInt, generateSessionId } from \"./utils\";\r\nimport {\r\n getSessionId,\r\n deleteSessionCookie,\r\n Cookies,\r\n} from \"./cookie\";\r\nimport { AuthInstance } from \"./types\";\r\nimport { COOKIE_SESSION_KEY } from \"./keys\";\r\nimport { Redis } from \"@upstash/redis\";\r\n\r\nexport async function getUserFromSession<UserType extends Record<string, unknown>>(\r\n auth: { _redis: Redis; _sessionFields: (keyof UserType)[]; _ttl: number },\r\n cookies: Pick<Cookies, \"get\">\r\n): Promise<Partial<UserType> | null> {\r\n const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;\r\n if (!sessionId) return null;\r\n\r\n const data = await auth._redis.get<string>(`session:${sessionId}`);\r\n if (!data) return null;\r\n\r\n // Parse the session data\r\n const sessionData: Partial<UserType> = JSON.parse(data);\r\n\r\n // Optional: pick only _sessionFields to ensure type safety\r\n const result: Partial<UserType> = {};\r\n for (const key of auth._sessionFields) {\r\n if (key in sessionData) result[key] = sessionData[key];\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport async function createUserSession<UserType extends Record<string, unknown>>(\r\n auth: { _redis: Redis; _sessionFields: (keyof UserType)[]; _ttl: number },\r\n user: Partial<UserType>,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n const sessionId = generateSessionId();\r\n\r\n // Pick only session fields\r\n const sessionData: Partial<UserType> = {};\r\n for (const key of auth._sessionFields) {\r\n if (key in user) sessionData[key] = user[key];\r\n }\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(sessionData),\r\n { ex: auth._ttl }\r\n );\r\n\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n expires: Math.floor(Date.now() / 1000) + auth._ttl,\r\n });\r\n}\r\n\r\nexport async function updateUserSession<UserType extends Record<string, unknown>>(\r\n auth: { _redis: Redis; _sessionFields: (keyof UserType)[]; _ttl: number },\r\n user: Partial<UserType>, // ✅ allow partial here\r\n cookies: Pick<Cookies, \"get\" | \"set\">\r\n): Promise<void> {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return; // ✅ just return void\r\n\r\n // Pick only session fields\r\n const sessionData: Partial<UserType> = {} as any;\r\n for (const key of auth._sessionFields) {\r\n if (key in user) sessionData[key] = user[key];\r\n }\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(sessionData),\r\n { ex: auth._ttl }\r\n );\r\n}\r\n\r\nexport async function removeUserFromSession<UserType extends Record<string, unknown>>(\r\n auth: { _redis: Redis; _sessionFields: (keyof UserType)[]; _ttl: number },\r\n cookies: Pick<Cookies, \"get\" | \"delete\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n await auth._redis.del(`session:${sessionId}`);\r\n deleteSessionCookie(cookies);\r\n}\r\n"],"mappings":"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","names":["crypto"]}
package/dist/index.mjs CHANGED
@@ -44,31 +44,42 @@ async function getUserFromSession(auth, cookies) {
44
44
  if (!sessionId) return null;
45
45
  const data = await auth._redis.get(`session:${sessionId}`);
46
46
  if (!data) return null;
47
- return auth._schema.parse(JSON.parse(data));
47
+ const sessionData = JSON.parse(data);
48
+ const result = {};
49
+ for (const key of auth._sessionFields) {
50
+ if (key in sessionData) result[key] = sessionData[key];
51
+ }
52
+ return result;
48
53
  }
49
54
  async function createUserSession(auth, user, cookies) {
50
55
  const sessionId = generateSessionId();
51
- const data = auth._schema.parse(user);
56
+ const sessionData = {};
57
+ for (const key of auth._sessionFields) {
58
+ if (key in user) sessionData[key] = user[key];
59
+ }
52
60
  await auth._redis.set(
53
61
  `session:${sessionId}`,
54
- stringifyBigInt(data),
55
- { ex: auth.ttl }
62
+ stringifyBigInt(sessionData),
63
+ { ex: auth._ttl }
56
64
  );
57
65
  cookies.set(COOKIE_SESSION_KEY, sessionId, {
58
66
  httpOnly: true,
59
67
  secure: true,
60
68
  sameSite: "lax",
61
- expires: Math.floor(Date.now() / 1e3) + auth.ttl
69
+ expires: Math.floor(Date.now() / 1e3) + auth._ttl
62
70
  });
63
71
  }
64
72
  async function updateUserSession(auth, user, cookies) {
65
73
  const sessionId = getSessionId(cookies);
66
- if (!sessionId) return null;
67
- const data = auth._schema.parse(user);
74
+ if (!sessionId) return;
75
+ const sessionData = {};
76
+ for (const key of auth._sessionFields) {
77
+ if (key in user) sessionData[key] = user[key];
78
+ }
68
79
  await auth._redis.set(
69
80
  `session:${sessionId}`,
70
- stringifyBigInt(data),
71
- { ex: auth.ttl }
81
+ stringifyBigInt(sessionData),
82
+ { ex: auth._ttl }
72
83
  );
73
84
  }
74
85
  async function removeUserFromSession(auth, cookies) {
@@ -80,27 +91,42 @@ async function removeUserFromSession(auth, cookies) {
80
91
 
81
92
  // src/create-auth.ts
82
93
  function createAuth(options) {
83
- if (!("id" in options.sessionSchema.shape)) {
84
- throw new Error("sessionSchema must include an `id` field");
94
+ if (!options.sessionFields.includes("id")) {
95
+ throw new Error("sessionFields must include `id`");
85
96
  }
86
- const redis = createRedisClient(options.redis);
97
+ const _redis = createRedisClient(options.redis);
98
+ const _sessionFields = options.sessionFields;
99
+ const _ttl = options.ttl;
87
100
  const auth = {
88
- _schema: options.sessionSchema,
89
- _redis: redis,
90
- ttl: options.ttl,
101
+ _redis,
102
+ _sessionFields,
103
+ _ttl,
104
+ // -------------------
105
+ // Session operations
106
+ // -------------------
91
107
  getCurrentUser(cookies) {
92
- return getUserFromSession(auth, cookies);
108
+ return getUserFromSession({ _redis, _sessionFields, _ttl }, cookies);
93
109
  },
94
110
  createUserSession(user, cookies) {
95
- return createUserSession(auth, user, cookies);
111
+ const sessionData = {};
112
+ for (const key of _sessionFields) {
113
+ if (key in user) sessionData[key] = user[key];
114
+ }
115
+ return createUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);
96
116
  },
97
117
  updateUserSession(user, cookies) {
98
- return updateUserSession(auth, user, cookies);
118
+ const sessionData = {};
119
+ for (const key of _sessionFields) {
120
+ if (key in user) sessionData[key] = user[key];
121
+ }
122
+ return updateUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);
99
123
  },
100
- removeUserFromSession(cookies) {
101
- return removeUserFromSession(auth, cookies);
124
+ async removeUserFromSession(cookies) {
125
+ await removeUserFromSession({ _redis, _sessionFields, _ttl }, cookies);
102
126
  },
103
- // 🔒 Add password helpers
127
+ // -------------------
128
+ // Password helpers
129
+ // -------------------
104
130
  hashPassword(password, salt) {
105
131
  return new Promise((resolve, reject) => {
106
132
  crypto2.scrypt(
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/create-auth.ts","../src/internal/redis-client.ts","../src/internal/utils.ts","../src/internal/keys.ts","../src/internal/cookie.ts","../src/internal/session.ts"],"sourcesContent":["import crypto from \"crypto\";\r\nimport { ZodObject, ZodRawShape } from \"zod\";\r\nimport { createRedisClient } from \"./internal/redis-client\";\r\nimport {\r\n getUserFromSession,\r\n createUserSession,\r\n updateUserSession,\r\n removeUserFromSession,\r\n} from \"./internal/session\";\r\nimport { AuthInstance } from \"./internal/types\";\r\n\r\ntype CreateAuthOptions<T extends ZodRawShape> = {\r\n sessionSchema: ZodObject<T>;\r\n ttl: number;\r\n redis: {\r\n url: string;\r\n token: string;\r\n };\r\n};\r\n\r\nexport function createAuth<T extends ZodRawShape>(\r\n options: CreateAuthOptions<T>\r\n): AuthInstance<T> {\r\n if (!(\"id\" in options.sessionSchema.shape)) {\r\n throw new Error(\"sessionSchema must include an `id` field\");\r\n }\r\n\r\n const redis = createRedisClient(options.redis);\r\n\r\n const auth: AuthInstance<T> = {\r\n _schema: options.sessionSchema,\r\n _redis: redis,\r\n ttl: options.ttl,\r\n\r\n getCurrentUser(cookies) {\r\n return getUserFromSession(auth, cookies);\r\n },\r\n\r\n createUserSession(user, cookies) {\r\n return createUserSession(auth, user, cookies);\r\n },\r\n\r\n updateUserSession(user, cookies) {\r\n return updateUserSession(auth, user, cookies);\r\n },\r\n\r\n removeUserFromSession(cookies) {\r\n return removeUserFromSession(auth, cookies);\r\n },\r\n\r\n // 🔒 Add password helpers\r\n hashPassword(password: string, salt: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n crypto.scrypt(\r\n password.normalize(),\r\n salt,\r\n 64,\r\n (err: Error | null, derivedKey: Buffer) => {\r\n if (err) return reject(err);\r\n resolve(derivedKey.toString(\"hex\").normalize());\r\n }\r\n );\r\n });\r\n },\r\n\r\n generateSalt(): string {\r\n return crypto.randomBytes(16).toString(\"hex\").normalize();\r\n },\r\n\r\n async comparePassword({\r\n password,\r\n salt,\r\n hashedPassword,\r\n }: {\r\n password: string;\r\n salt: string;\r\n hashedPassword: string;\r\n }): Promise<boolean> {\r\n const inputHashed = await auth.hashPassword(password, salt);\r\n return crypto.timingSafeEqual(\r\n Buffer.from(inputHashed, \"hex\"),\r\n Buffer.from(hashedPassword, \"hex\")\r\n );\r\n },\r\n };\r\n\r\n return auth;\r\n}\r\n","import { Redis } from \"@upstash/redis\";\r\n\r\nexport type CreateRedisClientOptions = {\r\n url: string;\r\n token: string;\r\n};\r\n\r\nexport const createRedisClient = ({ url, token }: CreateRedisClientOptions) => {\r\n if (!url || !token) {\r\n throw new Error(\"Both REDIS URL and TOKEN are required to create Redis client\");\r\n }\r\n\r\n const redisClient = new Redis({\r\n url,\r\n token,\r\n });\r\n\r\n return redisClient;\r\n};\r\n","export function stringifyBigInt<T>(obj: T): string {\r\n return JSON.stringify(obj, (_, value) =>\r\n typeof value === \"bigint\" ? value.toString() : value\r\n );\r\n}\r\n\r\nexport function generateSessionId(): string {\r\n const array = new Uint8Array(512);\r\n crypto.getRandomValues(array);\r\n\r\n return Array.from(array)\r\n .map((b) => b.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n}","export const COOKIE_SESSION_KEY = \"session-id\"","import { COOKIE_SESSION_KEY } from \"./keys\";\r\nimport { AuthInstance } from \"./types\";\r\n\r\nexport type Cookies = {\r\n set: (\r\n key: string,\r\n value: string,\r\n options: {\r\n secure?: boolean;\r\n httpOnly?: boolean;\r\n sameSite?: \"strict\" | \"lax\";\r\n expires?: number;\r\n }\r\n ) => void;\r\n get: (key: string) => { name: string; value: string } | undefined;\r\n delete: (key: string) => void;\r\n};\r\n\r\nexport function setSessionCookie(\r\n auth: AuthInstance,\r\n sessionId: string,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n secure: true,\r\n httpOnly: true,\r\n sameSite: \"lax\",\r\n expires: Date.now() + Number(auth.ttl) * 1000,\r\n });\r\n}\r\n\r\nexport function getSessionId(\r\n cookies: Pick<Cookies, \"get\">\r\n): string | null {\r\n return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;\r\n}\r\n\r\nexport function deleteSessionCookie(\r\n cookies: Pick<Cookies, \"delete\">\r\n) {\r\n cookies.delete(COOKIE_SESSION_KEY);\r\n}\r\n","import { stringifyBigInt, generateSessionId } from \"./utils\";\r\nimport {\r\n getSessionId,\r\n deleteSessionCookie,\r\n Cookies,\r\n} from \"./cookie\";\r\nimport { AuthInstance } from \"./types\";\r\nimport { COOKIE_SESSION_KEY } from \"./keys\";\r\n\r\nexport async function getUserFromSession(\r\n auth: AuthInstance,\r\n cookies: Pick<Cookies, \"get\">\r\n) {\r\n const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;\r\n if (!sessionId) return null;\r\n\r\n const data = await auth._redis.get<string>(`session:${sessionId}`)\r\n if (!data) return null;\r\n\r\n return auth._schema.parse(JSON.parse(data));\r\n}\r\n\r\nexport async function createUserSession<T>(\r\n auth: AuthInstance,\r\n user: T,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n const sessionId = generateSessionId();\r\n const data = auth._schema.parse(user);\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(data),\r\n { ex: auth.ttl }\r\n );\r\n\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n expires: Math.floor(Date.now() / 1000) + auth.ttl,\r\n });\r\n}\r\n\r\nexport async function updateUserSession<T>(\r\n auth: AuthInstance,\r\n user: T,\r\n cookies: Pick<Cookies, \"get\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n const data = auth._schema.parse(user);\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(data),\r\n { ex: auth.ttl }\r\n );\r\n}\r\n\r\nexport async function removeUserFromSession(\r\n auth: AuthInstance,\r\n cookies: Pick<Cookies, \"get\" | \"delete\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n await auth._redis.del(`session:${sessionId}`);\r\n deleteSessionCookie(cookies);\r\n}\r\n"],"mappings":"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","names":["crypto","crypto"]}
1
+ {"version":3,"sources":["../src/create-auth.ts","../src/internal/redis-client.ts","../src/internal/utils.ts","../src/internal/keys.ts","../src/internal/cookie.ts","../src/internal/session.ts"],"sourcesContent":["import crypto from \"crypto\";\r\nimport { createRedisClient } from \"./internal/redis-client\";\r\nimport {\r\n getUserFromSession,\r\n createUserSession as internalCreateUserSession,\r\n updateUserSession as internalUpdateUserSession,\r\n removeUserFromSession as internalRemoveUserFromSession,\r\n} from \"./internal/session\";\r\nimport { AuthInstance, AuthPublic } from \"./internal/types\";\r\nimport { Cookies } from \"./internal/cookie\";\r\n\r\n/**\r\n * Options for creating an auth instance\r\n */\r\nexport type CreateAuthOptions<UserType extends Record<string, unknown>> = {\r\n ttl: number;\r\n redis: {\r\n url: string;\r\n token: string;\r\n };\r\n /**\r\n * List of user fields to store in session.\r\n * Must include 'id'.\r\n */\r\n sessionFields: (keyof UserType)[];\r\n};\r\n\r\n/**\r\n * Create an authentication instance\r\n * Only exposes public methods, internal fields (_redis, _sessionFields, ttl) are private\r\n */\r\nexport function createAuth<UserType extends Record<string, unknown>>(\r\n options: CreateAuthOptions<UserType>\r\n): AuthPublic<UserType> {\r\n // Ensure 'id' is included in sessionFields\r\n if (!options.sessionFields.includes(\"id\" as keyof UserType)) {\r\n throw new Error(\"sessionFields must include `id`\");\r\n }\r\n\r\n // Internal fields (not exposed)\r\n const _redis = createRedisClient(options.redis);\r\n const _sessionFields = options.sessionFields;\r\n const _ttl = options.ttl;\r\n\r\n // The public API\r\n const auth: AuthInstance<UserType> = {\r\n _redis,\r\n _sessionFields,\r\n _ttl,\r\n // -------------------\r\n // Session operations\r\n // -------------------\r\n getCurrentUser(cookies) {\r\n return getUserFromSession({ _redis, _sessionFields, _ttl: _ttl }, cookies);\r\n },\r\n\r\n createUserSession(user, cookies) {\r\n const sessionData: Partial<UserType> = {} as any;\r\n for (const key of _sessionFields) {\r\n if (key in user) sessionData[key] = user[key];\r\n }\r\n return internalCreateUserSession({ _redis, _sessionFields, _ttl: _ttl }, sessionData, cookies);\r\n },\r\n\r\n updateUserSession(user, cookies: Pick<Cookies, \"get\" | \"set\">) {\r\n const sessionData: Partial<UserType> = {};\r\n for (const key of _sessionFields) {\r\n if (key in user) sessionData[key] = user[key];\r\n }\r\n return internalUpdateUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);\r\n },\r\n\r\n async removeUserFromSession(cookies) {\r\n await internalRemoveUserFromSession({ _redis, _sessionFields, _ttl: _ttl }, cookies);\r\n },\r\n\r\n // -------------------\r\n // Password helpers\r\n // -------------------\r\n hashPassword(password: string, salt: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n crypto.scrypt(\r\n password.normalize(),\r\n salt,\r\n 64,\r\n (err: Error | null, derivedKey: Buffer) => {\r\n if (err) return reject(err);\r\n resolve(derivedKey.toString(\"hex\").normalize());\r\n }\r\n );\r\n });\r\n },\r\n\r\n generateSalt(): string {\r\n return crypto.randomBytes(16).toString(\"hex\").normalize();\r\n },\r\n\r\n async comparePassword({\r\n password,\r\n salt,\r\n hashedPassword,\r\n }: {\r\n password: string;\r\n salt: string;\r\n hashedPassword: string;\r\n }): Promise<boolean> {\r\n const inputHashed = await auth.hashPassword(password, salt);\r\n return crypto.timingSafeEqual(\r\n Buffer.from(inputHashed, \"hex\"),\r\n Buffer.from(hashedPassword, \"hex\")\r\n );\r\n },\r\n };\r\n\r\n return auth;\r\n}","import { Redis } from \"@upstash/redis\";\r\n\r\nexport type CreateRedisClientOptions = {\r\n url: string;\r\n token: string;\r\n};\r\n\r\nexport const createRedisClient = ({ url, token }: CreateRedisClientOptions) => {\r\n if (!url || !token) {\r\n throw new Error(\"Both REDIS URL and TOKEN are required to create Redis client\");\r\n }\r\n\r\n const redisClient = new Redis({\r\n url,\r\n token,\r\n });\r\n\r\n return redisClient;\r\n};\r\n","export function stringifyBigInt<T>(obj: T): string {\r\n return JSON.stringify(obj, (_, value) =>\r\n typeof value === \"bigint\" ? value.toString() : value\r\n );\r\n}\r\n\r\nexport function generateSessionId(): string {\r\n const array = new Uint8Array(512);\r\n crypto.getRandomValues(array);\r\n\r\n return Array.from(array)\r\n .map((b) => b.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n}","export const COOKIE_SESSION_KEY = \"session-id\"","import { COOKIE_SESSION_KEY } from \"./keys\";\r\nimport { AuthInstance } from \"./types\";\r\n\r\nexport type Cookies = {\r\n set: (\r\n key: string,\r\n value: string,\r\n options: {\r\n secure?: boolean;\r\n httpOnly?: boolean;\r\n sameSite?: \"strict\" | \"lax\";\r\n expires?: number;\r\n }\r\n ) => void;\r\n get: (key: string) => { name: string; value: string } | undefined;\r\n delete: (key: string) => void;\r\n};\r\n\r\nexport function setSessionCookie<UserType extends Record<string, unknown>>(\r\n auth: AuthInstance<UserType>,\r\n sessionId: string,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n secure: true,\r\n httpOnly: true,\r\n sameSite: \"lax\",\r\n expires: Date.now() + Number(auth._ttl) * 1000,\r\n });\r\n}\r\n\r\nexport function getSessionId(\r\n cookies: Pick<Cookies, \"get\">\r\n): string | null {\r\n return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;\r\n}\r\n\r\nexport function deleteSessionCookie(\r\n cookies: Pick<Cookies, \"delete\">\r\n) {\r\n cookies.delete(COOKIE_SESSION_KEY);\r\n}\r\n","import { stringifyBigInt, generateSessionId } from \"./utils\";\r\nimport {\r\n getSessionId,\r\n deleteSessionCookie,\r\n Cookies,\r\n} from \"./cookie\";\r\nimport { AuthInstance } from \"./types\";\r\nimport { COOKIE_SESSION_KEY } from \"./keys\";\r\nimport { Redis } from \"@upstash/redis\";\r\n\r\nexport async function getUserFromSession<UserType extends Record<string, unknown>>(\r\n auth: { _redis: Redis; _sessionFields: (keyof UserType)[]; _ttl: number },\r\n cookies: Pick<Cookies, \"get\">\r\n): Promise<Partial<UserType> | null> {\r\n const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;\r\n if (!sessionId) return null;\r\n\r\n const data = await auth._redis.get<string>(`session:${sessionId}`);\r\n if (!data) return null;\r\n\r\n // Parse the session data\r\n const sessionData: Partial<UserType> = JSON.parse(data);\r\n\r\n // Optional: pick only _sessionFields to ensure type safety\r\n const result: Partial<UserType> = {};\r\n for (const key of auth._sessionFields) {\r\n if (key in sessionData) result[key] = sessionData[key];\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport async function createUserSession<UserType extends Record<string, unknown>>(\r\n auth: { _redis: Redis; _sessionFields: (keyof UserType)[]; _ttl: number },\r\n user: Partial<UserType>,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n const sessionId = generateSessionId();\r\n\r\n // Pick only session fields\r\n const sessionData: Partial<UserType> = {};\r\n for (const key of auth._sessionFields) {\r\n if (key in user) sessionData[key] = user[key];\r\n }\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(sessionData),\r\n { ex: auth._ttl }\r\n );\r\n\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n expires: Math.floor(Date.now() / 1000) + auth._ttl,\r\n });\r\n}\r\n\r\nexport async function updateUserSession<UserType extends Record<string, unknown>>(\r\n auth: { _redis: Redis; _sessionFields: (keyof UserType)[]; _ttl: number },\r\n user: Partial<UserType>, // ✅ allow partial here\r\n cookies: Pick<Cookies, \"get\" | \"set\">\r\n): Promise<void> {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return; // ✅ just return void\r\n\r\n // Pick only session fields\r\n const sessionData: Partial<UserType> = {} as any;\r\n for (const key of auth._sessionFields) {\r\n if (key in user) sessionData[key] = user[key];\r\n }\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(sessionData),\r\n { ex: auth._ttl }\r\n );\r\n}\r\n\r\nexport async function removeUserFromSession<UserType extends Record<string, unknown>>(\r\n auth: { _redis: Redis; _sessionFields: (keyof UserType)[]; _ttl: number },\r\n cookies: Pick<Cookies, \"get\" | \"delete\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n await auth._redis.del(`session:${sessionId}`);\r\n deleteSessionCookie(cookies);\r\n}\r\n"],"mappings":"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","names":["crypto","crypto"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nova-auth",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Custom authentication system for apps",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.js",
@@ -20,8 +20,7 @@
20
20
  "build": "tsup"
21
21
  },
22
22
  "dependencies": {
23
- "@upstash/redis": "^1.34.0",
24
- "zod": "^3.23.0"
23
+ "@upstash/redis": "^1.34.0"
25
24
  },
26
25
  "devDependencies": {
27
26
  "@types/node": "^20.0.0",