@parsrun/auth 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 +133 -0
- package/dist/adapters/hono.d.ts +9 -0
- package/dist/adapters/hono.js +6 -0
- package/dist/adapters/hono.js.map +1 -0
- package/dist/adapters/index.d.ts +9 -0
- package/dist/adapters/index.js +7 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/authorization-By1Xp8Za.d.ts +213 -0
- package/dist/base-BKyR8rcE.d.ts +646 -0
- package/dist/chunk-42MGHABB.js +263 -0
- package/dist/chunk-42MGHABB.js.map +1 -0
- package/dist/chunk-7GOBAL4G.js +3 -0
- package/dist/chunk-7GOBAL4G.js.map +1 -0
- package/dist/chunk-G5I3T73A.js +152 -0
- package/dist/chunk-G5I3T73A.js.map +1 -0
- package/dist/chunk-IB4WUQDZ.js +410 -0
- package/dist/chunk-IB4WUQDZ.js.map +1 -0
- package/dist/chunk-MOG4Y6I7.js +415 -0
- package/dist/chunk-MOG4Y6I7.js.map +1 -0
- package/dist/chunk-NK4TJV2W.js +295 -0
- package/dist/chunk-NK4TJV2W.js.map +1 -0
- package/dist/chunk-RHNVRCF3.js +838 -0
- package/dist/chunk-RHNVRCF3.js.map +1 -0
- package/dist/chunk-YTCPXJR5.js +570 -0
- package/dist/chunk-YTCPXJR5.js.map +1 -0
- package/dist/cloudflare-kv-L64CZKDK.js +105 -0
- package/dist/cloudflare-kv-L64CZKDK.js.map +1 -0
- package/dist/deno-kv-F55HKKP6.js +111 -0
- package/dist/deno-kv-F55HKKP6.js.map +1 -0
- package/dist/index-C3kz9XqE.d.ts +226 -0
- package/dist/index-DOGcetyD.d.ts +1041 -0
- package/dist/index.d.ts +1579 -0
- package/dist/index.js +4294 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt-manager-CH8H0kmm.d.ts +182 -0
- package/dist/providers/index.d.ts +90 -0
- package/dist/providers/index.js +3 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/otp/index.d.ts +3 -0
- package/dist/providers/otp/index.js +4 -0
- package/dist/providers/otp/index.js.map +1 -0
- package/dist/redis-5TIS6XCA.js +121 -0
- package/dist/redis-5TIS6XCA.js.map +1 -0
- package/dist/security/index.d.ts +301 -0
- package/dist/security/index.js +5 -0
- package/dist/security/index.js.map +1 -0
- package/dist/session/index.d.ts +117 -0
- package/dist/session/index.js +4 -0
- package/dist/session/index.js.map +1 -0
- package/dist/storage/index.d.ts +97 -0
- package/dist/storage/index.js +3 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/types-DSjafxJ4.d.ts +193 -0
- package/package.json +102 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// src/storage/cloudflare-kv.ts
|
|
2
|
+
var CloudflareKVStorage = class {
|
|
3
|
+
kv;
|
|
4
|
+
prefix;
|
|
5
|
+
constructor(binding, prefix) {
|
|
6
|
+
this.kv = binding;
|
|
7
|
+
this.prefix = prefix ?? "";
|
|
8
|
+
}
|
|
9
|
+
getKey(key) {
|
|
10
|
+
return this.prefix ? `${this.prefix}:${key}` : key;
|
|
11
|
+
}
|
|
12
|
+
async get(key) {
|
|
13
|
+
const fullKey = this.getKey(key);
|
|
14
|
+
const value = await this.kv.get(fullKey, { type: "json" });
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
async set(key, value, ttl) {
|
|
18
|
+
const fullKey = this.getKey(key);
|
|
19
|
+
const serialized = JSON.stringify(value);
|
|
20
|
+
const options = {};
|
|
21
|
+
if (ttl) {
|
|
22
|
+
options.expirationTtl = Math.max(60, ttl);
|
|
23
|
+
}
|
|
24
|
+
await this.kv.put(fullKey, serialized, options);
|
|
25
|
+
}
|
|
26
|
+
async delete(key) {
|
|
27
|
+
const fullKey = this.getKey(key);
|
|
28
|
+
await this.kv.delete(fullKey);
|
|
29
|
+
}
|
|
30
|
+
async has(key) {
|
|
31
|
+
const value = await this.get(key);
|
|
32
|
+
return value !== null;
|
|
33
|
+
}
|
|
34
|
+
async getMany(keys) {
|
|
35
|
+
return Promise.all(keys.map((key) => this.get(key)));
|
|
36
|
+
}
|
|
37
|
+
async setMany(entries) {
|
|
38
|
+
await Promise.all(
|
|
39
|
+
entries.map(([key, value, ttl]) => this.set(key, value, ttl))
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
async deleteMany(keys) {
|
|
43
|
+
await Promise.all(keys.map((key) => this.delete(key)));
|
|
44
|
+
}
|
|
45
|
+
async keys(pattern) {
|
|
46
|
+
const listOptions = {
|
|
47
|
+
limit: 1e3
|
|
48
|
+
};
|
|
49
|
+
if (pattern) {
|
|
50
|
+
const prefixPattern = pattern.replace(/\*.*$/, "");
|
|
51
|
+
listOptions.prefix = this.prefix ? `${this.prefix}:${prefixPattern}` : prefixPattern;
|
|
52
|
+
} else if (this.prefix) {
|
|
53
|
+
listOptions.prefix = `${this.prefix}:`;
|
|
54
|
+
}
|
|
55
|
+
const result = await this.kv.list(listOptions);
|
|
56
|
+
const prefixLength = this.prefix ? this.prefix.length + 1 : 0;
|
|
57
|
+
const keys = [];
|
|
58
|
+
for (const key of result.keys) {
|
|
59
|
+
const unprefixedKey = prefixLength ? key.name.slice(prefixLength) : key.name;
|
|
60
|
+
if (pattern && pattern.includes("*")) {
|
|
61
|
+
const regex = new RegExp(
|
|
62
|
+
"^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$"
|
|
63
|
+
);
|
|
64
|
+
if (regex.test(unprefixedKey)) {
|
|
65
|
+
keys.push(unprefixedKey);
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
keys.push(unprefixedKey);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return keys;
|
|
72
|
+
}
|
|
73
|
+
async clear() {
|
|
74
|
+
if (!this.prefix) {
|
|
75
|
+
console.warn(
|
|
76
|
+
"[Pars Auth] Cannot clear Cloudflare KV storage without prefix. This would delete all keys."
|
|
77
|
+
);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
let cursor;
|
|
81
|
+
do {
|
|
82
|
+
const result = await this.kv.list({
|
|
83
|
+
prefix: `${this.prefix}:`,
|
|
84
|
+
limit: 1e3,
|
|
85
|
+
cursor
|
|
86
|
+
});
|
|
87
|
+
await Promise.all(result.keys.map((key) => this.kv.delete(key.name)));
|
|
88
|
+
cursor = result.list_complete ? void 0 : result.cursor;
|
|
89
|
+
} while (cursor);
|
|
90
|
+
}
|
|
91
|
+
async close() {
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
function createCloudflareKVStorage(config) {
|
|
95
|
+
if (!config.binding) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
"[Pars Auth] Cloudflare KV storage requires a KV namespace binding"
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return new CloudflareKVStorage(config.binding, config.prefix);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export { CloudflareKVStorage, createCloudflareKVStorage };
|
|
104
|
+
//# sourceMappingURL=cloudflare-kv-L64CZKDK.js.map
|
|
105
|
+
//# sourceMappingURL=cloudflare-kv-L64CZKDK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/storage/cloudflare-kv.ts"],"names":[],"mappings":"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","file":"cloudflare-kv-L64CZKDK.js","sourcesContent":["/**\n * Cloudflare KV Storage adapter\n * For use in Cloudflare Workers\n */\n\nimport type { KVStorage, CloudflareKVConfig, KVNamespace } from './types.js';\n\n/**\n * Cloudflare KV storage adapter\n */\nexport class CloudflareKVStorage implements KVStorage {\n private kv: KVNamespace;\n private readonly prefix: string;\n\n constructor(binding: KVNamespace, prefix?: string) {\n this.kv = binding;\n this.prefix = prefix ?? '';\n }\n\n private getKey(key: string): string {\n return this.prefix ? `${this.prefix}:${key}` : key;\n }\n\n async get<T = unknown>(key: string): Promise<T | null> {\n const fullKey = this.getKey(key);\n const value = await this.kv.get(fullKey, { type: 'json' });\n return value as T | null;\n }\n\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n const fullKey = this.getKey(key);\n const serialized = JSON.stringify(value);\n\n const options: { expirationTtl?: number } = {};\n if (ttl) {\n // Cloudflare KV minimum TTL is 60 seconds\n options.expirationTtl = Math.max(60, ttl);\n }\n\n await this.kv.put(fullKey, serialized, options);\n }\n\n async delete(key: string): Promise<void> {\n const fullKey = this.getKey(key);\n await this.kv.delete(fullKey);\n }\n\n async has(key: string): Promise<boolean> {\n const value = await this.get(key);\n return value !== null;\n }\n\n async getMany<T = unknown>(keys: string[]): Promise<(T | null)[]> {\n // Cloudflare KV doesn't have native batch get, use Promise.all\n return Promise.all(keys.map((key) => this.get<T>(key)));\n }\n\n async setMany<T = unknown>(\n entries: Array<[key: string, value: T, ttl?: number]>\n ): Promise<void> {\n await Promise.all(\n entries.map(([key, value, ttl]) => this.set(key, value, ttl))\n );\n }\n\n async deleteMany(keys: string[]): Promise<void> {\n await Promise.all(keys.map((key) => this.delete(key)));\n }\n\n async keys(pattern?: string): Promise<string[]> {\n const listOptions: { prefix?: string; limit?: number } = {\n limit: 1000,\n };\n\n if (pattern) {\n // Simple prefix-based filtering\n // KV list only supports prefix, not glob patterns\n const prefixPattern = pattern.replace(/\\*.*$/, '');\n listOptions.prefix = this.prefix\n ? `${this.prefix}:${prefixPattern}`\n : prefixPattern;\n } else if (this.prefix) {\n listOptions.prefix = `${this.prefix}:`;\n }\n\n const result = await this.kv.list(listOptions);\n const prefixLength = this.prefix ? this.prefix.length + 1 : 0;\n\n const keys: string[] = [];\n for (const key of result.keys) {\n const unprefixedKey = prefixLength ? key.name.slice(prefixLength) : key.name;\n\n // If pattern has glob, filter manually\n if (pattern && pattern.includes('*')) {\n const regex = new RegExp(\n '^' + pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$'\n );\n if (regex.test(unprefixedKey)) {\n keys.push(unprefixedKey);\n }\n } else {\n keys.push(unprefixedKey);\n }\n }\n\n return keys;\n }\n\n async clear(): Promise<void> {\n if (!this.prefix) {\n console.warn(\n '[Pars Auth] Cannot clear Cloudflare KV storage without prefix. This would delete all keys.'\n );\n return;\n }\n\n // List and delete all keys with prefix\n let cursor: string | undefined;\n do {\n const result = await this.kv.list({\n prefix: `${this.prefix}:`,\n limit: 1000,\n cursor,\n });\n\n await Promise.all(result.keys.map((key) => this.kv.delete(key.name)));\n\n cursor = result.list_complete ? undefined : result.cursor;\n } while (cursor);\n }\n\n async close(): Promise<void> {\n // No-op for Cloudflare KV\n }\n}\n\n/**\n * Create Cloudflare KV storage adapter\n *\n * @example\n * ```ts\n * // In Cloudflare Worker\n * export default {\n * async fetch(request: Request, env: Env) {\n * const storage = createCloudflareKVStorage({\n * binding: env.AUTH_KV,\n * prefix: 'auth'\n * });\n *\n * // Use storage...\n * }\n * }\n * ```\n */\nexport function createCloudflareKVStorage(\n config: CloudflareKVConfig\n): KVStorage {\n if (!config.binding) {\n throw new Error(\n '[Pars Auth] Cloudflare KV storage requires a KV namespace binding'\n );\n }\n\n return new CloudflareKVStorage(config.binding, config.prefix);\n}\n"]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// src/storage/deno-kv.ts
|
|
2
|
+
var DenoKVStorage = class {
|
|
3
|
+
kv = null;
|
|
4
|
+
path;
|
|
5
|
+
prefix;
|
|
6
|
+
initPromise = null;
|
|
7
|
+
constructor(path, prefix) {
|
|
8
|
+
this.path = path;
|
|
9
|
+
this.prefix = prefix ?? "pars";
|
|
10
|
+
}
|
|
11
|
+
async ensureInit() {
|
|
12
|
+
if (this.kv) return;
|
|
13
|
+
if (this.initPromise) {
|
|
14
|
+
await this.initPromise;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
this.initPromise = this.init();
|
|
18
|
+
await this.initPromise;
|
|
19
|
+
}
|
|
20
|
+
async init() {
|
|
21
|
+
if (typeof Deno === "undefined" || !Deno.openKv) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
"[Pars Auth] Deno KV storage is only available in Deno runtime"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
this.kv = await Deno.openKv(this.path);
|
|
27
|
+
}
|
|
28
|
+
getKey(key) {
|
|
29
|
+
return [this.prefix, key];
|
|
30
|
+
}
|
|
31
|
+
async get(key) {
|
|
32
|
+
await this.ensureInit();
|
|
33
|
+
const kvKey = this.getKey(key);
|
|
34
|
+
const result = await this.kv.get(kvKey);
|
|
35
|
+
return result.value;
|
|
36
|
+
}
|
|
37
|
+
async set(key, value, ttl) {
|
|
38
|
+
await this.ensureInit();
|
|
39
|
+
const kvKey = this.getKey(key);
|
|
40
|
+
const options = {};
|
|
41
|
+
if (ttl) {
|
|
42
|
+
options.expireIn = ttl * 1e3;
|
|
43
|
+
}
|
|
44
|
+
await this.kv.set(kvKey, value, options);
|
|
45
|
+
}
|
|
46
|
+
async delete(key) {
|
|
47
|
+
await this.ensureInit();
|
|
48
|
+
const kvKey = this.getKey(key);
|
|
49
|
+
await this.kv.delete(kvKey);
|
|
50
|
+
}
|
|
51
|
+
async has(key) {
|
|
52
|
+
const value = await this.get(key);
|
|
53
|
+
return value !== null;
|
|
54
|
+
}
|
|
55
|
+
async getMany(keys) {
|
|
56
|
+
return Promise.all(keys.map((key) => this.get(key)));
|
|
57
|
+
}
|
|
58
|
+
async setMany(entries) {
|
|
59
|
+
await Promise.all(
|
|
60
|
+
entries.map(([key, value, ttl]) => this.set(key, value, ttl))
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
async deleteMany(keys) {
|
|
64
|
+
await Promise.all(keys.map((key) => this.delete(key)));
|
|
65
|
+
}
|
|
66
|
+
async keys(pattern) {
|
|
67
|
+
await this.ensureInit();
|
|
68
|
+
const keys = [];
|
|
69
|
+
const prefix = [this.prefix];
|
|
70
|
+
for await (const entry of this.kv.list({ prefix })) {
|
|
71
|
+
const keyParts = entry.key;
|
|
72
|
+
if (keyParts.length >= 2) {
|
|
73
|
+
const keyString = String(keyParts[1]);
|
|
74
|
+
if (pattern) {
|
|
75
|
+
const regex = new RegExp(
|
|
76
|
+
"^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$"
|
|
77
|
+
);
|
|
78
|
+
if (regex.test(keyString)) {
|
|
79
|
+
keys.push(keyString);
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
keys.push(keyString);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return keys;
|
|
87
|
+
}
|
|
88
|
+
async clear() {
|
|
89
|
+
await this.ensureInit();
|
|
90
|
+
const prefix = [this.prefix];
|
|
91
|
+
const keysToDelete = [];
|
|
92
|
+
for await (const entry of this.kv.list({ prefix })) {
|
|
93
|
+
keysToDelete.push(entry.key);
|
|
94
|
+
}
|
|
95
|
+
await Promise.all(keysToDelete.map((key) => this.kv.delete(key)));
|
|
96
|
+
}
|
|
97
|
+
async close() {
|
|
98
|
+
if (this.kv) {
|
|
99
|
+
this.kv.close();
|
|
100
|
+
this.kv = null;
|
|
101
|
+
this.initPromise = null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
function createDenoKVStorage(config) {
|
|
106
|
+
return new DenoKVStorage(config?.path, config?.prefix);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export { DenoKVStorage, createDenoKVStorage };
|
|
110
|
+
//# sourceMappingURL=deno-kv-F55HKKP6.js.map
|
|
111
|
+
//# sourceMappingURL=deno-kv-F55HKKP6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/storage/deno-kv.ts"],"names":[],"mappings":"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","file":"deno-kv-F55HKKP6.js","sourcesContent":["/**\n * Deno KV Storage adapter\n * For use in Deno runtime\n */\n\nimport type { KVStorage, DenoKVConfig } from './types.js';\n\n/**\n * Deno KV instance type\n */\ninterface DenoKvInstance {\n get<T = unknown>(key: unknown[]): Promise<{ value: T | null; versionstamp: string | null }>;\n set(key: unknown[], value: unknown, options?: { expireIn?: number }): Promise<{ ok: boolean; versionstamp: string }>;\n delete(key: unknown[]): Promise<void>;\n list<T = unknown>(selector: { prefix: unknown[] }, options?: { limit?: number }): AsyncIterable<{ key: unknown[]; value: T; versionstamp: string }>;\n close(): void;\n}\n\n/**\n * Deno KV storage adapter\n */\nexport class DenoKVStorage implements KVStorage {\n private kv: DenoKvInstance | null = null;\n private readonly path?: string;\n private readonly prefix: string;\n private initPromise: Promise<void> | null = null;\n\n constructor(path?: string, prefix?: string) {\n this.path = path;\n this.prefix = prefix ?? 'pars';\n }\n\n private async ensureInit(): Promise<void> {\n if (this.kv) return;\n\n if (this.initPromise) {\n await this.initPromise;\n return;\n }\n\n this.initPromise = this.init();\n await this.initPromise;\n }\n\n private async init(): Promise<void> {\n // @ts-expect-error - Deno specific global\n if (typeof Deno === 'undefined' || !Deno.openKv) {\n throw new Error(\n '[Pars Auth] Deno KV storage is only available in Deno runtime'\n );\n }\n\n // @ts-expect-error - Deno specific API\n this.kv = await Deno.openKv(this.path) as DenoKvInstance;\n }\n\n private getKey(key: string): unknown[] {\n return [this.prefix, key];\n }\n\n async get<T = unknown>(key: string): Promise<T | null> {\n await this.ensureInit();\n const kvKey = this.getKey(key);\n const result = await this.kv!.get<T>(kvKey);\n return result.value;\n }\n\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n await this.ensureInit();\n const kvKey = this.getKey(key);\n\n const options: { expireIn?: number } = {};\n if (ttl) {\n // Deno KV uses milliseconds for expireIn\n options.expireIn = ttl * 1000;\n }\n\n await this.kv!.set(kvKey, value, options);\n }\n\n async delete(key: string): Promise<void> {\n await this.ensureInit();\n const kvKey = this.getKey(key);\n await this.kv!.delete(kvKey);\n }\n\n async has(key: string): Promise<boolean> {\n const value = await this.get(key);\n return value !== null;\n }\n\n async getMany<T = unknown>(keys: string[]): Promise<(T | null)[]> {\n return Promise.all(keys.map((key) => this.get<T>(key)));\n }\n\n async setMany<T = unknown>(\n entries: Array<[key: string, value: T, ttl?: number]>\n ): Promise<void> {\n await Promise.all(\n entries.map(([key, value, ttl]) => this.set(key, value, ttl))\n );\n }\n\n async deleteMany(keys: string[]): Promise<void> {\n await Promise.all(keys.map((key) => this.delete(key)));\n }\n\n async keys(pattern?: string): Promise<string[]> {\n await this.ensureInit();\n\n const keys: string[] = [];\n const prefix = [this.prefix];\n\n for await (const entry of this.kv!.list({ prefix })) {\n // Extract key string from Deno KV key array\n const keyParts = entry.key as unknown[];\n if (keyParts.length >= 2) {\n const keyString = String(keyParts[1]);\n\n // Filter by pattern if provided\n if (pattern) {\n const regex = new RegExp(\n '^' + pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$'\n );\n if (regex.test(keyString)) {\n keys.push(keyString);\n }\n } else {\n keys.push(keyString);\n }\n }\n }\n\n return keys;\n }\n\n async clear(): Promise<void> {\n await this.ensureInit();\n\n const prefix = [this.prefix];\n const keysToDelete: unknown[][] = [];\n\n for await (const entry of this.kv!.list({ prefix })) {\n keysToDelete.push(entry.key as unknown[]);\n }\n\n await Promise.all(keysToDelete.map((key) => this.kv!.delete(key)));\n }\n\n async close(): Promise<void> {\n if (this.kv) {\n this.kv.close();\n this.kv = null;\n this.initPromise = null;\n }\n }\n}\n\n/**\n * Create Deno KV storage adapter\n *\n * @example\n * ```ts\n * // Default (uses Deno.openKv())\n * const storage = await createDenoKVStorage();\n *\n * // With custom path\n * const storage = await createDenoKVStorage({\n * path: './data/auth.db',\n * prefix: 'auth'\n * });\n *\n * // For Deno Deploy (path is ignored)\n * const storage = await createDenoKVStorage({ prefix: 'auth' });\n * ```\n */\nexport function createDenoKVStorage(config?: DenoKVConfig): KVStorage {\n return new DenoKVStorage(config?.path, config?.prefix);\n}\n"]}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { K as KVStorage } from './types-DSjafxJ4.js';
|
|
2
|
+
import { A as AuthProvider, g as OtpConfig, V as VerifyInput, d as VerifyResult, b as AuthInput, c as AuthResult, a as ProviderInfo } from './base-BKyR8rcE.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* OTP Manager
|
|
6
|
+
* Handles OTP generation, storage, and verification
|
|
7
|
+
* Uses KVStorage interface for multi-runtime support
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* OTP configuration
|
|
12
|
+
*/
|
|
13
|
+
interface OTPConfig {
|
|
14
|
+
/** OTP code length (default: 6) */
|
|
15
|
+
length?: number;
|
|
16
|
+
/** OTP expiry in seconds (default: 600 = 10 minutes) */
|
|
17
|
+
expiresIn?: number;
|
|
18
|
+
/** Maximum verification attempts (default: 3) */
|
|
19
|
+
maxAttempts?: number;
|
|
20
|
+
/** Rate limit: max requests per window (default: 5) */
|
|
21
|
+
rateLimit?: number;
|
|
22
|
+
/** Rate limit window in seconds (default: 900 = 15 minutes) */
|
|
23
|
+
rateLimitWindow?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* OTP record stored in KV
|
|
27
|
+
*/
|
|
28
|
+
interface OTPRecord {
|
|
29
|
+
/** OTP code */
|
|
30
|
+
code: string;
|
|
31
|
+
/** Target identifier (email/phone) */
|
|
32
|
+
identifier: string;
|
|
33
|
+
/** OTP type */
|
|
34
|
+
type: 'email' | 'sms';
|
|
35
|
+
/** Expiry timestamp (ISO string) */
|
|
36
|
+
expiresAt: string;
|
|
37
|
+
/** Failed verification attempts */
|
|
38
|
+
attempts: number;
|
|
39
|
+
/** Maximum allowed attempts */
|
|
40
|
+
maxAttempts: number;
|
|
41
|
+
/** Creation timestamp (ISO string) */
|
|
42
|
+
createdAt: string;
|
|
43
|
+
/** Tenant ID (for multi-tenant) */
|
|
44
|
+
tenantId?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* OTP storage result
|
|
48
|
+
*/
|
|
49
|
+
interface StoreOTPResult {
|
|
50
|
+
success: boolean;
|
|
51
|
+
code?: string;
|
|
52
|
+
expiresAt?: Date;
|
|
53
|
+
error?: string;
|
|
54
|
+
remainingRequests?: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* OTP verification result
|
|
58
|
+
*/
|
|
59
|
+
interface VerifyOTPResult {
|
|
60
|
+
success: boolean;
|
|
61
|
+
message: string;
|
|
62
|
+
attemptsLeft?: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Rate limit check result
|
|
66
|
+
*/
|
|
67
|
+
interface RateLimitCheck {
|
|
68
|
+
allowed: boolean;
|
|
69
|
+
remainingRequests: number;
|
|
70
|
+
resetAt: Date;
|
|
71
|
+
message?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* OTP Manager class
|
|
75
|
+
*/
|
|
76
|
+
declare class OTPManager {
|
|
77
|
+
private storage;
|
|
78
|
+
private config;
|
|
79
|
+
constructor(storage: KVStorage, config?: OTPConfig);
|
|
80
|
+
/**
|
|
81
|
+
* Generate OTP code
|
|
82
|
+
*/
|
|
83
|
+
generateCode(length?: number): string;
|
|
84
|
+
/**
|
|
85
|
+
* Get storage key for OTP
|
|
86
|
+
*/
|
|
87
|
+
private getOTPKey;
|
|
88
|
+
/**
|
|
89
|
+
* Get storage key for rate limiting
|
|
90
|
+
*/
|
|
91
|
+
private getRateLimitKey;
|
|
92
|
+
/**
|
|
93
|
+
* Check rate limit for OTP requests
|
|
94
|
+
*/
|
|
95
|
+
checkRateLimit(identifier: string, type: 'email' | 'sms'): Promise<RateLimitCheck>;
|
|
96
|
+
/**
|
|
97
|
+
* Increment rate limit counter
|
|
98
|
+
*/
|
|
99
|
+
private incrementRateLimit;
|
|
100
|
+
/**
|
|
101
|
+
* Store OTP for verification
|
|
102
|
+
*/
|
|
103
|
+
store(identifier: string, type: 'email' | 'sms', options?: {
|
|
104
|
+
tenantId?: string;
|
|
105
|
+
testMode?: boolean;
|
|
106
|
+
}): Promise<StoreOTPResult>;
|
|
107
|
+
/**
|
|
108
|
+
* Verify OTP code
|
|
109
|
+
*/
|
|
110
|
+
verify(identifier: string, type: 'email' | 'sms', code: string, options?: {
|
|
111
|
+
testUser?: boolean;
|
|
112
|
+
}): Promise<VerifyOTPResult>;
|
|
113
|
+
/**
|
|
114
|
+
* Check if valid OTP exists
|
|
115
|
+
*/
|
|
116
|
+
hasValidOTP(identifier: string, type: 'email' | 'sms'): Promise<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* Get OTP info (for debugging)
|
|
119
|
+
*/
|
|
120
|
+
getInfo(identifier: string, type: 'email' | 'sms'): Promise<{
|
|
121
|
+
exists: boolean;
|
|
122
|
+
expiresAt?: Date;
|
|
123
|
+
attempts?: number;
|
|
124
|
+
attemptsLeft?: number;
|
|
125
|
+
}>;
|
|
126
|
+
/**
|
|
127
|
+
* Delete OTP (for testing/cleanup)
|
|
128
|
+
*/
|
|
129
|
+
delete(identifier: string, type: 'email' | 'sms'): Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Get rate limit info
|
|
132
|
+
*/
|
|
133
|
+
getRateLimitInfo(identifier: string, type: 'email' | 'sms'): Promise<{
|
|
134
|
+
requestsUsed: number;
|
|
135
|
+
remainingRequests: number;
|
|
136
|
+
resetAt: Date;
|
|
137
|
+
}>;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Create OTP manager instance
|
|
141
|
+
*/
|
|
142
|
+
declare function createOTPManager(storage: KVStorage, config?: OTPConfig): OTPManager;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* OTP Authentication Provider
|
|
146
|
+
* Email and SMS one-time password authentication
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* OTP request input
|
|
151
|
+
*/
|
|
152
|
+
interface RequestOTPInput {
|
|
153
|
+
/** Email or phone number */
|
|
154
|
+
identifier: string;
|
|
155
|
+
/** OTP type */
|
|
156
|
+
type: 'email' | 'sms';
|
|
157
|
+
/** Tenant ID (for multi-tenant) */
|
|
158
|
+
tenantId?: string;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* OTP request result
|
|
162
|
+
*/
|
|
163
|
+
interface RequestOTPResult {
|
|
164
|
+
success: boolean;
|
|
165
|
+
expiresAt?: Date;
|
|
166
|
+
error?: string;
|
|
167
|
+
remainingRequests?: number;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* OTP Provider
|
|
171
|
+
*/
|
|
172
|
+
declare class OTPProvider implements AuthProvider {
|
|
173
|
+
readonly name = "otp";
|
|
174
|
+
readonly type: "otp";
|
|
175
|
+
private otpManager;
|
|
176
|
+
private config;
|
|
177
|
+
private emailSend?;
|
|
178
|
+
private smsSend?;
|
|
179
|
+
private _enabled;
|
|
180
|
+
constructor(storage: KVStorage, config: OtpConfig);
|
|
181
|
+
get enabled(): boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Request OTP (send to email or SMS)
|
|
184
|
+
*/
|
|
185
|
+
requestOTP(input: RequestOTPInput): Promise<RequestOTPResult>;
|
|
186
|
+
/**
|
|
187
|
+
* Verify OTP (implements AuthProvider.verify)
|
|
188
|
+
*/
|
|
189
|
+
verify(input: VerifyInput): Promise<VerifyResult>;
|
|
190
|
+
/**
|
|
191
|
+
* Authenticate with OTP (implements AuthProvider.authenticate)
|
|
192
|
+
* This verifies OTP but doesn't create session - that's done by auth engine
|
|
193
|
+
*/
|
|
194
|
+
authenticate(input: AuthInput): Promise<AuthResult>;
|
|
195
|
+
/**
|
|
196
|
+
* Get provider info
|
|
197
|
+
*/
|
|
198
|
+
getInfo(): ProviderInfo;
|
|
199
|
+
/**
|
|
200
|
+
* Check if valid OTP exists
|
|
201
|
+
*/
|
|
202
|
+
hasValidOTP(identifier: string, type: 'email' | 'sms'): Promise<boolean>;
|
|
203
|
+
/**
|
|
204
|
+
* Get OTP info (for debugging)
|
|
205
|
+
*/
|
|
206
|
+
getOTPInfo(identifier: string, type: 'email' | 'sms'): Promise<{
|
|
207
|
+
exists: boolean;
|
|
208
|
+
expiresAt?: Date;
|
|
209
|
+
attempts?: number;
|
|
210
|
+
attemptsLeft?: number;
|
|
211
|
+
}>;
|
|
212
|
+
/**
|
|
213
|
+
* Get rate limit info
|
|
214
|
+
*/
|
|
215
|
+
getRateLimitInfo(identifier: string, type: 'email' | 'sms'): Promise<{
|
|
216
|
+
requestsUsed: number;
|
|
217
|
+
remainingRequests: number;
|
|
218
|
+
resetAt: Date;
|
|
219
|
+
}>;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Create OTP provider
|
|
223
|
+
*/
|
|
224
|
+
declare function createOTPProvider(storage: KVStorage, config: OtpConfig): OTPProvider;
|
|
225
|
+
|
|
226
|
+
export { OTPProvider as O, type RequestOTPInput as R, type StoreOTPResult as S, type VerifyOTPResult as V, OTPManager as a, createOTPManager as b, createOTPProvider as c, type RequestOTPResult as d, type OTPConfig as e, type OTPRecord as f, type RateLimitCheck as g };
|