swift-auth 1.0.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.
@@ -0,0 +1,51 @@
1
+ type Cookies = {
2
+ set: (key: string, value: string, options?: {
3
+ secure?: boolean;
4
+ httpOnly?: boolean;
5
+ sameSite?: "strict" | "lax";
6
+ path: string;
7
+ maxAge: number;
8
+ }) => void;
9
+ get: (key: string) => {
10
+ name: string;
11
+ value: string;
12
+ } | undefined;
13
+ delete: (key: string) => void;
14
+ };
15
+
16
+ type AuthPublic<UserType extends Record<string, unknown>> = {
17
+ getCurrentUser(cookies: Pick<Cookies, "get">): Promise<Partial<UserType> | null>;
18
+ createUserSession(user: UserType, cookies: Pick<Cookies, "set">): Promise<void>;
19
+ updateUserSession(user: UserType, cookies: Pick<Cookies, "get" | "set">): Promise<void>;
20
+ removeUserFromSession(cookies: Pick<Cookies, "get" | "delete">): Promise<void>;
21
+ hashPassword(password: string, salt: string): Promise<string>;
22
+ generateSalt(): string;
23
+ comparePassword(params: {
24
+ password: string;
25
+ salt: string;
26
+ hashedPassword: string;
27
+ }): Promise<boolean>;
28
+ };
29
+
30
+ /**
31
+ * Options for creating an auth instance
32
+ */
33
+ type CreateAuthOptions<UserType extends Record<string, unknown>> = {
34
+ ttl: number;
35
+ redis: {
36
+ url: string;
37
+ token: string;
38
+ };
39
+ /**
40
+ * List of user fields to store in session.
41
+ * Must include 'id'.
42
+ */
43
+ sessionFields: (keyof UserType)[];
44
+ };
45
+ /**
46
+ * Create an authentication instance
47
+ * Only exposes public methods, internal fields (_redis, _sessionFields, ttl) are private
48
+ */
49
+ declare function createAuth<UserType extends Record<string, unknown>>(options: CreateAuthOptions<UserType>): AuthPublic<UserType>;
50
+
51
+ export { createAuth };
@@ -0,0 +1,51 @@
1
+ type Cookies = {
2
+ set: (key: string, value: string, options?: {
3
+ secure?: boolean;
4
+ httpOnly?: boolean;
5
+ sameSite?: "strict" | "lax";
6
+ path: string;
7
+ maxAge: number;
8
+ }) => void;
9
+ get: (key: string) => {
10
+ name: string;
11
+ value: string;
12
+ } | undefined;
13
+ delete: (key: string) => void;
14
+ };
15
+
16
+ type AuthPublic<UserType extends Record<string, unknown>> = {
17
+ getCurrentUser(cookies: Pick<Cookies, "get">): Promise<Partial<UserType> | null>;
18
+ createUserSession(user: UserType, cookies: Pick<Cookies, "set">): Promise<void>;
19
+ updateUserSession(user: UserType, cookies: Pick<Cookies, "get" | "set">): Promise<void>;
20
+ removeUserFromSession(cookies: Pick<Cookies, "get" | "delete">): Promise<void>;
21
+ hashPassword(password: string, salt: string): Promise<string>;
22
+ generateSalt(): string;
23
+ comparePassword(params: {
24
+ password: string;
25
+ salt: string;
26
+ hashedPassword: string;
27
+ }): Promise<boolean>;
28
+ };
29
+
30
+ /**
31
+ * Options for creating an auth instance
32
+ */
33
+ type CreateAuthOptions<UserType extends Record<string, unknown>> = {
34
+ ttl: number;
35
+ redis: {
36
+ url: string;
37
+ token: string;
38
+ };
39
+ /**
40
+ * List of user fields to store in session.
41
+ * Must include 'id'.
42
+ */
43
+ sessionFields: (keyof UserType)[];
44
+ };
45
+ /**
46
+ * Create an authentication instance
47
+ * Only exposes public methods, internal fields (_redis, _sessionFields, ttl) are private
48
+ */
49
+ declare function createAuth<UserType extends Record<string, unknown>>(options: CreateAuthOptions<UserType>): AuthPublic<UserType>;
50
+
51
+ export { createAuth };
package/dist/index.js ADDED
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ createAuth: () => createAuth
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/create-auth.ts
38
+ var import_crypto = __toESM(require("crypto"));
39
+
40
+ // src/internal/redis-client.ts
41
+ var import_redis = require("@upstash/redis");
42
+ var createRedisClient = ({ url, token }) => {
43
+ if (!url || !token) {
44
+ throw new Error("Both REDIS URL and TOKEN are required to create Redis client");
45
+ }
46
+ const redisClient = new import_redis.Redis({
47
+ url,
48
+ token
49
+ });
50
+ return redisClient;
51
+ };
52
+
53
+ // src/internal/utils.ts
54
+ function stringifyBigInt(obj) {
55
+ return JSON.stringify(
56
+ obj,
57
+ (_, value) => typeof value === "bigint" ? value.toString() : value
58
+ );
59
+ }
60
+ function generateSessionId() {
61
+ const array = new Uint8Array(512);
62
+ crypto.getRandomValues(array);
63
+ return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
64
+ }
65
+
66
+ // src/internal/keys.ts
67
+ var COOKIE_SESSION_KEY = "session-id";
68
+
69
+ // src/internal/cookie.ts
70
+ function getSessionId(cookies) {
71
+ return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;
72
+ }
73
+ function deleteSessionCookie(cookies) {
74
+ cookies.delete(COOKIE_SESSION_KEY);
75
+ }
76
+
77
+ // src/internal/session.ts
78
+ async function getUserFromSession(auth, cookies) {
79
+ const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;
80
+ if (!sessionId) return null;
81
+ const data = await auth._redis.get(`session:${sessionId}`);
82
+ if (!data) return null;
83
+ const sessionData = typeof data === "string" ? JSON.parse(data) : data;
84
+ const result = {};
85
+ for (const key of auth._sessionFields) {
86
+ if (key in sessionData) result[key] = sessionData[key];
87
+ }
88
+ return result;
89
+ }
90
+ async function createUserSession(auth, user, cookies) {
91
+ const sessionId = generateSessionId();
92
+ const sessionData = {};
93
+ for (const key of auth._sessionFields) {
94
+ if (key in user) sessionData[key] = user[key];
95
+ }
96
+ await auth._redis.set(
97
+ `session:${sessionId}`,
98
+ stringifyBigInt(sessionData),
99
+ { ex: auth._ttl }
100
+ );
101
+ cookies.set(COOKIE_SESSION_KEY, sessionId, {
102
+ secure: process.env.NODE_ENV === "production",
103
+ httpOnly: true,
104
+ sameSite: "lax",
105
+ path: "/",
106
+ maxAge: auth._ttl
107
+ });
108
+ }
109
+ async function updateUserSession(auth, user, cookies) {
110
+ const sessionId = getSessionId(cookies);
111
+ if (!sessionId) return;
112
+ const sessionData = {};
113
+ for (const key of auth._sessionFields) {
114
+ if (key in user) sessionData[key] = user[key];
115
+ }
116
+ await auth._redis.set(
117
+ `session:${sessionId}`,
118
+ stringifyBigInt(sessionData),
119
+ { ex: auth._ttl }
120
+ );
121
+ }
122
+ async function removeUserFromSession(auth, cookies) {
123
+ const sessionId = getSessionId(cookies);
124
+ if (!sessionId) return null;
125
+ await auth._redis.del(`session:${sessionId}`);
126
+ deleteSessionCookie(cookies);
127
+ }
128
+
129
+ // src/create-auth.ts
130
+ function createAuth(options) {
131
+ if (!options.sessionFields.includes("id")) {
132
+ throw new Error("sessionFields must include `id`");
133
+ }
134
+ const _redis = createRedisClient(options.redis);
135
+ const _sessionFields = options.sessionFields;
136
+ const _ttl = options.ttl;
137
+ const auth = {
138
+ _redis,
139
+ _sessionFields,
140
+ _ttl,
141
+ // -------------------
142
+ // Session operations
143
+ // -------------------
144
+ getCurrentUser(cookies) {
145
+ return getUserFromSession({ _redis, _sessionFields, _ttl }, cookies);
146
+ },
147
+ createUserSession(user, cookies) {
148
+ const sessionData = {};
149
+ for (const key of _sessionFields) {
150
+ if (key in user) sessionData[key] = user[key];
151
+ }
152
+ return createUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);
153
+ },
154
+ updateUserSession(user, cookies) {
155
+ const sessionData = {};
156
+ for (const key of _sessionFields) {
157
+ if (key in user) sessionData[key] = user[key];
158
+ }
159
+ return updateUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);
160
+ },
161
+ async removeUserFromSession(cookies) {
162
+ await removeUserFromSession({ _redis, _sessionFields, _ttl }, cookies);
163
+ },
164
+ // -------------------
165
+ // Password helpers
166
+ // -------------------
167
+ hashPassword(password, salt) {
168
+ return new Promise((resolve, reject) => {
169
+ import_crypto.default.scrypt(
170
+ password.normalize(),
171
+ salt,
172
+ 64,
173
+ (err, derivedKey) => {
174
+ if (err) return reject(err);
175
+ resolve(derivedKey.toString("hex").normalize());
176
+ }
177
+ );
178
+ });
179
+ },
180
+ generateSalt() {
181
+ return import_crypto.default.randomBytes(16).toString("hex").normalize();
182
+ },
183
+ async comparePassword({
184
+ password,
185
+ salt,
186
+ hashedPassword
187
+ }) {
188
+ const inputHashed = await auth.hashPassword(password, salt);
189
+ return import_crypto.default.timingSafeEqual(
190
+ Buffer.from(inputHashed, "hex"),
191
+ Buffer.from(hashedPassword, "hex")
192
+ );
193
+ }
194
+ };
195
+ return auth;
196
+ }
197
+ // Annotate the CommonJS export names for ESM import in node:
198
+ 0 && (module.exports = {
199
+ createAuth
200
+ });
201
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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 { 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\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 path: string;\r\n maxAge: 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 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 { 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 | object>(`session:${sessionId}`);\r\n if (!data) return null;\r\n\r\n // Only parse if it's still a string\r\n const sessionData: Partial<UserType> = typeof data === \"string\"\r\n ? JSON.parse(data)\r\n : (data as any);\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 secure: process.env.NODE_ENV === \"production\",\r\n httpOnly: true,\r\n sameSite: \"lax\",\r\n path: \"/\",\r\n maxAge: auth._ttl,\r\n });\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 ADDED
@@ -0,0 +1,164 @@
1
+ // src/create-auth.ts
2
+ import crypto2 from "crypto";
3
+
4
+ // src/internal/redis-client.ts
5
+ import { Redis } from "@upstash/redis";
6
+ var createRedisClient = ({ url, token }) => {
7
+ if (!url || !token) {
8
+ throw new Error("Both REDIS URL and TOKEN are required to create Redis client");
9
+ }
10
+ const redisClient = new Redis({
11
+ url,
12
+ token
13
+ });
14
+ return redisClient;
15
+ };
16
+
17
+ // src/internal/utils.ts
18
+ function stringifyBigInt(obj) {
19
+ return JSON.stringify(
20
+ obj,
21
+ (_, value) => typeof value === "bigint" ? value.toString() : value
22
+ );
23
+ }
24
+ function generateSessionId() {
25
+ const array = new Uint8Array(512);
26
+ crypto.getRandomValues(array);
27
+ return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
28
+ }
29
+
30
+ // src/internal/keys.ts
31
+ var COOKIE_SESSION_KEY = "session-id";
32
+
33
+ // src/internal/cookie.ts
34
+ function getSessionId(cookies) {
35
+ return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;
36
+ }
37
+ function deleteSessionCookie(cookies) {
38
+ cookies.delete(COOKIE_SESSION_KEY);
39
+ }
40
+
41
+ // src/internal/session.ts
42
+ async function getUserFromSession(auth, cookies) {
43
+ const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;
44
+ if (!sessionId) return null;
45
+ const data = await auth._redis.get(`session:${sessionId}`);
46
+ if (!data) return null;
47
+ const sessionData = typeof data === "string" ? JSON.parse(data) : data;
48
+ const result = {};
49
+ for (const key of auth._sessionFields) {
50
+ if (key in sessionData) result[key] = sessionData[key];
51
+ }
52
+ return result;
53
+ }
54
+ async function createUserSession(auth, user, cookies) {
55
+ const sessionId = generateSessionId();
56
+ const sessionData = {};
57
+ for (const key of auth._sessionFields) {
58
+ if (key in user) sessionData[key] = user[key];
59
+ }
60
+ await auth._redis.set(
61
+ `session:${sessionId}`,
62
+ stringifyBigInt(sessionData),
63
+ { ex: auth._ttl }
64
+ );
65
+ cookies.set(COOKIE_SESSION_KEY, sessionId, {
66
+ secure: process.env.NODE_ENV === "production",
67
+ httpOnly: true,
68
+ sameSite: "lax",
69
+ path: "/",
70
+ maxAge: auth._ttl
71
+ });
72
+ }
73
+ async function updateUserSession(auth, user, cookies) {
74
+ const sessionId = getSessionId(cookies);
75
+ if (!sessionId) return;
76
+ const sessionData = {};
77
+ for (const key of auth._sessionFields) {
78
+ if (key in user) sessionData[key] = user[key];
79
+ }
80
+ await auth._redis.set(
81
+ `session:${sessionId}`,
82
+ stringifyBigInt(sessionData),
83
+ { ex: auth._ttl }
84
+ );
85
+ }
86
+ async function removeUserFromSession(auth, cookies) {
87
+ const sessionId = getSessionId(cookies);
88
+ if (!sessionId) return null;
89
+ await auth._redis.del(`session:${sessionId}`);
90
+ deleteSessionCookie(cookies);
91
+ }
92
+
93
+ // src/create-auth.ts
94
+ function createAuth(options) {
95
+ if (!options.sessionFields.includes("id")) {
96
+ throw new Error("sessionFields must include `id`");
97
+ }
98
+ const _redis = createRedisClient(options.redis);
99
+ const _sessionFields = options.sessionFields;
100
+ const _ttl = options.ttl;
101
+ const auth = {
102
+ _redis,
103
+ _sessionFields,
104
+ _ttl,
105
+ // -------------------
106
+ // Session operations
107
+ // -------------------
108
+ getCurrentUser(cookies) {
109
+ return getUserFromSession({ _redis, _sessionFields, _ttl }, cookies);
110
+ },
111
+ createUserSession(user, cookies) {
112
+ const sessionData = {};
113
+ for (const key of _sessionFields) {
114
+ if (key in user) sessionData[key] = user[key];
115
+ }
116
+ return createUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);
117
+ },
118
+ updateUserSession(user, cookies) {
119
+ const sessionData = {};
120
+ for (const key of _sessionFields) {
121
+ if (key in user) sessionData[key] = user[key];
122
+ }
123
+ return updateUserSession({ _redis, _sessionFields, _ttl }, sessionData, cookies);
124
+ },
125
+ async removeUserFromSession(cookies) {
126
+ await removeUserFromSession({ _redis, _sessionFields, _ttl }, cookies);
127
+ },
128
+ // -------------------
129
+ // Password helpers
130
+ // -------------------
131
+ hashPassword(password, salt) {
132
+ return new Promise((resolve, reject) => {
133
+ crypto2.scrypt(
134
+ password.normalize(),
135
+ salt,
136
+ 64,
137
+ (err, derivedKey) => {
138
+ if (err) return reject(err);
139
+ resolve(derivedKey.toString("hex").normalize());
140
+ }
141
+ );
142
+ });
143
+ },
144
+ generateSalt() {
145
+ return crypto2.randomBytes(16).toString("hex").normalize();
146
+ },
147
+ async comparePassword({
148
+ password,
149
+ salt,
150
+ hashedPassword
151
+ }) {
152
+ const inputHashed = await auth.hashPassword(password, salt);
153
+ return crypto2.timingSafeEqual(
154
+ Buffer.from(inputHashed, "hex"),
155
+ Buffer.from(hashedPassword, "hex")
156
+ );
157
+ }
158
+ };
159
+ return auth;
160
+ }
161
+ export {
162
+ createAuth
163
+ };
164
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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 { 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\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 path: string;\r\n maxAge: 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 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 { 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 | object>(`session:${sessionId}`);\r\n if (!data) return null;\r\n\r\n // Only parse if it's still a string\r\n const sessionData: Partial<UserType> = typeof data === \"string\"\r\n ? JSON.parse(data)\r\n : (data as any);\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 secure: process.env.NODE_ENV === \"production\",\r\n httpOnly: true,\r\n sameSite: \"lax\",\r\n path: \"/\",\r\n maxAge: auth._ttl,\r\n });\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 ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "swift-auth",
3
+ "version": "1.0.0",
4
+ "description": "Custom authentication system for apps",
5
+ "main": "dist/index.cjs.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "author": "Taimoor Safdar",
15
+ "license": "MIT",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup"
21
+ },
22
+ "dependencies": {
23
+ "@upstash/redis": "^1.34.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^20.0.0",
27
+ "tsup": "^8.5.1",
28
+ "typescript": "^5.4.0"
29
+ }
30
+ }