@mesob/auth-hono 0.0.7 → 0.1.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 +172 -0
- package/dist/index-CScADcDn.d.ts +137 -0
- package/dist/index-ULpI-i0z.d.ts +2008 -0
- package/dist/index.d.ts +23 -15
- package/dist/index.js +5272 -1885
- package/dist/index.js.map +1 -1
- package/dist/lib/cleanup.d.ts +11 -0
- package/dist/lib/cleanup.js +296 -0
- package/dist/lib/cleanup.js.map +1 -0
- package/dist/lib/cookie.d.ts +18 -0
- package/dist/lib/cookie.js +40 -0
- package/dist/lib/cookie.js.map +1 -0
- package/dist/lib/crypto.js +5 -0
- package/dist/lib/crypto.js.map +1 -1
- package/dist/lib/docs.d.ts +11 -0
- package/dist/lib/docs.js +14 -0
- package/dist/lib/docs.js.map +1 -0
- package/dist/lib/normalize-user.d.ts +32 -0
- package/dist/lib/normalize-user.js +15 -0
- package/dist/lib/normalize-user.js.map +1 -0
- package/dist/lib/openapi-config.d.ts +31 -0
- package/dist/lib/openapi-config.js +66 -0
- package/dist/lib/openapi-config.js.map +1 -0
- package/dist/lib/session.d.ts +43 -18
- package/dist/lib/session.js +57 -23
- package/dist/lib/session.js.map +1 -1
- package/dist/lib/tenant.d.ts +8 -1
- package/dist/lib/tenant.js +5 -4
- package/dist/lib/tenant.js.map +1 -1
- package/package.json +7 -4
- package/dist/index-J2ZbOnZO.d.ts +0 -76
- package/dist/lib/jwt.d.ts +0 -15
- package/dist/lib/jwt.js +0 -25
- package/dist/lib/jwt.js.map +0 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// src/lib/openapi-config.ts
|
|
2
|
+
var createOpenApiConfig = (config) => {
|
|
3
|
+
const basePath = config.basePath || "";
|
|
4
|
+
const servers = config.docs?.servers || [
|
|
5
|
+
{
|
|
6
|
+
url: "http://localhost:3000",
|
|
7
|
+
description: "Development server"
|
|
8
|
+
}
|
|
9
|
+
];
|
|
10
|
+
const serversWithBasePath = servers.map((server) => ({
|
|
11
|
+
...server,
|
|
12
|
+
url: `${server.url.replace(/\/$/, "")}${basePath}`
|
|
13
|
+
}));
|
|
14
|
+
return {
|
|
15
|
+
openapi: "3.0.0",
|
|
16
|
+
info: {
|
|
17
|
+
title: config.docs?.title || "IAM API",
|
|
18
|
+
version: config.docs?.version || "1.0.0",
|
|
19
|
+
description: "Complete Identity and Access Management API"
|
|
20
|
+
},
|
|
21
|
+
servers: serversWithBasePath,
|
|
22
|
+
tags: [
|
|
23
|
+
{ name: "Auth", description: "Authentication endpoints" },
|
|
24
|
+
{ name: "Profile", description: "User profile management" },
|
|
25
|
+
{ name: "Password", description: "Password management" },
|
|
26
|
+
{ name: "Email", description: "Email verification" },
|
|
27
|
+
{ name: "Phone", description: "Phone verification" },
|
|
28
|
+
{ name: "Users", description: "User management (IAM)" },
|
|
29
|
+
{ name: "Tenants", description: "Tenant management (IAM)" },
|
|
30
|
+
{ name: "Domains", description: "Domain management (IAM)" },
|
|
31
|
+
{ name: "Roles", description: "Role management (IAM)" },
|
|
32
|
+
{ name: "Permissions", description: "Permission management (IAM)" },
|
|
33
|
+
{
|
|
34
|
+
name: "Role Permissions",
|
|
35
|
+
description: "Role-permission mapping (IAM)"
|
|
36
|
+
},
|
|
37
|
+
{ name: "User Roles", description: "User-role assignment (IAM)" },
|
|
38
|
+
{ name: "Sessions", description: "Session management (IAM)" },
|
|
39
|
+
{ name: "Verifications", description: "Verification management (IAM)" }
|
|
40
|
+
],
|
|
41
|
+
"x-tagGroups": [
|
|
42
|
+
{
|
|
43
|
+
name: "Authentication",
|
|
44
|
+
tags: ["Auth", "Profile", "Password", "Email", "Phone"]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "IAM Management",
|
|
48
|
+
tags: [
|
|
49
|
+
"Users",
|
|
50
|
+
"Tenants",
|
|
51
|
+
"Domains",
|
|
52
|
+
"Roles",
|
|
53
|
+
"Permissions",
|
|
54
|
+
"Role Permissions",
|
|
55
|
+
"User Roles",
|
|
56
|
+
"Sessions",
|
|
57
|
+
"Verifications"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
export {
|
|
64
|
+
createOpenApiConfig
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=openapi-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/openapi-config.ts"],"sourcesContent":["import type { AuthConfig } from '../types';\n\nexport const createOpenApiConfig = (config: AuthConfig) => {\n const basePath = config.basePath || '';\n const servers = config.docs?.servers || [\n {\n url: 'http://localhost:3000',\n description: 'Development server',\n },\n ];\n const serversWithBasePath = servers.map((server) => ({\n ...server,\n url: `${server.url.replace(/\\/$/, '')}${basePath}`,\n }));\n\n return {\n openapi: '3.0.0',\n info: {\n title: config.docs?.title || 'IAM API',\n version: config.docs?.version || '1.0.0',\n description: 'Complete Identity and Access Management API',\n },\n servers: serversWithBasePath,\n tags: [\n { name: 'Auth', description: 'Authentication endpoints' },\n { name: 'Profile', description: 'User profile management' },\n { name: 'Password', description: 'Password management' },\n { name: 'Email', description: 'Email verification' },\n { name: 'Phone', description: 'Phone verification' },\n { name: 'Users', description: 'User management (IAM)' },\n { name: 'Tenants', description: 'Tenant management (IAM)' },\n { name: 'Domains', description: 'Domain management (IAM)' },\n { name: 'Roles', description: 'Role management (IAM)' },\n { name: 'Permissions', description: 'Permission management (IAM)' },\n {\n name: 'Role Permissions',\n description: 'Role-permission mapping (IAM)',\n },\n { name: 'User Roles', description: 'User-role assignment (IAM)' },\n { name: 'Sessions', description: 'Session management (IAM)' },\n { name: 'Verifications', description: 'Verification management (IAM)' },\n ],\n 'x-tagGroups': [\n {\n name: 'Authentication',\n tags: ['Auth', 'Profile', 'Password', 'Email', 'Phone'],\n },\n {\n name: 'IAM Management',\n tags: [\n 'Users',\n 'Tenants',\n 'Domains',\n 'Roles',\n 'Permissions',\n 'Role Permissions',\n 'User Roles',\n 'Sessions',\n 'Verifications',\n ],\n },\n ],\n };\n};\n"],"mappings":";AAEO,IAAM,sBAAsB,CAAC,WAAuB;AACzD,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,UAAU,OAAO,MAAM,WAAW;AAAA,IACtC;AAAA,MACE,KAAK;AAAA,MACL,aAAa;AAAA,IACf;AAAA,EACF;AACA,QAAM,sBAAsB,QAAQ,IAAI,CAAC,YAAY;AAAA,IACnD,GAAG;AAAA,IACH,KAAK,GAAG,OAAO,IAAI,QAAQ,OAAO,EAAE,CAAC,GAAG,QAAQ;AAAA,EAClD,EAAE;AAEF,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM;AAAA,MACJ,OAAO,OAAO,MAAM,SAAS;AAAA,MAC7B,SAAS,OAAO,MAAM,WAAW;AAAA,MACjC,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,IACT,MAAM;AAAA,MACJ,EAAE,MAAM,QAAQ,aAAa,2BAA2B;AAAA,MACxD,EAAE,MAAM,WAAW,aAAa,0BAA0B;AAAA,MAC1D,EAAE,MAAM,YAAY,aAAa,sBAAsB;AAAA,MACvD,EAAE,MAAM,SAAS,aAAa,qBAAqB;AAAA,MACnD,EAAE,MAAM,SAAS,aAAa,qBAAqB;AAAA,MACnD,EAAE,MAAM,SAAS,aAAa,wBAAwB;AAAA,MACtD,EAAE,MAAM,WAAW,aAAa,0BAA0B;AAAA,MAC1D,EAAE,MAAM,WAAW,aAAa,0BAA0B;AAAA,MAC1D,EAAE,MAAM,SAAS,aAAa,wBAAwB;AAAA,MACtD,EAAE,MAAM,eAAe,aAAa,8BAA8B;AAAA,MAClE;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,EAAE,MAAM,cAAc,aAAa,6BAA6B;AAAA,MAChE,EAAE,MAAM,YAAY,aAAa,2BAA2B;AAAA,MAC5D,EAAE,MAAM,iBAAiB,aAAa,gCAAgC;AAAA,IACxE;AAAA,IACA,eAAe;AAAA,MACb;AAAA,QACE,MAAM;AAAA,QACN,MAAM,CAAC,QAAQ,WAAW,YAAY,SAAS,OAAO;AAAA,MACxD;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/lib/session.d.ts
CHANGED
|
@@ -1,23 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
declare const
|
|
11
|
-
id: string;
|
|
12
|
-
expiresAt: string;
|
|
13
|
-
createdAt: string | undefined;
|
|
14
|
-
userAgent: string | null;
|
|
15
|
-
ip: string | null;
|
|
16
|
-
};
|
|
17
|
-
declare const generateHandle: (seed?: string | null) => string;
|
|
1
|
+
import { b as SessionConfig } from '../index-CScADcDn.js';
|
|
2
|
+
import 'hono';
|
|
3
|
+
import '@hono/zod-openapi';
|
|
4
|
+
import '../index-ULpI-i0z.js';
|
|
5
|
+
import 'drizzle-orm/node-postgres';
|
|
6
|
+
import 'drizzle-orm/pg-core';
|
|
7
|
+
import 'drizzle-orm';
|
|
8
|
+
import 'pg';
|
|
9
|
+
|
|
10
|
+
declare const generateHandle: () => string;
|
|
18
11
|
declare const getSessionExpiresAt: (days?: number) => string;
|
|
19
12
|
declare const parseDuration: (duration: string) => number;
|
|
20
13
|
declare const addDuration: (duration: string) => string;
|
|
21
14
|
declare const generateOtpCode: (length?: number) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Get session expiration duration based on rememberMe option
|
|
17
|
+
*/
|
|
18
|
+
declare const getSessionDuration: ({ sessionConfig, rememberMe, }: {
|
|
19
|
+
sessionConfig: SessionConfig;
|
|
20
|
+
rememberMe: boolean;
|
|
21
|
+
}) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Get the update age threshold based on session type
|
|
24
|
+
*/
|
|
25
|
+
declare const getSessionUpdateAge: ({ sessionConfig, rememberMe, }: {
|
|
26
|
+
sessionConfig: SessionConfig;
|
|
27
|
+
rememberMe: boolean;
|
|
28
|
+
}) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Check if session needs refresh based on remaining time
|
|
31
|
+
*/
|
|
32
|
+
declare const shouldRefreshSession: ({ expiresAt, updateAge, }: {
|
|
33
|
+
expiresAt: string;
|
|
34
|
+
updateAge: string;
|
|
35
|
+
}) => boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Get new expiration time for session refresh
|
|
38
|
+
*/
|
|
39
|
+
declare const getRefreshedExpiresAt: ({ sessionConfig, rememberMe, }: {
|
|
40
|
+
sessionConfig: SessionConfig;
|
|
41
|
+
rememberMe: boolean;
|
|
42
|
+
}) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Check if session is expired
|
|
45
|
+
*/
|
|
46
|
+
declare const isSessionExpired: (expiresAt: string) => boolean;
|
|
22
47
|
|
|
23
|
-
export {
|
|
48
|
+
export { addDuration, generateHandle, generateOtpCode, getRefreshedExpiresAt, getSessionDuration, getSessionExpiresAt, getSessionUpdateAge, isSessionExpired, parseDuration, shouldRefreshSession };
|
package/dist/lib/session.js
CHANGED
|
@@ -1,27 +1,13 @@
|
|
|
1
1
|
// src/lib/session.ts
|
|
2
2
|
import { dayjs } from "@mesob/common";
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
expiresAt,
|
|
7
|
-
createdAt,
|
|
8
|
-
userAgent,
|
|
9
|
-
ip
|
|
10
|
-
}) => ({
|
|
11
|
-
id,
|
|
12
|
-
expiresAt,
|
|
13
|
-
createdAt,
|
|
14
|
-
userAgent: userAgent || null,
|
|
15
|
-
ip: ip || null
|
|
16
|
-
});
|
|
17
|
-
var generateHandle = (seed) => {
|
|
18
|
-
const base = seed?.replace(/[^a-zA-Z0-9]/g, "").toLowerCase() || `user${Math.random().toString(36).slice(2, 8)}`;
|
|
19
|
-
return `${base}-${Math.random().toString(36).slice(2, 6)}`;
|
|
3
|
+
import { nanoid } from "nanoid";
|
|
4
|
+
var generateHandle = () => {
|
|
5
|
+
return nanoid(10);
|
|
20
6
|
};
|
|
21
7
|
var getSessionExpiresAt = (days = 30) => dayjs().add(days, "day").toISOString();
|
|
22
8
|
var parseDuration = (duration) => {
|
|
23
9
|
const match = duration.match(/^(\d+)([smhd])$/);
|
|
24
|
-
if (!match) {
|
|
10
|
+
if (!(match?.[1] && match[2])) {
|
|
25
11
|
throw new Error(`Invalid duration format: ${duration}`);
|
|
26
12
|
}
|
|
27
13
|
const value = Number.parseInt(match[1], 10);
|
|
@@ -40,19 +26,67 @@ var addDuration = (duration) => {
|
|
|
40
26
|
};
|
|
41
27
|
var generateOtpCode = (length = 6) => {
|
|
42
28
|
const digits = "0123456789";
|
|
29
|
+
const maxValid = 250;
|
|
43
30
|
let code = "";
|
|
44
|
-
|
|
45
|
-
|
|
31
|
+
while (code.length < length) {
|
|
32
|
+
const randomValues = new Uint8Array(length - code.length);
|
|
33
|
+
crypto.getRandomValues(randomValues);
|
|
34
|
+
for (const val of randomValues) {
|
|
35
|
+
if (val < maxValid && code.length < length) {
|
|
36
|
+
code += digits[val % 10];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
46
39
|
}
|
|
47
40
|
return code;
|
|
48
41
|
};
|
|
42
|
+
var getSessionDuration = ({
|
|
43
|
+
sessionConfig,
|
|
44
|
+
rememberMe
|
|
45
|
+
}) => {
|
|
46
|
+
if (rememberMe) {
|
|
47
|
+
return sessionConfig.rememberMeExpiresIn;
|
|
48
|
+
}
|
|
49
|
+
return sessionConfig.shortSessionExpiresIn;
|
|
50
|
+
};
|
|
51
|
+
var getSessionUpdateAge = ({
|
|
52
|
+
sessionConfig,
|
|
53
|
+
rememberMe
|
|
54
|
+
}) => {
|
|
55
|
+
if (rememberMe) {
|
|
56
|
+
return sessionConfig.updateAge;
|
|
57
|
+
}
|
|
58
|
+
return sessionConfig.shortSessionUpdateAge;
|
|
59
|
+
};
|
|
60
|
+
var shouldRefreshSession = ({
|
|
61
|
+
expiresAt,
|
|
62
|
+
updateAge
|
|
63
|
+
}) => {
|
|
64
|
+
const updateAgeSeconds = parseDuration(updateAge);
|
|
65
|
+
const now = dayjs();
|
|
66
|
+
const expires = dayjs(expiresAt);
|
|
67
|
+
const remainingSeconds = expires.diff(now, "second");
|
|
68
|
+
return remainingSeconds > 0 && remainingSeconds <= updateAgeSeconds;
|
|
69
|
+
};
|
|
70
|
+
var getRefreshedExpiresAt = ({
|
|
71
|
+
sessionConfig,
|
|
72
|
+
rememberMe
|
|
73
|
+
}) => {
|
|
74
|
+
const duration = getSessionDuration({ sessionConfig, rememberMe });
|
|
75
|
+
return addDuration(duration);
|
|
76
|
+
};
|
|
77
|
+
var isSessionExpired = (expiresAt) => {
|
|
78
|
+
return dayjs(expiresAt).isBefore(dayjs());
|
|
79
|
+
};
|
|
49
80
|
export {
|
|
50
|
-
SESSION_COOKIE_NAME,
|
|
51
81
|
addDuration,
|
|
52
|
-
buildSessionPayload,
|
|
53
82
|
generateHandle,
|
|
54
83
|
generateOtpCode,
|
|
84
|
+
getRefreshedExpiresAt,
|
|
85
|
+
getSessionDuration,
|
|
55
86
|
getSessionExpiresAt,
|
|
56
|
-
|
|
87
|
+
getSessionUpdateAge,
|
|
88
|
+
isSessionExpired,
|
|
89
|
+
parseDuration,
|
|
90
|
+
shouldRefreshSession
|
|
57
91
|
};
|
|
58
92
|
//# sourceMappingURL=session.js.map
|
package/dist/lib/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/session.ts"],"sourcesContent":["import { dayjs } from '@mesob/common';\
|
|
1
|
+
{"version":3,"sources":["../../src/lib/session.ts"],"sourcesContent":["import { dayjs } from '@mesob/common';\nimport { nanoid } from 'nanoid';\nimport type { SessionConfig } from '../types';\n\nexport const generateHandle = (): string => {\n return nanoid(10);\n};\n\nexport const getSessionExpiresAt = (days = 30) =>\n dayjs().add(days, 'day').toISOString();\n\nexport const parseDuration = (duration: string): number => {\n const match = duration.match(/^(\\d+)([smhd])$/);\n if (!(match?.[1] && match[2])) {\n throw new Error(`Invalid duration format: ${duration}`);\n }\n const value = Number.parseInt(match[1], 10);\n const unit = match[2];\n const multipliers: Record<string, number> = {\n s: 1,\n m: 60,\n h: 3600,\n d: 86400,\n };\n return value * (multipliers[unit] || 1);\n};\n\nexport const addDuration = (duration: string): string => {\n const seconds = parseDuration(duration);\n return dayjs().add(seconds, 'second').toISOString();\n};\n\nexport const generateOtpCode = (length = 6): string => {\n const digits = '0123456789';\n const maxValid = 250; // largest multiple of 10 <= 255 to avoid modulo bias\n let code = '';\n\n while (code.length < length) {\n const randomValues = new Uint8Array(length - code.length);\n crypto.getRandomValues(randomValues);\n for (const val of randomValues) {\n if (val < maxValid && code.length < length) {\n code += digits[val % 10];\n }\n }\n }\n return code;\n};\n\n/**\n * Get session expiration duration based on rememberMe option\n */\nexport const getSessionDuration = ({\n sessionConfig,\n rememberMe,\n}: {\n sessionConfig: SessionConfig;\n rememberMe: boolean;\n}): string => {\n if (rememberMe) {\n return sessionConfig.rememberMeExpiresIn;\n }\n return sessionConfig.shortSessionExpiresIn;\n};\n\n/**\n * Get the update age threshold based on session type\n */\nexport const getSessionUpdateAge = ({\n sessionConfig,\n rememberMe,\n}: {\n sessionConfig: SessionConfig;\n rememberMe: boolean;\n}): string => {\n if (rememberMe) {\n return sessionConfig.updateAge;\n }\n return sessionConfig.shortSessionUpdateAge;\n};\n\n/**\n * Check if session needs refresh based on remaining time\n */\nexport const shouldRefreshSession = ({\n expiresAt,\n updateAge,\n}: {\n expiresAt: string;\n updateAge: string;\n}): boolean => {\n const updateAgeSeconds = parseDuration(updateAge);\n const now = dayjs();\n const expires = dayjs(expiresAt);\n const remainingSeconds = expires.diff(now, 'second');\n\n return remainingSeconds > 0 && remainingSeconds <= updateAgeSeconds;\n};\n\n/**\n * Get new expiration time for session refresh\n */\nexport const getRefreshedExpiresAt = ({\n sessionConfig,\n rememberMe,\n}: {\n sessionConfig: SessionConfig;\n rememberMe: boolean;\n}): string => {\n const duration = getSessionDuration({ sessionConfig, rememberMe });\n return addDuration(duration);\n};\n\n/**\n * Check if session is expired\n */\nexport const isSessionExpired = (expiresAt: string): boolean => {\n return dayjs(expiresAt).isBefore(dayjs());\n};\n"],"mappings":";AAAA,SAAS,aAAa;AACtB,SAAS,cAAc;AAGhB,IAAM,iBAAiB,MAAc;AAC1C,SAAO,OAAO,EAAE;AAClB;AAEO,IAAM,sBAAsB,CAAC,OAAO,OACzC,MAAM,EAAE,IAAI,MAAM,KAAK,EAAE,YAAY;AAEhC,IAAM,gBAAgB,CAAC,aAA6B;AACzD,QAAM,QAAQ,SAAS,MAAM,iBAAiB;AAC9C,MAAI,EAAE,QAAQ,CAAC,KAAK,MAAM,CAAC,IAAI;AAC7B,UAAM,IAAI,MAAM,4BAA4B,QAAQ,EAAE;AAAA,EACxD;AACA,QAAM,QAAQ,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAC1C,QAAM,OAAO,MAAM,CAAC;AACpB,QAAM,cAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACA,SAAO,SAAS,YAAY,IAAI,KAAK;AACvC;AAEO,IAAM,cAAc,CAAC,aAA6B;AACvD,QAAM,UAAU,cAAc,QAAQ;AACtC,SAAO,MAAM,EAAE,IAAI,SAAS,QAAQ,EAAE,YAAY;AACpD;AAEO,IAAM,kBAAkB,CAAC,SAAS,MAAc;AACrD,QAAM,SAAS;AACf,QAAM,WAAW;AACjB,MAAI,OAAO;AAEX,SAAO,KAAK,SAAS,QAAQ;AAC3B,UAAM,eAAe,IAAI,WAAW,SAAS,KAAK,MAAM;AACxD,WAAO,gBAAgB,YAAY;AACnC,eAAW,OAAO,cAAc;AAC9B,UAAI,MAAM,YAAY,KAAK,SAAS,QAAQ;AAC1C,gBAAQ,OAAO,MAAM,EAAE;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKO,IAAM,qBAAqB,CAAC;AAAA,EACjC;AAAA,EACA;AACF,MAGc;AACZ,MAAI,YAAY;AACd,WAAO,cAAc;AAAA,EACvB;AACA,SAAO,cAAc;AACvB;AAKO,IAAM,sBAAsB,CAAC;AAAA,EAClC;AAAA,EACA;AACF,MAGc;AACZ,MAAI,YAAY;AACd,WAAO,cAAc;AAAA,EACvB;AACA,SAAO,cAAc;AACvB;AAKO,IAAM,uBAAuB,CAAC;AAAA,EACnC;AAAA,EACA;AACF,MAGe;AACb,QAAM,mBAAmB,cAAc,SAAS;AAChD,QAAM,MAAM,MAAM;AAClB,QAAM,UAAU,MAAM,SAAS;AAC/B,QAAM,mBAAmB,QAAQ,KAAK,KAAK,QAAQ;AAEnD,SAAO,mBAAmB,KAAK,oBAAoB;AACrD;AAKO,IAAM,wBAAwB,CAAC;AAAA,EACpC;AAAA,EACA;AACF,MAGc;AACZ,QAAM,WAAW,mBAAmB,EAAE,eAAe,WAAW,CAAC;AACjE,SAAO,YAAY,QAAQ;AAC7B;AAKO,IAAM,mBAAmB,CAAC,cAA+B;AAC9D,SAAO,MAAM,SAAS,EAAE,SAAS,MAAM,CAAC;AAC1C;","names":[]}
|
package/dist/lib/tenant.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import { A as AuthConfig } from '../index-
|
|
1
|
+
import { A as AuthConfig } from '../index-CScADcDn.js';
|
|
2
|
+
import 'hono';
|
|
3
|
+
import '@hono/zod-openapi';
|
|
4
|
+
import '../index-ULpI-i0z.js';
|
|
5
|
+
import 'drizzle-orm/node-postgres';
|
|
6
|
+
import 'drizzle-orm/pg-core';
|
|
7
|
+
import 'drizzle-orm';
|
|
8
|
+
import 'pg';
|
|
2
9
|
|
|
3
10
|
declare const ensureTenantId: (config: AuthConfig, tenantId: string | undefined) => string;
|
|
4
11
|
|
package/dist/lib/tenant.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/lib/tenant.ts
|
|
2
2
|
import { HTTPException } from "hono/http-exception";
|
|
3
3
|
var ensureTenantId = (config, tenantId) => {
|
|
4
|
-
|
|
4
|
+
const enableTenant = config.tenant?.enabled ?? true;
|
|
5
|
+
if (enableTenant) {
|
|
5
6
|
if (!tenantId) {
|
|
6
7
|
throw new HTTPException(400, {
|
|
7
8
|
message: "Missing tenantId. Tenant isolation is enabled."
|
|
@@ -9,12 +10,12 @@ var ensureTenantId = (config, tenantId) => {
|
|
|
9
10
|
}
|
|
10
11
|
return tenantId;
|
|
11
12
|
}
|
|
12
|
-
if (!config.tenantId) {
|
|
13
|
+
if (!config.tenant?.tenantId) {
|
|
13
14
|
throw new HTTPException(500, {
|
|
14
|
-
message: "tenantId must be provided in config when
|
|
15
|
+
message: "tenantId must be provided in config.tenant when tenant.enabled is false."
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
|
-
return config.tenantId;
|
|
18
|
+
return config.tenant.tenantId;
|
|
18
19
|
};
|
|
19
20
|
export {
|
|
20
21
|
ensureTenantId
|
package/dist/lib/tenant.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/tenant.ts"],"sourcesContent":["import { HTTPException } from 'hono/http-exception';\nimport type { AuthConfig } from '../types';\n\nexport const ensureTenantId = (\n config: AuthConfig,\n tenantId: string | undefined,\n): string => {\n if (
|
|
1
|
+
{"version":3,"sources":["../../src/lib/tenant.ts"],"sourcesContent":["import { HTTPException } from 'hono/http-exception';\nimport type { AuthConfig } from '../types';\n\nexport const ensureTenantId = (\n config: AuthConfig,\n tenantId: string | undefined,\n): string => {\n const enableTenant = config.tenant?.enabled ?? true;\n if (enableTenant) {\n if (!tenantId) {\n throw new HTTPException(400, {\n message: 'Missing tenantId. Tenant isolation is enabled.',\n });\n }\n return tenantId;\n }\n\n // When tenant is disabled, use tenantId from config\n if (!config.tenant?.tenantId) {\n throw new HTTPException(500, {\n message:\n 'tenantId must be provided in config.tenant when tenant.enabled is false.',\n });\n }\n return config.tenant.tenantId;\n};\n"],"mappings":";AAAA,SAAS,qBAAqB;AAGvB,IAAM,iBAAiB,CAC5B,QACA,aACW;AACX,QAAM,eAAe,OAAO,QAAQ,WAAW;AAC/C,MAAI,cAAc;AAChB,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,cAAc,KAAK;AAAA,QAC3B,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,OAAO,QAAQ,UAAU;AAC5B,UAAM,IAAI,cAAc,KAAK;AAAA,MAC3B,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AACA,SAAO,OAAO,OAAO;AACvB;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mesob/auth-hono",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -19,17 +19,20 @@
|
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@hono/zod-openapi": "^1.
|
|
22
|
+
"@hono/zod-openapi": "^1.2.0",
|
|
23
23
|
"@noble/hashes": "^2.0.1",
|
|
24
|
+
"@scalar/hono-api-reference": "^0.9.22",
|
|
24
25
|
"argon2-wasm-edge": "^1.0.23",
|
|
26
|
+
"deepmerge-ts": "^7.1.5",
|
|
25
27
|
"drizzle-orm": "^0.44.4",
|
|
26
28
|
"hash-wasm": "^4.12.0",
|
|
27
|
-
"hono": "^4.
|
|
29
|
+
"hono": "^4.11.3",
|
|
28
30
|
"jsonwebtoken": "^9.0.2",
|
|
31
|
+
"nanoid": "^5.1.5",
|
|
29
32
|
"pg": "^8.16.3",
|
|
30
33
|
"resend": "^4.8.0",
|
|
31
34
|
"zod": "^4.1.12",
|
|
32
|
-
"@mesob/common": "0.0
|
|
35
|
+
"@mesob/common": "0.1.0"
|
|
33
36
|
},
|
|
34
37
|
"devDependencies": {
|
|
35
38
|
"@types/jsonwebtoken": "^9.0.10",
|
package/dist/index-J2ZbOnZO.d.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
type UserRole = {
|
|
2
|
-
id: string;
|
|
3
|
-
roleId: string;
|
|
4
|
-
code: string;
|
|
5
|
-
name: unknown;
|
|
6
|
-
description: unknown;
|
|
7
|
-
};
|
|
8
|
-
type User = {
|
|
9
|
-
id: string;
|
|
10
|
-
tenantId: string;
|
|
11
|
-
fullName: string;
|
|
12
|
-
email: string | null;
|
|
13
|
-
phone: string | null;
|
|
14
|
-
handle: string;
|
|
15
|
-
image: string | null;
|
|
16
|
-
emailVerified: boolean;
|
|
17
|
-
phoneVerified: boolean;
|
|
18
|
-
lastSignInAt: string | null;
|
|
19
|
-
userRoles?: UserRole[];
|
|
20
|
-
};
|
|
21
|
-
type Session = {
|
|
22
|
-
id: string;
|
|
23
|
-
tenantId: string;
|
|
24
|
-
userId: string;
|
|
25
|
-
expiresAt: string;
|
|
26
|
-
createdAt: string;
|
|
27
|
-
updatedAt: string;
|
|
28
|
-
userAgent: string | null;
|
|
29
|
-
ip: string | null;
|
|
30
|
-
};
|
|
31
|
-
type ResendConfig = {
|
|
32
|
-
apiKey: string;
|
|
33
|
-
from: string;
|
|
34
|
-
baseUrl?: string;
|
|
35
|
-
verificationSubject?: string;
|
|
36
|
-
resetPasswordSubject?: string;
|
|
37
|
-
};
|
|
38
|
-
type SMSConfig = {
|
|
39
|
-
baseUrl: string;
|
|
40
|
-
identifierId: string;
|
|
41
|
-
senderName: string;
|
|
42
|
-
apiKey: string;
|
|
43
|
-
templateVerification?: string;
|
|
44
|
-
templateLogin?: string;
|
|
45
|
-
};
|
|
46
|
-
type EmailConfig = {
|
|
47
|
-
enabled: boolean;
|
|
48
|
-
verificationRequired: boolean;
|
|
49
|
-
verificationExpiresIn: string;
|
|
50
|
-
resetPasswordExpiresIn: string;
|
|
51
|
-
resend: ResendConfig;
|
|
52
|
-
};
|
|
53
|
-
type PhoneConfig = {
|
|
54
|
-
enabled: boolean;
|
|
55
|
-
verificationRequired: boolean;
|
|
56
|
-
otpLength: number;
|
|
57
|
-
otpExpiresIn: string;
|
|
58
|
-
maxAttempts: number;
|
|
59
|
-
smsConfig: SMSConfig;
|
|
60
|
-
};
|
|
61
|
-
type SessionConfig = {
|
|
62
|
-
expiresIn: string;
|
|
63
|
-
maxPerUser?: number;
|
|
64
|
-
};
|
|
65
|
-
type AuthConfig = {
|
|
66
|
-
connectionString: string;
|
|
67
|
-
secret: string;
|
|
68
|
-
basePath?: string;
|
|
69
|
-
enableTenant?: boolean;
|
|
70
|
-
tenantId?: string;
|
|
71
|
-
session: SessionConfig;
|
|
72
|
-
email: EmailConfig;
|
|
73
|
-
phone: PhoneConfig;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export type { AuthConfig as A, Session as S, User as U };
|
package/dist/lib/jwt.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
type TokenPayload = {
|
|
2
|
-
userId: string;
|
|
3
|
-
sessionId: string;
|
|
4
|
-
tenantId: string;
|
|
5
|
-
type: 'access';
|
|
6
|
-
};
|
|
7
|
-
declare const signAccessToken: (payload: TokenPayload, secret: string, ttlMinutes?: number) => {
|
|
8
|
-
token: string;
|
|
9
|
-
expiresAt: string;
|
|
10
|
-
};
|
|
11
|
-
declare const verifyAccessToken: (token: string, secret: string) => (TokenPayload & {
|
|
12
|
-
exp: number;
|
|
13
|
-
}) | null;
|
|
14
|
-
|
|
15
|
-
export { type TokenPayload, signAccessToken, verifyAccessToken };
|
package/dist/lib/jwt.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// src/lib/jwt.ts
|
|
2
|
-
import { dayjs } from "@mesob/common";
|
|
3
|
-
import jwt from "jsonwebtoken";
|
|
4
|
-
var signAccessToken = (payload, secret, ttlMinutes = 15) => {
|
|
5
|
-
const exp = dayjs().add(ttlMinutes, "minute").unix();
|
|
6
|
-
const token = jwt.sign({ ...payload, exp }, secret, {
|
|
7
|
-
algorithm: "HS256"
|
|
8
|
-
});
|
|
9
|
-
return {
|
|
10
|
-
token,
|
|
11
|
-
expiresAt: dayjs.unix(exp).toISOString()
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
var verifyAccessToken = (token, secret) => {
|
|
15
|
-
try {
|
|
16
|
-
return jwt.verify(token, secret);
|
|
17
|
-
} catch (_err) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
export {
|
|
22
|
-
signAccessToken,
|
|
23
|
-
verifyAccessToken
|
|
24
|
-
};
|
|
25
|
-
//# sourceMappingURL=jwt.js.map
|
package/dist/lib/jwt.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/jwt.ts"],"sourcesContent":["import { dayjs } from '@mesob/common';\nimport jwt from 'jsonwebtoken';\n\nexport type TokenPayload = {\n userId: string;\n sessionId: string;\n tenantId: string;\n type: 'access';\n};\n\nexport const signAccessToken = (\n payload: TokenPayload,\n secret: string,\n ttlMinutes = 15,\n) => {\n const exp = dayjs().add(ttlMinutes, 'minute').unix();\n const token = jwt.sign({ ...payload, exp }, secret, {\n algorithm: 'HS256',\n });\n return {\n token,\n expiresAt: dayjs.unix(exp).toISOString(),\n };\n};\n\nexport const verifyAccessToken = (token: string, secret: string) => {\n try {\n return jwt.verify(token, secret) as TokenPayload & { exp: number };\n } catch (_err) {\n return null;\n }\n};\n"],"mappings":";AAAA,SAAS,aAAa;AACtB,OAAO,SAAS;AAST,IAAM,kBAAkB,CAC7B,SACA,QACA,aAAa,OACV;AACH,QAAM,MAAM,MAAM,EAAE,IAAI,YAAY,QAAQ,EAAE,KAAK;AACnD,QAAM,QAAQ,IAAI,KAAK,EAAE,GAAG,SAAS,IAAI,GAAG,QAAQ;AAAA,IAClD,WAAW;AAAA,EACb,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA,WAAW,MAAM,KAAK,GAAG,EAAE,YAAY;AAAA,EACzC;AACF;AAEO,IAAM,oBAAoB,CAAC,OAAe,WAAmB;AAClE,MAAI;AACF,WAAO,IAAI,OAAO,OAAO,MAAM;AAAA,EACjC,SAAS,MAAM;AACb,WAAO;AAAA,EACT;AACF;","names":[]}
|