@minimoth/sdk-node 0.2.2 → 0.3.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 +49 -17
- package/dist/index.cjs +69 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.js +69 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,49 +17,50 @@ Requires Node.js 18+.
|
|
|
17
17
|
```ts
|
|
18
18
|
import { MiniMoth } from '@minimoth/sdk-node'
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const mm = new MiniMoth({
|
|
21
21
|
apiKey: 'mm_live_...', // from app.minimoth.dev
|
|
22
22
|
})
|
|
23
23
|
|
|
24
24
|
// Send OTP
|
|
25
|
-
const { otpId } = await
|
|
25
|
+
const { otpId } = await mm.otp.send({ phone: '919876543210' })
|
|
26
26
|
|
|
27
27
|
// Verify OTP
|
|
28
|
-
const result = await
|
|
28
|
+
const result = await mm.otp.verify({ phone: '919876543210', otp: '123456' })
|
|
29
29
|
if (result.valid) {
|
|
30
30
|
// Store tokens — SDK auto-stores in memory by default
|
|
31
31
|
console.log(result.accessToken, result.refreshToken, result.sessionId)
|
|
32
|
+
// result.identityId is set once identity lookups are enabled for the project — see Identity below
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
// Validate on every request
|
|
35
|
-
const session = await
|
|
36
|
-
// session.projectId, session.sessionId, session.expiresAt
|
|
36
|
+
const session = await mm.session.validate(req.headers['x-access-token'])
|
|
37
|
+
// session.projectId, session.sessionId, session.expiresAt, session.identityId (if enabled)
|
|
37
38
|
// If session.newTokens is set, send new tokens back to client
|
|
38
39
|
//
|
|
39
40
|
// Session no longer carries a phone number — access tokens don't embed it, by
|
|
40
41
|
// design (JWT payloads are unencrypted and travel client-side). Store your own
|
|
41
|
-
// session_id -> phone mapping when you call
|
|
42
|
+
// session_id -> phone mapping when you call mm.otp.verify() (you already
|
|
42
43
|
// have the phone number then), and look it up from session.sessionId whenever
|
|
43
44
|
// you need it.
|
|
44
45
|
|
|
45
46
|
// Safe variant — never throws
|
|
46
|
-
const safe = await
|
|
47
|
+
const safe = await mm.session.safeValidate(token)
|
|
47
48
|
if (!safe.valid) {
|
|
48
49
|
res.status(401).json({ error: safe.code })
|
|
49
50
|
return
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
// Refresh — SDK handles this automatically on validate(); call manually only if needed proactively
|
|
53
|
-
const tokens = await
|
|
54
|
+
const tokens = await mm.session.refresh(refreshToken)
|
|
54
55
|
|
|
55
56
|
// Logout (auto-refreshes if access token is expired)
|
|
56
|
-
await
|
|
57
|
+
await mm.session.logout({ accessToken, refreshToken })
|
|
57
58
|
```
|
|
58
59
|
|
|
59
60
|
## Configuration
|
|
60
61
|
|
|
61
62
|
```ts
|
|
62
|
-
const
|
|
63
|
+
const mm = new MiniMoth({
|
|
63
64
|
apiKey: 'mm_live_...', // required
|
|
64
65
|
|
|
65
66
|
// Logging
|
|
@@ -73,7 +74,7 @@ const client = new MiniMoth({
|
|
|
73
74
|
}
|
|
74
75
|
})
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
mm.setLogLevel('warn') // update at runtime (only affects built-in console logger)
|
|
77
78
|
```
|
|
78
79
|
|
|
79
80
|
## validateMode
|
|
@@ -90,7 +91,7 @@ client.setLogLevel('warn') // update at runtime (only affects built-in cons
|
|
|
90
91
|
By default, the SDK uses an in-memory Map. In production with multiple server replicas, provide a shared store (e.g. Redis):
|
|
91
92
|
|
|
92
93
|
```ts
|
|
93
|
-
const
|
|
94
|
+
const mm = new MiniMoth({
|
|
94
95
|
apiKey: 'mm_live_...',
|
|
95
96
|
session: {
|
|
96
97
|
store: {
|
|
@@ -114,7 +115,7 @@ const client = new MiniMoth({
|
|
|
114
115
|
import { MiniMothError } from '@minimoth/sdk-node'
|
|
115
116
|
|
|
116
117
|
try {
|
|
117
|
-
await
|
|
118
|
+
await mm.session.validate(token)
|
|
118
119
|
} catch (err) {
|
|
119
120
|
if (err instanceof MiniMothError) {
|
|
120
121
|
// err.code: 'INVALID_ACCESS_TOKEN' | 'SESSION_EXPIRED' | 'NETWORK_ERROR' | ...
|
|
@@ -127,7 +128,7 @@ try {
|
|
|
127
128
|
Use `safeValidate` / `otp.verify` to avoid try/catch:
|
|
128
129
|
|
|
129
130
|
```ts
|
|
130
|
-
const result = await
|
|
131
|
+
const result = await mm.session.safeValidate(token)
|
|
131
132
|
if (!result.valid) return res.status(401).json({ error: result.code })
|
|
132
133
|
const { session } = result
|
|
133
134
|
```
|
|
@@ -195,6 +196,34 @@ Revoke all tokens for a session.
|
|
|
195
196
|
- Returns: Promise<void>
|
|
196
197
|
- Throws: `MiniMothError` if the token can't be decoded, the pre-logout refresh fails, or the logout call itself fails. Local session store cleanup errors are caught and logged internally — they don't affect the promise.
|
|
197
198
|
|
|
199
|
+
### IdentityClient
|
|
200
|
+
|
|
201
|
+
MiniMoth recognizes the same person across multiple logins over time via a per-project identity — `result.identityId` from `otp.verify()` and `session.identityId` from `session.validate()` are the id to use here. Identity lookup and deletion are opt-in per project (enable them in Project Settings at app.minimoth.dev) and only apply to live sessions — sandbox (`mm_test_`) keys always get `IDENTITY_NOT_FOUND`.
|
|
202
|
+
|
|
203
|
+
#### `get(identityId)`
|
|
204
|
+
|
|
205
|
+
Look up an identity by id.
|
|
206
|
+
|
|
207
|
+
- `identityId` (string, required): Identity id from `otp.verify()`/`session.validate()`
|
|
208
|
+
- Returns: `Promise<Identity>` where `Identity` is `{ id: string; createdAt: Date; factors: { type: string; value: string }[] }`
|
|
209
|
+
- Throws: `MiniMothError` with code `IDENTITY_NOT_FOUND` (no match, or lookup is disabled for a sandbox key) or `IDENTITY_LOOKUP_DISABLED` (not enabled for this project)
|
|
210
|
+
|
|
211
|
+
#### `getByPhone(phone)`
|
|
212
|
+
|
|
213
|
+
Look up an identity by phone number.
|
|
214
|
+
|
|
215
|
+
- `phone` (string, required): Indian phone number (e.g. `919876543210`)
|
|
216
|
+
- Returns: `Promise<Identity>`
|
|
217
|
+
- Throws: `MiniMothError` with code `IDENTITY_NOT_FOUND` or `IDENTITY_LOOKUP_DISABLED`, same as `get()`
|
|
218
|
+
|
|
219
|
+
#### `delete(identityId)`
|
|
220
|
+
|
|
221
|
+
Hard-delete an identity and revoke every active session tied to it.
|
|
222
|
+
|
|
223
|
+
- `identityId` (string, required): Identity id to delete
|
|
224
|
+
- Returns: `Promise<{ deleted: true }>`
|
|
225
|
+
- Throws: `MiniMothError` with code `IDENTITY_NOT_FOUND` or `IDENTITY_DELETE_DISABLED` (not enabled for this project)
|
|
226
|
+
|
|
198
227
|
## Error Codes
|
|
199
228
|
|
|
200
229
|
Common `MiniMothError.code` values:
|
|
@@ -207,6 +236,9 @@ Common `MiniMothError.code` values:
|
|
|
207
236
|
- `SESSION_EXPIRED`: Session has expired or was revoked — user must re-verify
|
|
208
237
|
- `INVALID_PHONE`: Phone number format is invalid
|
|
209
238
|
- `INSUFFICIENT_BALANCE`: Account has insufficient credits/balance
|
|
239
|
+
- `IDENTITY_NOT_FOUND`: No identity matches this id/phone, or the caller is a sandbox key
|
|
240
|
+
- `IDENTITY_LOOKUP_DISABLED`: Identity lookup is not enabled for this project
|
|
241
|
+
- `IDENTITY_DELETE_DISABLED`: Identity deletion is not enabled for this project
|
|
210
242
|
- `NETWORK_ERROR`: Network request failed
|
|
211
243
|
- `UNKNOWN_ERROR`: Unexpected server error
|
|
212
244
|
|
|
@@ -217,15 +249,15 @@ The SDK is fully typed. All client methods include inline JSDoc and return prope
|
|
|
217
249
|
```ts
|
|
218
250
|
import { MiniMoth, MiniMothError } from '@minimoth/sdk-node'
|
|
219
251
|
|
|
220
|
-
const
|
|
252
|
+
const mm = new MiniMoth({ apiKey: 'mm_live_...' })
|
|
221
253
|
|
|
222
254
|
// All methods are fully typed
|
|
223
|
-
const result = await
|
|
255
|
+
const result = await mm.otp.verify({
|
|
224
256
|
phone: '919876543210',
|
|
225
257
|
otp: '123456',
|
|
226
258
|
})
|
|
227
259
|
|
|
228
|
-
const session: Session = await
|
|
260
|
+
const session: Session = await mm.session.validate(token)
|
|
229
261
|
```
|
|
230
262
|
|
|
231
263
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -69,7 +69,10 @@ var BACKEND_CODE_MAP = {
|
|
|
69
69
|
OTP_RATE_LIMITED: "OTP_RATE_LIMITED",
|
|
70
70
|
VERIFY_RATE_LIMITED: "VERIFY_RATE_LIMITED",
|
|
71
71
|
INSUFFICIENT_BALANCE: "INSUFFICIENT_BALANCE",
|
|
72
|
-
INVALID_PHONE: "INVALID_PHONE"
|
|
72
|
+
INVALID_PHONE: "INVALID_PHONE",
|
|
73
|
+
IDENTITY_NOT_FOUND: "IDENTITY_NOT_FOUND",
|
|
74
|
+
IDENTITY_DELETE_DISABLED: "IDENTITY_DELETE_DISABLED",
|
|
75
|
+
IDENTITY_LOOKUP_DISABLED: "IDENTITY_LOOKUP_DISABLED"
|
|
73
76
|
};
|
|
74
77
|
async function handleResponse(response) {
|
|
75
78
|
if (response.ok) return response.json();
|
|
@@ -109,6 +112,35 @@ async function apiGet(path, apiKey) {
|
|
|
109
112
|
}
|
|
110
113
|
return handleResponse(response);
|
|
111
114
|
}
|
|
115
|
+
async function apiDelete(path, apiKey) {
|
|
116
|
+
let response;
|
|
117
|
+
try {
|
|
118
|
+
response = await fetch(`${BASE_URL}${path}`, {
|
|
119
|
+
method: "DELETE",
|
|
120
|
+
headers: {
|
|
121
|
+
"X-Api-Key": apiKey,
|
|
122
|
+
"User-Agent": USER_AGENT
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
} catch (err) {
|
|
126
|
+
throw new MiniMothError("NETWORK_ERROR", "Network request failed", 0, err);
|
|
127
|
+
}
|
|
128
|
+
return handleResponse(response);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/phone.ts
|
|
132
|
+
function normalizePhone(raw) {
|
|
133
|
+
if (!raw || typeof raw !== "string") {
|
|
134
|
+
throw new MiniMothError("INVALID_PHONE", "Phone number is required", 422);
|
|
135
|
+
}
|
|
136
|
+
if (/[\s-]/.test(raw)) {
|
|
137
|
+
throw new MiniMothError("INVALID_PHONE", "Phone number must not contain spaces or hyphens", 422);
|
|
138
|
+
}
|
|
139
|
+
let phone = raw;
|
|
140
|
+
if (phone.startsWith("+")) phone = phone.slice(1);
|
|
141
|
+
if (phone.length === 10) phone = "91" + phone;
|
|
142
|
+
return phone;
|
|
143
|
+
}
|
|
112
144
|
|
|
113
145
|
// src/otp/OtpClient.ts
|
|
114
146
|
var OtpClient = class {
|
|
@@ -161,7 +193,8 @@ var OtpClient = class {
|
|
|
161
193
|
valid: true,
|
|
162
194
|
accessToken: res.access_token,
|
|
163
195
|
refreshToken: res.refresh_token,
|
|
164
|
-
sessionId: payload.session_id
|
|
196
|
+
sessionId: payload.session_id,
|
|
197
|
+
...payload.identity_id ? { identityId: payload.identity_id } : {}
|
|
165
198
|
};
|
|
166
199
|
} catch (err) {
|
|
167
200
|
if (err instanceof MiniMothError) {
|
|
@@ -174,18 +207,6 @@ var OtpClient = class {
|
|
|
174
207
|
}
|
|
175
208
|
}
|
|
176
209
|
};
|
|
177
|
-
function normalizePhone(raw) {
|
|
178
|
-
if (!raw || typeof raw !== "string") {
|
|
179
|
-
throw new MiniMothError("INVALID_PHONE", "Phone number is required", 422);
|
|
180
|
-
}
|
|
181
|
-
if (/[\s-]/.test(raw)) {
|
|
182
|
-
throw new MiniMothError("INVALID_PHONE", "Phone number must not contain spaces or hyphens", 422);
|
|
183
|
-
}
|
|
184
|
-
let phone = raw;
|
|
185
|
-
if (phone.startsWith("+")) phone = phone.slice(1);
|
|
186
|
-
if (phone.length === 10) phone = "91" + phone;
|
|
187
|
-
return phone;
|
|
188
|
-
}
|
|
189
210
|
function validateOtp(otp) {
|
|
190
211
|
if (!otp || typeof otp !== "string") {
|
|
191
212
|
throw new MiniMothError("INVALID_OTP", "OTP is required", 422);
|
|
@@ -268,6 +289,7 @@ var SessionClient = class {
|
|
|
268
289
|
sessionId: payload.session_id,
|
|
269
290
|
expiresAt: new Date(payload.exp * 1e3)
|
|
270
291
|
};
|
|
292
|
+
if (payload.identity_id) session.identityId = payload.identity_id;
|
|
271
293
|
if (newTokens) session.newTokens = newTokens;
|
|
272
294
|
this.logger.info("session.validated", { sessionId: payload.session_id.slice(0, 8) });
|
|
273
295
|
return session;
|
|
@@ -336,6 +358,37 @@ var SessionClient = class {
|
|
|
336
358
|
}
|
|
337
359
|
};
|
|
338
360
|
|
|
361
|
+
// src/identity/IdentityClient.ts
|
|
362
|
+
var IdentityClient = class {
|
|
363
|
+
constructor(apiKey, logger) {
|
|
364
|
+
this.apiKey = apiKey;
|
|
365
|
+
this.logger = logger;
|
|
366
|
+
}
|
|
367
|
+
apiKey;
|
|
368
|
+
logger;
|
|
369
|
+
async get(identityId) {
|
|
370
|
+
const res = await apiGet(`/v1/identity/${encodeURIComponent(identityId)}`, this.apiKey);
|
|
371
|
+
return toIdentity(res);
|
|
372
|
+
}
|
|
373
|
+
async getByPhone(phone) {
|
|
374
|
+
const normalized = normalizePhone(phone);
|
|
375
|
+
const res = await apiGet(`/v1/identity?phone=${encodeURIComponent(normalized)}`, this.apiKey);
|
|
376
|
+
return toIdentity(res);
|
|
377
|
+
}
|
|
378
|
+
async delete(identityId) {
|
|
379
|
+
await apiDelete(`/v1/identity/${encodeURIComponent(identityId)}`, this.apiKey);
|
|
380
|
+
this.logger.info("identity.deleted", { identityId: identityId.slice(0, 8) });
|
|
381
|
+
return { deleted: true };
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
function toIdentity(res) {
|
|
385
|
+
return {
|
|
386
|
+
id: res.id,
|
|
387
|
+
createdAt: new Date(res.created_at),
|
|
388
|
+
factors: res.factors
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
339
392
|
// src/session/JwksCache.ts
|
|
340
393
|
var import_crypto = __toESM(require("crypto"), 1);
|
|
341
394
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -532,6 +585,7 @@ var ConsoleLogger = class {
|
|
|
532
585
|
var MiniMoth = class {
|
|
533
586
|
otp;
|
|
534
587
|
session;
|
|
588
|
+
identity;
|
|
535
589
|
consoleLogger;
|
|
536
590
|
constructor(config) {
|
|
537
591
|
this.consoleLogger = new ConsoleLogger(config.logLevel ?? "info");
|
|
@@ -550,6 +604,7 @@ var MiniMoth = class {
|
|
|
550
604
|
store,
|
|
551
605
|
logger
|
|
552
606
|
);
|
|
607
|
+
this.identity = new IdentityClient(config.apiKey, logger);
|
|
553
608
|
}
|
|
554
609
|
// Only affects the built-in ConsoleLogger. Has no effect if a custom logger was provided.
|
|
555
610
|
setLogLevel(level) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../node_modules/tsup/assets/cjs_shims.js","../src/otp/OtpClient.ts","../src/MiniMothError.ts","../src/http.ts","../src/session/SessionClient.ts","../src/session/JwksCache.ts","../src/session/RevocationCache.ts","../src/session/RefreshDeduplicator.ts","../src/store/DefaultSessionStore.ts","../src/logger/ConsoleLogger.ts","../src/MiniMoth.ts"],"sourcesContent":["export { MiniMoth } from './MiniMoth'\nexport { MiniMothError } from './MiniMothError'\nexport type { MiniMothErrorCode } from './MiniMothError'\nexport type { Session, ValidateMode, MiniMothConfig, AccessTokenPayload } from './types'\nexport type { MiniMothSessionStore } from './store/MiniMothSessionStore'\nexport type { MiniMothLogger } from './logger/MiniMothLogger'\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import jwt from 'jsonwebtoken'\nimport { apiPost, apiGet } from '../http'\nimport { MiniMothError, type MiniMothErrorCode } from '../MiniMothError'\nimport type { MiniMothSessionStore } from '../store/MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { AccessTokenPayload } from '../types'\n\ntype VerifyResult =\n | { valid: true; accessToken: string; refreshToken: string; sessionId: string }\n | { valid: false; code: MiniMothErrorCode }\n\ntype OtpStatus = {\n otpId: string\n channel: string | null\n status: 'queued' | 'delivered' | 'failed'\n deliveredAt: string | null\n}\n\nexport class OtpClient {\n constructor(\n private readonly apiKey: string,\n private readonly store: MiniMothSessionStore,\n private readonly logger: MiniMothLogger\n ) {}\n\n async send(params: { phone: string }): Promise<{ otpId: string }> {\n const phone = normalizePhone(params.phone)\n const res = await apiPost<{ message: string; otp_id: string }>('/v1/otp/send', this.apiKey, { phone })\n this.logger.info('otp.sent', { phone: maskPhone(phone) })\n return { otpId: res.otp_id }\n }\n\n async status(otpId: string): Promise<OtpStatus> {\n const res = await apiGet<{\n otp_id: string\n channel: string | null\n status: 'queued' | 'delivered' | 'failed'\n delivered_at: string | null\n }>(`/v1/otp/status/${encodeURIComponent(otpId)}`, this.apiKey)\n return {\n otpId: res.otp_id,\n channel: res.channel,\n status: res.status,\n deliveredAt: res.delivered_at,\n }\n }\n\n async verify(params: { phone: string; otp: string }): Promise<VerifyResult> {\n const phone = normalizePhone(params.phone)\n validateOtp(params.otp)\n\n try {\n const res = await apiPost<{ access_token: string; refresh_token: string; expires_at: string }>(\n '/v1/otp/verify',\n this.apiKey,\n { phone, code: params.otp }\n )\n\n const payload = jwt.decode(res.access_token) as AccessTokenPayload | null\n if (!payload?.session_id) {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Could not decode session_id from access token', 0)\n }\n\n try {\n await this.store.setTokens(payload.session_id, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch {\n this.logger.error('otp.store.setTokens.failed', { sessionId: payload.session_id.slice(0, 8) })\n }\n\n this.logger.info('otp.verified', { sessionId: payload.session_id.slice(0, 8) })\n\n return {\n valid: true,\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n sessionId: payload.session_id,\n }\n } catch (err) {\n if (err instanceof MiniMothError) {\n if (\n err.code === 'INVALID_OTP' ||\n err.code === 'OTP_NOT_FOUND' ||\n err.code === 'INVALID_PHONE' ||\n err.code === 'VERIFY_RATE_LIMITED'\n ) {\n this.logger.debug('otp.verify.failed', { code: err.code })\n return { valid: false, code: err.code }\n }\n }\n throw err\n }\n }\n}\n\n// Normalizes to 12-digit canonical Indian format (91XXXXXXXXXX).\n// Rejects if spaces or hyphens are present.\nfunction normalizePhone(raw: string): string {\n if (!raw || typeof raw !== 'string') {\n throw new MiniMothError('INVALID_PHONE', 'Phone number is required', 422)\n }\n if (/[\\s-]/.test(raw)) {\n throw new MiniMothError('INVALID_PHONE', 'Phone number must not contain spaces or hyphens', 422)\n }\n let phone = raw\n if (phone.startsWith('+')) phone = phone.slice(1)\n // 10-digit subscriber number — prepend country code\n if (phone.length === 10) phone = '91' + phone\n return phone\n}\n\nfunction validateOtp(otp: string): void {\n if (!otp || typeof otp !== 'string') {\n throw new MiniMothError('INVALID_OTP', 'OTP is required', 422)\n }\n}\n\nexport function maskPhone(phone: string): string {\n if (phone.length <= 4) return '****'\n return phone.slice(0, 4) + '*'.repeat(Math.max(phone.length - 6, 1)) + phone.slice(-2)\n}\n","export type MiniMothErrorCode =\n | 'INVALID_ACCESS_TOKEN'\n | 'SESSION_EXPIRED'\n | 'INVALID_OTP'\n | 'OTP_NOT_FOUND'\n | 'OTP_RATE_LIMITED'\n | 'VERIFY_RATE_LIMITED'\n | 'INSUFFICIENT_BALANCE'\n | 'NETWORK_ERROR'\n | 'INVALID_PHONE'\n | 'UNKNOWN_ERROR'\n\nexport class MiniMothError extends Error {\n readonly code: MiniMothErrorCode\n readonly statusCode: number\n\n constructor(code: MiniMothErrorCode, message: string, statusCode: number, cause?: unknown) {\n super(message, cause !== undefined ? { cause } : undefined)\n this.name = 'MiniMothError'\n this.code = code\n this.statusCode = statusCode\n // Restore prototype chain for instanceof checks across module boundaries\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n","import { MiniMothError, type MiniMothErrorCode } from './MiniMothError'\nimport { createRequire } from 'module'\n\nconst require = createRequire(import.meta.url)\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\nconst pkg = require('../package.json') as { version: string }\n\nconst BASE_URL = 'https://api.minimoth.dev'\nconst USER_AGENT = `minimoth-sdk-node/${pkg.version}`\n\nconst BACKEND_CODE_MAP: Record<string, MiniMothErrorCode> = {\n INVALID_ACCESS_TOKEN: 'INVALID_ACCESS_TOKEN',\n SESSION_EXPIRED: 'SESSION_EXPIRED',\n INVALID_OTP: 'INVALID_OTP',\n OTP_NOT_FOUND: 'OTP_NOT_FOUND',\n OTP_RATE_LIMITED: 'OTP_RATE_LIMITED',\n VERIFY_RATE_LIMITED: 'VERIFY_RATE_LIMITED',\n INSUFFICIENT_BALANCE: 'INSUFFICIENT_BALANCE',\n INVALID_PHONE: 'INVALID_PHONE',\n}\n\nasync function handleResponse<T>(response: Response): Promise<T> {\n if (response.ok) return response.json() as Promise<T>\n\n let body: { code?: string; error?: string } = {}\n try { body = await response.json() as { code?: string; error?: string } } catch {}\n\n const sdkCode: MiniMothErrorCode = BACKEND_CODE_MAP[body.code ?? ''] ?? 'UNKNOWN_ERROR'\n throw new MiniMothError(sdkCode, body.error ?? 'Unknown error', response.status)\n}\n\nexport async function apiPost<T>(\n path: string,\n apiKey: string,\n body: Record<string, unknown>\n): Promise<T> {\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Api-Key': apiKey,\n 'User-Agent': USER_AGENT,\n },\n body: JSON.stringify(body),\n })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n\nexport async function apiGet<T>(path: string, apiKey?: string): Promise<T> {\n const headers: Record<string, string> = { 'User-Agent': USER_AGENT }\n if (apiKey) headers['X-Api-Key'] = apiKey\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, { headers })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n","import jwt from 'jsonwebtoken'\nimport { apiPost } from '../http'\nimport { MiniMothError, type MiniMothErrorCode } from '../MiniMothError'\nimport type { JwksCache } from './JwksCache'\nimport type { RevocationCache } from './RevocationCache'\nimport type { RefreshDeduplicator } from './RefreshDeduplicator'\nimport type { MiniMothSessionStore } from '../store/MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { Session, AccessTokenPayload } from '../types'\n\ntype Tokens = { accessToken: string; refreshToken: string }\n\ntype SafeValidateResult =\n | { valid: true; session: Session }\n | { valid: false; code: MiniMothErrorCode }\n\nexport class SessionClient {\n constructor(\n private readonly apiKey: string,\n private readonly jwksCache: JwksCache,\n private readonly revocationCache: RevocationCache,\n private readonly deduplicator: RefreshDeduplicator,\n private readonly store: MiniMothSessionStore,\n private readonly logger: MiniMothLogger\n ) {}\n\n async validate(accessToken: string): Promise<Session> {\n const decoded = jwt.decode(accessToken, { complete: true })\n if (!decoded || typeof decoded === 'string') {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is malformed', 401)\n }\n\n const kid = (decoded.header as unknown as Record<string, string>)['kid']\n if (!kid) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is missing kid header', 401)\n\n const publicKey = await this.jwksCache.getKey(kid)\n\n let currentToken = accessToken\n let newTokens: Tokens | undefined\n\n try {\n jwt.verify(accessToken, publicKey, { algorithms: ['RS256'] })\n } catch (err) {\n if (err instanceof jwt.TokenExpiredError) {\n const expiredPayload = decoded.payload as AccessTokenPayload\n const sessionId = expiredPayload?.session_id\n if (!sessionId) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is invalid', 401)\n\n newTokens = await this.deduplicator.getOrRun(sessionId, async () => {\n const refreshToken = await this.store.getRefreshToken(sessionId)\n if (!refreshToken) {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Access token expired and no refresh token available', 401)\n }\n\n this.logger.info('session.auto_refresh', { sessionId: sessionId.slice(0, 8) })\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: refreshToken }\n )\n\n try {\n await this.store.setTokens(sessionId, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: sessionId.slice(0, 8) })\n }\n\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n })\n\n currentToken = newTokens.accessToken\n\n // Verify the new token\n const newDecoded = jwt.decode(currentToken, { complete: true })\n const newKid = (newDecoded?.header as Record<string, string> | undefined)?.['kid']\n const newKey = newKid ? await this.jwksCache.getKey(newKid) : publicKey\n jwt.verify(currentToken, newKey, { algorithms: ['RS256'] })\n } else {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token signature is invalid', 401)\n }\n }\n\n const payload = jwt.decode(currentToken) as AccessTokenPayload\n const isValid = await this.revocationCache.check(payload.jti, currentToken)\n if (!isValid) throw new MiniMothError('SESSION_EXPIRED', 'Session has been revoked', 401)\n\n const session: Session = {\n projectId: payload.project_id,\n sessionId: payload.session_id,\n expiresAt: new Date(payload.exp * 1000),\n }\n if (newTokens) session.newTokens = newTokens\n\n this.logger.info('session.validated', { sessionId: payload.session_id.slice(0, 8) })\n return session\n }\n\n async safeValidate(accessToken: string): Promise<SafeValidateResult> {\n try {\n const session = await this.validate(accessToken)\n return { valid: true, session }\n } catch (err) {\n if (err instanceof MiniMothError) return { valid: false, code: err.code }\n throw err\n }\n }\n\n async refresh(refreshToken: string): Promise<Tokens> {\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: refreshToken }\n )\n\n // Update store if session_id is decodable from new token\n const payload = jwt.decode(res.access_token) as AccessTokenPayload | null\n if (payload?.session_id) {\n try {\n await this.store.setTokens(payload.session_id, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: payload.session_id.slice(0, 8) })\n }\n }\n\n this.logger.info('session.refreshed')\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n }\n\n async logout(params: { accessToken: string; refreshToken: string }): Promise<void> {\n const payload = jwt.decode(params.accessToken) as AccessTokenPayload | null\n const sessionId = payload?.session_id ?? null\n\n if (!sessionId) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Cannot decode token', 401)\n\n let currentAccessToken = params.accessToken\n\n // If token is expired, refresh before logout — deduplicated to prevent concurrent refresh races\n if (payload && payload.exp < Math.floor(Date.now() / 1000)) {\n const newTokens = await this.deduplicator.getOrRun(sessionId, async () => {\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: params.refreshToken }\n )\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n })\n currentAccessToken = newTokens.accessToken\n try {\n await this.store.setTokens(sessionId, newTokens)\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: sessionId.slice(0, 8) })\n }\n }\n\n await apiPost<{ message: string }>(\n '/v1/session/logout',\n this.apiKey,\n { access_token: currentAccessToken }\n )\n\n try {\n await this.store.deleteSession(sessionId)\n } catch (err) {\n this.logger.error('session.store.deleteSession.failed', { sessionId: sessionId.slice(0, 8) })\n }\n this.logger.info('session.logged_out', { sessionId: sessionId.slice(0, 8) })\n }\n}\n","import crypto from 'crypto'\nimport { apiGet } from '../http'\nimport { MiniMothError } from '../MiniMothError'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\n\nconst CACHE_TTL_MS = 60 * 60 * 1000 // 1 hour\n\ntype JwkEntry = Record<string, string>\n\nexport class JwksCache {\n private keyMap = new Map<string, crypto.KeyObject>()\n private fetchedAt = 0\n private fetching: Promise<void> | null = null\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n async getKey(kid: string): Promise<crypto.KeyObject> {\n if (this.keyMap.size === 0 || Date.now() - this.fetchedAt > CACHE_TTL_MS) {\n await this.fetch()\n }\n\n let key = this.keyMap.get(kid)\n if (!key) {\n this.logger.debug('jwks.unknown_kid', { kid })\n await this.fetch()\n key = this.keyMap.get(kid)\n }\n\n if (!key) throw new MiniMothError('INVALID_ACCESS_TOKEN', `No public key found for kid: ${kid}`, 401)\n return key\n }\n\n private fetch(): Promise<void> {\n if (this.fetching) return this.fetching\n this.fetching = this.doFetch().finally(() => { this.fetching = null })\n return this.fetching\n }\n\n private async doFetch(): Promise<void> {\n this.logger.debug('jwks.fetch')\n const data = await apiGet<{ keys: JwkEntry[] }>('/.well-known/jwks.json')\n const newMap = new Map<string, crypto.KeyObject>()\n for (const jwk of data.keys) {\n if (jwk['kid'] && jwk['kty'] === 'RSA') {\n const key = crypto.createPublicKey({ key: jwk as unknown as crypto.JsonWebKey, format: 'jwk' })\n newMap.set(jwk['kid'], key)\n }\n }\n this.keyMap = newMap\n this.fetchedAt = Date.now()\n this.logger.debug('jwks.updated', { keyCount: newMap.size })\n }\n}\n","import { apiPost } from '../http'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { ValidateMode } from '../types'\n\nconst MODE_TTL_MS: Partial<Record<ValidateMode, number>> = {\n recheck_1m: 60_000,\n recheck_3m: 180_000,\n}\n\nconst EVICTION_TTL_MS = 5 * 60 * 1000 // JWT max lifetime\nconst CLEANUP_WINDOW_MS = 5 * 60 * 1000\n\ntype Entry = { checkedAt: number }\n\nexport class RevocationCache {\n private readonly cache = new Map<string, Entry>()\n private lastCleanedAt = 0\n\n constructor(\n private readonly mode: ValidateMode,\n private readonly apiKey: string,\n private readonly logger: MiniMothLogger\n ) {}\n\n async check(jti: string, accessToken: string): Promise<boolean> {\n if (this.mode === 'instant') return true\n\n if (this.mode !== 'strict') this.maybeCleanup()\n\n const ttl = MODE_TTL_MS[this.mode] ?? 0\n if (ttl > 0) {\n const entry = this.cache.get(jti)\n if (entry && Date.now() - entry.checkedAt < ttl) {\n this.logger.debug('revocation.cache.hit', { jti: jti.slice(0, 8) })\n return true\n }\n }\n\n try {\n const result = await apiPost<{ valid: boolean }>(\n '/v1/session/validate',\n this.apiKey,\n { access_token: accessToken }\n )\n\n if (result.valid && ttl > 0) {\n this.cache.set(jti, { checkedAt: Date.now() })\n }\n\n return result.valid\n } catch (err) {\n if (this.mode === 'strict') throw err\n\n // recheck_*m: fail open\n this.logger.warn('revocation.check.failed_open', {\n jti: jti.slice(0, 8),\n error: err instanceof Error ? err.message : 'unknown',\n })\n return true\n }\n }\n\n private maybeCleanup(): void {\n const now = Date.now()\n if (now - this.lastCleanedAt < CLEANUP_WINDOW_MS) return\n this.lastCleanedAt = now // set before iteration to prevent concurrent double-clean\n for (const [jti, entry] of this.cache) {\n if (now - entry.checkedAt > EVICTION_TTL_MS) {\n this.cache.delete(jti)\n }\n }\n }\n}\n","import { MiniMothLogger } from '../logger/MiniMothLogger'\n\ntype Tokens = { accessToken: string; refreshToken: string }\n\nexport class RefreshDeduplicator {\n private readonly inflight = new Map<string, Promise<unknown>>()\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n getOrRun<T>(sessionId: string, fn: () => Promise<T>): Promise<T> {\n const existing = this.inflight.get(sessionId)\n if (existing) {\n this.logger.debug('refresh dedup hit', { key: sessionId })\n return existing as Promise<T>\n }\n\n const promise = fn().finally(() => {\n this.inflight.delete(sessionId)\n })\n\n this.inflight.set(sessionId, promise)\n return promise\n }\n}\n","import type { MiniMothSessionStore } from './MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\n\ntype Entry = { accessToken: string; refreshToken: string }\n\nexport class DefaultSessionStore implements MiniMothSessionStore {\n private readonly map = new Map<string, Entry>()\n private warnedProduction = false\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n private maybeWarn(): void {\n if (process.env['NODE_ENV'] === 'production' && !this.warnedProduction) {\n this.warnedProduction = true\n this.logger.warn('using default in-memory session store — not suitable for multi-replica deployments')\n }\n }\n\n async getRefreshToken(sessionId: string): Promise<string | null> {\n this.maybeWarn()\n return this.map.get(sessionId)?.refreshToken ?? null\n }\n\n async setTokens(sessionId: string, tokens: { accessToken: string; refreshToken: string }): Promise<void> {\n this.maybeWarn()\n this.map.set(sessionId, tokens)\n }\n\n async deleteSession(sessionId: string): Promise<void> {\n this.map.delete(sessionId)\n }\n}\n","import type { MiniMothLogger } from './MiniMothLogger'\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0, info: 1, warn: 2, error: 3, silent: 4,\n}\n\nexport class ConsoleLogger implements MiniMothLogger {\n private level: LogLevel\n\n constructor(level: LogLevel = 'info') {\n this.level = level\n }\n\n setLevel(level: LogLevel): void {\n this.level = level\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[this.level]\n }\n\n private format(msg: string, meta?: Record<string, unknown>): string {\n if (!meta || Object.keys(meta).length === 0) return `[minimoth] ${msg}`\n return `[minimoth] ${msg} ${JSON.stringify(meta)}`\n }\n\n debug(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('debug')) console.debug(this.format(msg, meta))\n }\n\n info(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('info')) console.info(this.format(msg, meta))\n }\n\n warn(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('warn')) console.warn(this.format(msg, meta))\n }\n\n error(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('error')) console.error(this.format(msg, meta))\n }\n}\n","import { OtpClient } from './otp/OtpClient'\nimport { SessionClient } from './session/SessionClient'\nimport { JwksCache } from './session/JwksCache'\nimport { RevocationCache } from './session/RevocationCache'\nimport { RefreshDeduplicator } from './session/RefreshDeduplicator'\nimport { DefaultSessionStore } from './store/DefaultSessionStore'\nimport { ConsoleLogger } from './logger/ConsoleLogger'\nimport type { MiniMothConfig } from './types'\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nexport class MiniMoth {\n readonly otp: OtpClient\n readonly session: SessionClient\n private readonly consoleLogger: ConsoleLogger\n\n constructor(config: MiniMothConfig) {\n this.consoleLogger = new ConsoleLogger(config.logLevel ?? 'info')\n const logger = config.logger ?? this.consoleLogger\n\n const store = config.session?.store ?? new DefaultSessionStore(logger)\n const validateMode = config.session?.validateMode ?? 'instant'\n\n const jwksCache = new JwksCache(logger)\n const revocationCache = new RevocationCache(validateMode, config.apiKey, logger)\n const deduplicator = new RefreshDeduplicator(logger)\n\n this.otp = new OtpClient(config.apiKey, store, logger)\n this.session = new SessionClient(\n config.apiKey,\n jwksCache,\n revocationCache,\n deduplicator,\n store,\n logger\n )\n }\n\n // Only affects the built-in ConsoleLogger. Has no effect if a custom logger was provided.\n setLogLevel(level: LogLevel): void {\n this.consoleLogger.setLevel(level)\n }\n}\n"],"mappings":"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","names":["require","jwt","import_jsonwebtoken","jwt","err","crypto"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../node_modules/tsup/assets/cjs_shims.js","../src/otp/OtpClient.ts","../src/MiniMothError.ts","../src/http.ts","../src/phone.ts","../src/session/SessionClient.ts","../src/identity/IdentityClient.ts","../src/session/JwksCache.ts","../src/session/RevocationCache.ts","../src/session/RefreshDeduplicator.ts","../src/store/DefaultSessionStore.ts","../src/logger/ConsoleLogger.ts","../src/MiniMoth.ts"],"sourcesContent":["export { MiniMoth } from './MiniMoth'\nexport { MiniMothError } from './MiniMothError'\nexport type { MiniMothErrorCode } from './MiniMothError'\nexport type { Session, ValidateMode, MiniMothConfig, AccessTokenPayload, Identity, IdentityFactor } from './types'\nexport type { MiniMothSessionStore } from './store/MiniMothSessionStore'\nexport type { MiniMothLogger } from './logger/MiniMothLogger'\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import jwt from 'jsonwebtoken'\nimport { apiPost, apiGet } from '../http'\nimport { MiniMothError, type MiniMothErrorCode } from '../MiniMothError'\nimport { normalizePhone } from '../phone'\nimport type { MiniMothSessionStore } from '../store/MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { AccessTokenPayload } from '../types'\n\ntype VerifyResult =\n | { valid: true; accessToken: string; refreshToken: string; sessionId: string; identityId?: string }\n | { valid: false; code: MiniMothErrorCode }\n\ntype OtpStatus = {\n otpId: string\n channel: string | null\n status: 'queued' | 'delivered' | 'failed'\n deliveredAt: string | null\n}\n\nexport class OtpClient {\n constructor(\n private readonly apiKey: string,\n private readonly store: MiniMothSessionStore,\n private readonly logger: MiniMothLogger\n ) {}\n\n async send(params: { phone: string }): Promise<{ otpId: string }> {\n const phone = normalizePhone(params.phone)\n const res = await apiPost<{ message: string; otp_id: string }>('/v1/otp/send', this.apiKey, { phone })\n this.logger.info('otp.sent', { phone: maskPhone(phone) })\n return { otpId: res.otp_id }\n }\n\n async status(otpId: string): Promise<OtpStatus> {\n const res = await apiGet<{\n otp_id: string\n channel: string | null\n status: 'queued' | 'delivered' | 'failed'\n delivered_at: string | null\n }>(`/v1/otp/status/${encodeURIComponent(otpId)}`, this.apiKey)\n return {\n otpId: res.otp_id,\n channel: res.channel,\n status: res.status,\n deliveredAt: res.delivered_at,\n }\n }\n\n async verify(params: { phone: string; otp: string }): Promise<VerifyResult> {\n const phone = normalizePhone(params.phone)\n validateOtp(params.otp)\n\n try {\n const res = await apiPost<{ access_token: string; refresh_token: string; expires_at: string }>(\n '/v1/otp/verify',\n this.apiKey,\n { phone, code: params.otp }\n )\n\n const payload = jwt.decode(res.access_token) as AccessTokenPayload | null\n if (!payload?.session_id) {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Could not decode session_id from access token', 0)\n }\n\n try {\n await this.store.setTokens(payload.session_id, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch {\n this.logger.error('otp.store.setTokens.failed', { sessionId: payload.session_id.slice(0, 8) })\n }\n\n this.logger.info('otp.verified', { sessionId: payload.session_id.slice(0, 8) })\n\n return {\n valid: true,\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n sessionId: payload.session_id,\n ...(payload.identity_id ? { identityId: payload.identity_id } : {}),\n }\n } catch (err) {\n if (err instanceof MiniMothError) {\n if (\n err.code === 'INVALID_OTP' ||\n err.code === 'OTP_NOT_FOUND' ||\n err.code === 'INVALID_PHONE' ||\n err.code === 'VERIFY_RATE_LIMITED'\n ) {\n this.logger.debug('otp.verify.failed', { code: err.code })\n return { valid: false, code: err.code }\n }\n }\n throw err\n }\n }\n}\n\nfunction validateOtp(otp: string): void {\n if (!otp || typeof otp !== 'string') {\n throw new MiniMothError('INVALID_OTP', 'OTP is required', 422)\n }\n}\n\nexport function maskPhone(phone: string): string {\n if (phone.length <= 4) return '****'\n return phone.slice(0, 4) + '*'.repeat(Math.max(phone.length - 6, 1)) + phone.slice(-2)\n}\n","export type MiniMothErrorCode =\n | 'INVALID_ACCESS_TOKEN'\n | 'SESSION_EXPIRED'\n | 'INVALID_OTP'\n | 'OTP_NOT_FOUND'\n | 'OTP_RATE_LIMITED'\n | 'VERIFY_RATE_LIMITED'\n | 'INSUFFICIENT_BALANCE'\n | 'NETWORK_ERROR'\n | 'INVALID_PHONE'\n | 'IDENTITY_NOT_FOUND'\n | 'IDENTITY_DELETE_DISABLED'\n | 'IDENTITY_LOOKUP_DISABLED'\n | 'UNKNOWN_ERROR'\n\nexport class MiniMothError extends Error {\n readonly code: MiniMothErrorCode\n readonly statusCode: number\n\n constructor(code: MiniMothErrorCode, message: string, statusCode: number, cause?: unknown) {\n super(message, cause !== undefined ? { cause } : undefined)\n this.name = 'MiniMothError'\n this.code = code\n this.statusCode = statusCode\n // Restore prototype chain for instanceof checks across module boundaries\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n","import { MiniMothError, type MiniMothErrorCode } from './MiniMothError'\nimport { createRequire } from 'module'\n\nconst require = createRequire(import.meta.url)\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\nconst pkg = require('../package.json') as { version: string }\n\nconst BASE_URL = 'https://api.minimoth.dev'\nconst USER_AGENT = `minimoth-sdk-node/${pkg.version}`\n\nconst BACKEND_CODE_MAP: Record<string, MiniMothErrorCode> = {\n INVALID_ACCESS_TOKEN: 'INVALID_ACCESS_TOKEN',\n SESSION_EXPIRED: 'SESSION_EXPIRED',\n INVALID_OTP: 'INVALID_OTP',\n OTP_NOT_FOUND: 'OTP_NOT_FOUND',\n OTP_RATE_LIMITED: 'OTP_RATE_LIMITED',\n VERIFY_RATE_LIMITED: 'VERIFY_RATE_LIMITED',\n INSUFFICIENT_BALANCE: 'INSUFFICIENT_BALANCE',\n INVALID_PHONE: 'INVALID_PHONE',\n IDENTITY_NOT_FOUND: 'IDENTITY_NOT_FOUND',\n IDENTITY_DELETE_DISABLED: 'IDENTITY_DELETE_DISABLED',\n IDENTITY_LOOKUP_DISABLED: 'IDENTITY_LOOKUP_DISABLED',\n}\n\nasync function handleResponse<T>(response: Response): Promise<T> {\n if (response.ok) return response.json() as Promise<T>\n\n let body: { code?: string; error?: string } = {}\n try { body = await response.json() as { code?: string; error?: string } } catch {}\n\n const sdkCode: MiniMothErrorCode = BACKEND_CODE_MAP[body.code ?? ''] ?? 'UNKNOWN_ERROR'\n throw new MiniMothError(sdkCode, body.error ?? 'Unknown error', response.status)\n}\n\nexport async function apiPost<T>(\n path: string,\n apiKey: string,\n body: Record<string, unknown>\n): Promise<T> {\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Api-Key': apiKey,\n 'User-Agent': USER_AGENT,\n },\n body: JSON.stringify(body),\n })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n\nexport async function apiGet<T>(path: string, apiKey?: string): Promise<T> {\n const headers: Record<string, string> = { 'User-Agent': USER_AGENT }\n if (apiKey) headers['X-Api-Key'] = apiKey\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, { headers })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n\nexport async function apiDelete<T>(path: string, apiKey: string): Promise<T> {\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, {\n method: 'DELETE',\n headers: {\n 'X-Api-Key': apiKey,\n 'User-Agent': USER_AGENT,\n },\n })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n","import { MiniMothError } from './MiniMothError'\n\n// Normalizes to 12-digit canonical Indian format (91XXXXXXXXXX).\n// Rejects if spaces or hyphens are present.\nexport function normalizePhone(raw: string): string {\n if (!raw || typeof raw !== 'string') {\n throw new MiniMothError('INVALID_PHONE', 'Phone number is required', 422)\n }\n if (/[\\s-]/.test(raw)) {\n throw new MiniMothError('INVALID_PHONE', 'Phone number must not contain spaces or hyphens', 422)\n }\n let phone = raw\n if (phone.startsWith('+')) phone = phone.slice(1)\n // 10-digit subscriber number — prepend country code\n if (phone.length === 10) phone = '91' + phone\n return phone\n}\n","import jwt from 'jsonwebtoken'\nimport { apiPost } from '../http'\nimport { MiniMothError, type MiniMothErrorCode } from '../MiniMothError'\nimport type { JwksCache } from './JwksCache'\nimport type { RevocationCache } from './RevocationCache'\nimport type { RefreshDeduplicator } from './RefreshDeduplicator'\nimport type { MiniMothSessionStore } from '../store/MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { Session, AccessTokenPayload } from '../types'\n\ntype Tokens = { accessToken: string; refreshToken: string }\n\ntype SafeValidateResult =\n | { valid: true; session: Session }\n | { valid: false; code: MiniMothErrorCode }\n\nexport class SessionClient {\n constructor(\n private readonly apiKey: string,\n private readonly jwksCache: JwksCache,\n private readonly revocationCache: RevocationCache,\n private readonly deduplicator: RefreshDeduplicator,\n private readonly store: MiniMothSessionStore,\n private readonly logger: MiniMothLogger\n ) {}\n\n async validate(accessToken: string): Promise<Session> {\n const decoded = jwt.decode(accessToken, { complete: true })\n if (!decoded || typeof decoded === 'string') {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is malformed', 401)\n }\n\n const kid = (decoded.header as unknown as Record<string, string>)['kid']\n if (!kid) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is missing kid header', 401)\n\n const publicKey = await this.jwksCache.getKey(kid)\n\n let currentToken = accessToken\n let newTokens: Tokens | undefined\n\n try {\n jwt.verify(accessToken, publicKey, { algorithms: ['RS256'] })\n } catch (err) {\n if (err instanceof jwt.TokenExpiredError) {\n const expiredPayload = decoded.payload as AccessTokenPayload\n const sessionId = expiredPayload?.session_id\n if (!sessionId) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is invalid', 401)\n\n newTokens = await this.deduplicator.getOrRun(sessionId, async () => {\n const refreshToken = await this.store.getRefreshToken(sessionId)\n if (!refreshToken) {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Access token expired and no refresh token available', 401)\n }\n\n this.logger.info('session.auto_refresh', { sessionId: sessionId.slice(0, 8) })\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: refreshToken }\n )\n\n try {\n await this.store.setTokens(sessionId, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: sessionId.slice(0, 8) })\n }\n\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n })\n\n currentToken = newTokens.accessToken\n\n // Verify the new token\n const newDecoded = jwt.decode(currentToken, { complete: true })\n const newKid = (newDecoded?.header as Record<string, string> | undefined)?.['kid']\n const newKey = newKid ? await this.jwksCache.getKey(newKid) : publicKey\n jwt.verify(currentToken, newKey, { algorithms: ['RS256'] })\n } else {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token signature is invalid', 401)\n }\n }\n\n const payload = jwt.decode(currentToken) as AccessTokenPayload\n const isValid = await this.revocationCache.check(payload.jti, currentToken)\n if (!isValid) throw new MiniMothError('SESSION_EXPIRED', 'Session has been revoked', 401)\n\n const session: Session = {\n projectId: payload.project_id,\n sessionId: payload.session_id,\n expiresAt: new Date(payload.exp * 1000),\n }\n if (payload.identity_id) session.identityId = payload.identity_id\n if (newTokens) session.newTokens = newTokens\n\n this.logger.info('session.validated', { sessionId: payload.session_id.slice(0, 8) })\n return session\n }\n\n async safeValidate(accessToken: string): Promise<SafeValidateResult> {\n try {\n const session = await this.validate(accessToken)\n return { valid: true, session }\n } catch (err) {\n if (err instanceof MiniMothError) return { valid: false, code: err.code }\n throw err\n }\n }\n\n async refresh(refreshToken: string): Promise<Tokens> {\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: refreshToken }\n )\n\n // Update store if session_id is decodable from new token\n const payload = jwt.decode(res.access_token) as AccessTokenPayload | null\n if (payload?.session_id) {\n try {\n await this.store.setTokens(payload.session_id, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: payload.session_id.slice(0, 8) })\n }\n }\n\n this.logger.info('session.refreshed')\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n }\n\n async logout(params: { accessToken: string; refreshToken: string }): Promise<void> {\n const payload = jwt.decode(params.accessToken) as AccessTokenPayload | null\n const sessionId = payload?.session_id ?? null\n\n if (!sessionId) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Cannot decode token', 401)\n\n let currentAccessToken = params.accessToken\n\n // If token is expired, refresh before logout — deduplicated to prevent concurrent refresh races\n if (payload && payload.exp < Math.floor(Date.now() / 1000)) {\n const newTokens = await this.deduplicator.getOrRun(sessionId, async () => {\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: params.refreshToken }\n )\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n })\n currentAccessToken = newTokens.accessToken\n try {\n await this.store.setTokens(sessionId, newTokens)\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: sessionId.slice(0, 8) })\n }\n }\n\n await apiPost<{ message: string }>(\n '/v1/session/logout',\n this.apiKey,\n { access_token: currentAccessToken }\n )\n\n try {\n await this.store.deleteSession(sessionId)\n } catch (err) {\n this.logger.error('session.store.deleteSession.failed', { sessionId: sessionId.slice(0, 8) })\n }\n this.logger.info('session.logged_out', { sessionId: sessionId.slice(0, 8) })\n }\n}\n","import { apiGet, apiDelete } from '../http'\nimport { normalizePhone } from '../phone'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { Identity, IdentityFactor } from '../types'\n\ntype IdentityResponse = {\n id: string\n created_at: string\n factors: IdentityFactor[]\n}\n\nexport class IdentityClient {\n constructor(\n private readonly apiKey: string,\n private readonly logger: MiniMothLogger\n ) {}\n\n async get(identityId: string): Promise<Identity> {\n const res = await apiGet<IdentityResponse>(`/v1/identity/${encodeURIComponent(identityId)}`, this.apiKey)\n return toIdentity(res)\n }\n\n async getByPhone(phone: string): Promise<Identity> {\n const normalized = normalizePhone(phone)\n const res = await apiGet<IdentityResponse>(`/v1/identity?phone=${encodeURIComponent(normalized)}`, this.apiKey)\n return toIdentity(res)\n }\n\n async delete(identityId: string): Promise<{ deleted: true }> {\n await apiDelete<{ deleted: boolean }>(`/v1/identity/${encodeURIComponent(identityId)}`, this.apiKey)\n this.logger.info('identity.deleted', { identityId: identityId.slice(0, 8) })\n return { deleted: true }\n }\n}\n\nfunction toIdentity(res: IdentityResponse): Identity {\n return {\n id: res.id,\n createdAt: new Date(res.created_at),\n factors: res.factors,\n }\n}\n","import crypto from 'crypto'\nimport { apiGet } from '../http'\nimport { MiniMothError } from '../MiniMothError'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\n\nconst CACHE_TTL_MS = 60 * 60 * 1000 // 1 hour\n\ntype JwkEntry = Record<string, string>\n\nexport class JwksCache {\n private keyMap = new Map<string, crypto.KeyObject>()\n private fetchedAt = 0\n private fetching: Promise<void> | null = null\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n async getKey(kid: string): Promise<crypto.KeyObject> {\n if (this.keyMap.size === 0 || Date.now() - this.fetchedAt > CACHE_TTL_MS) {\n await this.fetch()\n }\n\n let key = this.keyMap.get(kid)\n if (!key) {\n this.logger.debug('jwks.unknown_kid', { kid })\n await this.fetch()\n key = this.keyMap.get(kid)\n }\n\n if (!key) throw new MiniMothError('INVALID_ACCESS_TOKEN', `No public key found for kid: ${kid}`, 401)\n return key\n }\n\n private fetch(): Promise<void> {\n if (this.fetching) return this.fetching\n this.fetching = this.doFetch().finally(() => { this.fetching = null })\n return this.fetching\n }\n\n private async doFetch(): Promise<void> {\n this.logger.debug('jwks.fetch')\n const data = await apiGet<{ keys: JwkEntry[] }>('/.well-known/jwks.json')\n const newMap = new Map<string, crypto.KeyObject>()\n for (const jwk of data.keys) {\n if (jwk['kid'] && jwk['kty'] === 'RSA') {\n const key = crypto.createPublicKey({ key: jwk as unknown as crypto.JsonWebKey, format: 'jwk' })\n newMap.set(jwk['kid'], key)\n }\n }\n this.keyMap = newMap\n this.fetchedAt = Date.now()\n this.logger.debug('jwks.updated', { keyCount: newMap.size })\n }\n}\n","import { apiPost } from '../http'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { ValidateMode } from '../types'\n\nconst MODE_TTL_MS: Partial<Record<ValidateMode, number>> = {\n recheck_1m: 60_000,\n recheck_3m: 180_000,\n}\n\nconst EVICTION_TTL_MS = 5 * 60 * 1000 // JWT max lifetime\nconst CLEANUP_WINDOW_MS = 5 * 60 * 1000\n\ntype Entry = { checkedAt: number }\n\nexport class RevocationCache {\n private readonly cache = new Map<string, Entry>()\n private lastCleanedAt = 0\n\n constructor(\n private readonly mode: ValidateMode,\n private readonly apiKey: string,\n private readonly logger: MiniMothLogger\n ) {}\n\n async check(jti: string, accessToken: string): Promise<boolean> {\n if (this.mode === 'instant') return true\n\n if (this.mode !== 'strict') this.maybeCleanup()\n\n const ttl = MODE_TTL_MS[this.mode] ?? 0\n if (ttl > 0) {\n const entry = this.cache.get(jti)\n if (entry && Date.now() - entry.checkedAt < ttl) {\n this.logger.debug('revocation.cache.hit', { jti: jti.slice(0, 8) })\n return true\n }\n }\n\n try {\n const result = await apiPost<{ valid: boolean }>(\n '/v1/session/validate',\n this.apiKey,\n { access_token: accessToken }\n )\n\n if (result.valid && ttl > 0) {\n this.cache.set(jti, { checkedAt: Date.now() })\n }\n\n return result.valid\n } catch (err) {\n if (this.mode === 'strict') throw err\n\n // recheck_*m: fail open\n this.logger.warn('revocation.check.failed_open', {\n jti: jti.slice(0, 8),\n error: err instanceof Error ? err.message : 'unknown',\n })\n return true\n }\n }\n\n private maybeCleanup(): void {\n const now = Date.now()\n if (now - this.lastCleanedAt < CLEANUP_WINDOW_MS) return\n this.lastCleanedAt = now // set before iteration to prevent concurrent double-clean\n for (const [jti, entry] of this.cache) {\n if (now - entry.checkedAt > EVICTION_TTL_MS) {\n this.cache.delete(jti)\n }\n }\n }\n}\n","import { MiniMothLogger } from '../logger/MiniMothLogger'\n\ntype Tokens = { accessToken: string; refreshToken: string }\n\nexport class RefreshDeduplicator {\n private readonly inflight = new Map<string, Promise<unknown>>()\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n getOrRun<T>(sessionId: string, fn: () => Promise<T>): Promise<T> {\n const existing = this.inflight.get(sessionId)\n if (existing) {\n this.logger.debug('refresh dedup hit', { key: sessionId })\n return existing as Promise<T>\n }\n\n const promise = fn().finally(() => {\n this.inflight.delete(sessionId)\n })\n\n this.inflight.set(sessionId, promise)\n return promise\n }\n}\n","import type { MiniMothSessionStore } from './MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\n\ntype Entry = { accessToken: string; refreshToken: string }\n\nexport class DefaultSessionStore implements MiniMothSessionStore {\n private readonly map = new Map<string, Entry>()\n private warnedProduction = false\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n private maybeWarn(): void {\n if (process.env['NODE_ENV'] === 'production' && !this.warnedProduction) {\n this.warnedProduction = true\n this.logger.warn('using default in-memory session store — not suitable for multi-replica deployments')\n }\n }\n\n async getRefreshToken(sessionId: string): Promise<string | null> {\n this.maybeWarn()\n return this.map.get(sessionId)?.refreshToken ?? null\n }\n\n async setTokens(sessionId: string, tokens: { accessToken: string; refreshToken: string }): Promise<void> {\n this.maybeWarn()\n this.map.set(sessionId, tokens)\n }\n\n async deleteSession(sessionId: string): Promise<void> {\n this.map.delete(sessionId)\n }\n}\n","import type { MiniMothLogger } from './MiniMothLogger'\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0, info: 1, warn: 2, error: 3, silent: 4,\n}\n\nexport class ConsoleLogger implements MiniMothLogger {\n private level: LogLevel\n\n constructor(level: LogLevel = 'info') {\n this.level = level\n }\n\n setLevel(level: LogLevel): void {\n this.level = level\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[this.level]\n }\n\n private format(msg: string, meta?: Record<string, unknown>): string {\n if (!meta || Object.keys(meta).length === 0) return `[minimoth] ${msg}`\n return `[minimoth] ${msg} ${JSON.stringify(meta)}`\n }\n\n debug(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('debug')) console.debug(this.format(msg, meta))\n }\n\n info(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('info')) console.info(this.format(msg, meta))\n }\n\n warn(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('warn')) console.warn(this.format(msg, meta))\n }\n\n error(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('error')) console.error(this.format(msg, meta))\n }\n}\n","import { OtpClient } from './otp/OtpClient'\nimport { SessionClient } from './session/SessionClient'\nimport { IdentityClient } from './identity/IdentityClient'\nimport { JwksCache } from './session/JwksCache'\nimport { RevocationCache } from './session/RevocationCache'\nimport { RefreshDeduplicator } from './session/RefreshDeduplicator'\nimport { DefaultSessionStore } from './store/DefaultSessionStore'\nimport { ConsoleLogger } from './logger/ConsoleLogger'\nimport type { MiniMothConfig } from './types'\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nexport class MiniMoth {\n readonly otp: OtpClient\n readonly session: SessionClient\n readonly identity: IdentityClient\n private readonly consoleLogger: ConsoleLogger\n\n constructor(config: MiniMothConfig) {\n this.consoleLogger = new ConsoleLogger(config.logLevel ?? 'info')\n const logger = config.logger ?? this.consoleLogger\n\n const store = config.session?.store ?? new DefaultSessionStore(logger)\n const validateMode = config.session?.validateMode ?? 'instant'\n\n const jwksCache = new JwksCache(logger)\n const revocationCache = new RevocationCache(validateMode, config.apiKey, logger)\n const deduplicator = new RefreshDeduplicator(logger)\n\n this.otp = new OtpClient(config.apiKey, store, logger)\n this.session = new SessionClient(\n config.apiKey,\n jwksCache,\n revocationCache,\n deduplicator,\n store,\n logger\n )\n this.identity = new IdentityClient(config.apiKey, logger)\n }\n\n // Only affects the built-in ConsoleLogger. Has no effect if a custom logger was provided.\n setLogLevel(level: LogLevel): void {\n this.consoleLogger.setLevel(level)\n }\n}\n"],"mappings":"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","names":["require","jwt","import_jsonwebtoken","jwt","err","crypto"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
2
|
|
|
3
|
-
type MiniMothErrorCode = 'INVALID_ACCESS_TOKEN' | 'SESSION_EXPIRED' | 'INVALID_OTP' | 'OTP_NOT_FOUND' | 'OTP_RATE_LIMITED' | 'VERIFY_RATE_LIMITED' | 'INSUFFICIENT_BALANCE' | 'NETWORK_ERROR' | 'INVALID_PHONE' | 'UNKNOWN_ERROR';
|
|
3
|
+
type MiniMothErrorCode = 'INVALID_ACCESS_TOKEN' | 'SESSION_EXPIRED' | 'INVALID_OTP' | 'OTP_NOT_FOUND' | 'OTP_RATE_LIMITED' | 'VERIFY_RATE_LIMITED' | 'INSUFFICIENT_BALANCE' | 'NETWORK_ERROR' | 'INVALID_PHONE' | 'IDENTITY_NOT_FOUND' | 'IDENTITY_DELETE_DISABLED' | 'IDENTITY_LOOKUP_DISABLED' | 'UNKNOWN_ERROR';
|
|
4
4
|
declare class MiniMothError extends Error {
|
|
5
5
|
readonly code: MiniMothErrorCode;
|
|
6
6
|
readonly statusCode: number;
|
|
@@ -28,6 +28,7 @@ type VerifyResult = {
|
|
|
28
28
|
accessToken: string;
|
|
29
29
|
refreshToken: string;
|
|
30
30
|
sessionId: string;
|
|
31
|
+
identityId?: string;
|
|
31
32
|
} | {
|
|
32
33
|
valid: false;
|
|
33
34
|
code: MiniMothErrorCode;
|
|
@@ -80,6 +81,7 @@ type Session = {
|
|
|
80
81
|
projectId: string;
|
|
81
82
|
sessionId: string;
|
|
82
83
|
expiresAt: Date;
|
|
84
|
+
identityId?: string;
|
|
83
85
|
newTokens?: {
|
|
84
86
|
accessToken: string;
|
|
85
87
|
refreshToken: string;
|
|
@@ -92,6 +94,16 @@ type AccessTokenPayload = {
|
|
|
92
94
|
jti: string;
|
|
93
95
|
iat: number;
|
|
94
96
|
exp: number;
|
|
97
|
+
identity_id?: string;
|
|
98
|
+
};
|
|
99
|
+
type IdentityFactor = {
|
|
100
|
+
type: string;
|
|
101
|
+
value: string;
|
|
102
|
+
};
|
|
103
|
+
type Identity = {
|
|
104
|
+
id: string;
|
|
105
|
+
createdAt: Date;
|
|
106
|
+
factors: IdentityFactor[];
|
|
95
107
|
};
|
|
96
108
|
|
|
97
109
|
declare class RevocationCache {
|
|
@@ -140,13 +152,25 @@ declare class SessionClient {
|
|
|
140
152
|
}): Promise<void>;
|
|
141
153
|
}
|
|
142
154
|
|
|
155
|
+
declare class IdentityClient {
|
|
156
|
+
private readonly apiKey;
|
|
157
|
+
private readonly logger;
|
|
158
|
+
constructor(apiKey: string, logger: MiniMothLogger);
|
|
159
|
+
get(identityId: string): Promise<Identity>;
|
|
160
|
+
getByPhone(phone: string): Promise<Identity>;
|
|
161
|
+
delete(identityId: string): Promise<{
|
|
162
|
+
deleted: true;
|
|
163
|
+
}>;
|
|
164
|
+
}
|
|
165
|
+
|
|
143
166
|
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
144
167
|
declare class MiniMoth {
|
|
145
168
|
readonly otp: OtpClient;
|
|
146
169
|
readonly session: SessionClient;
|
|
170
|
+
readonly identity: IdentityClient;
|
|
147
171
|
private readonly consoleLogger;
|
|
148
172
|
constructor(config: MiniMothConfig);
|
|
149
173
|
setLogLevel(level: LogLevel): void;
|
|
150
174
|
}
|
|
151
175
|
|
|
152
|
-
export { type AccessTokenPayload, MiniMoth, type MiniMothConfig, MiniMothError, type MiniMothErrorCode, type MiniMothLogger, type MiniMothSessionStore, type Session, type ValidateMode };
|
|
176
|
+
export { type AccessTokenPayload, type Identity, type IdentityFactor, MiniMoth, type MiniMothConfig, MiniMothError, type MiniMothErrorCode, type MiniMothLogger, type MiniMothSessionStore, type Session, type ValidateMode };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
2
|
|
|
3
|
-
type MiniMothErrorCode = 'INVALID_ACCESS_TOKEN' | 'SESSION_EXPIRED' | 'INVALID_OTP' | 'OTP_NOT_FOUND' | 'OTP_RATE_LIMITED' | 'VERIFY_RATE_LIMITED' | 'INSUFFICIENT_BALANCE' | 'NETWORK_ERROR' | 'INVALID_PHONE' | 'UNKNOWN_ERROR';
|
|
3
|
+
type MiniMothErrorCode = 'INVALID_ACCESS_TOKEN' | 'SESSION_EXPIRED' | 'INVALID_OTP' | 'OTP_NOT_FOUND' | 'OTP_RATE_LIMITED' | 'VERIFY_RATE_LIMITED' | 'INSUFFICIENT_BALANCE' | 'NETWORK_ERROR' | 'INVALID_PHONE' | 'IDENTITY_NOT_FOUND' | 'IDENTITY_DELETE_DISABLED' | 'IDENTITY_LOOKUP_DISABLED' | 'UNKNOWN_ERROR';
|
|
4
4
|
declare class MiniMothError extends Error {
|
|
5
5
|
readonly code: MiniMothErrorCode;
|
|
6
6
|
readonly statusCode: number;
|
|
@@ -28,6 +28,7 @@ type VerifyResult = {
|
|
|
28
28
|
accessToken: string;
|
|
29
29
|
refreshToken: string;
|
|
30
30
|
sessionId: string;
|
|
31
|
+
identityId?: string;
|
|
31
32
|
} | {
|
|
32
33
|
valid: false;
|
|
33
34
|
code: MiniMothErrorCode;
|
|
@@ -80,6 +81,7 @@ type Session = {
|
|
|
80
81
|
projectId: string;
|
|
81
82
|
sessionId: string;
|
|
82
83
|
expiresAt: Date;
|
|
84
|
+
identityId?: string;
|
|
83
85
|
newTokens?: {
|
|
84
86
|
accessToken: string;
|
|
85
87
|
refreshToken: string;
|
|
@@ -92,6 +94,16 @@ type AccessTokenPayload = {
|
|
|
92
94
|
jti: string;
|
|
93
95
|
iat: number;
|
|
94
96
|
exp: number;
|
|
97
|
+
identity_id?: string;
|
|
98
|
+
};
|
|
99
|
+
type IdentityFactor = {
|
|
100
|
+
type: string;
|
|
101
|
+
value: string;
|
|
102
|
+
};
|
|
103
|
+
type Identity = {
|
|
104
|
+
id: string;
|
|
105
|
+
createdAt: Date;
|
|
106
|
+
factors: IdentityFactor[];
|
|
95
107
|
};
|
|
96
108
|
|
|
97
109
|
declare class RevocationCache {
|
|
@@ -140,13 +152,25 @@ declare class SessionClient {
|
|
|
140
152
|
}): Promise<void>;
|
|
141
153
|
}
|
|
142
154
|
|
|
155
|
+
declare class IdentityClient {
|
|
156
|
+
private readonly apiKey;
|
|
157
|
+
private readonly logger;
|
|
158
|
+
constructor(apiKey: string, logger: MiniMothLogger);
|
|
159
|
+
get(identityId: string): Promise<Identity>;
|
|
160
|
+
getByPhone(phone: string): Promise<Identity>;
|
|
161
|
+
delete(identityId: string): Promise<{
|
|
162
|
+
deleted: true;
|
|
163
|
+
}>;
|
|
164
|
+
}
|
|
165
|
+
|
|
143
166
|
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
144
167
|
declare class MiniMoth {
|
|
145
168
|
readonly otp: OtpClient;
|
|
146
169
|
readonly session: SessionClient;
|
|
170
|
+
readonly identity: IdentityClient;
|
|
147
171
|
private readonly consoleLogger;
|
|
148
172
|
constructor(config: MiniMothConfig);
|
|
149
173
|
setLogLevel(level: LogLevel): void;
|
|
150
174
|
}
|
|
151
175
|
|
|
152
|
-
export { type AccessTokenPayload, MiniMoth, type MiniMothConfig, MiniMothError, type MiniMothErrorCode, type MiniMothLogger, type MiniMothSessionStore, type Session, type ValidateMode };
|
|
176
|
+
export { type AccessTokenPayload, type Identity, type IdentityFactor, MiniMoth, type MiniMothConfig, MiniMothError, type MiniMothErrorCode, type MiniMothLogger, type MiniMothSessionStore, type Session, type ValidateMode };
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,10 @@ var BACKEND_CODE_MAP = {
|
|
|
28
28
|
OTP_RATE_LIMITED: "OTP_RATE_LIMITED",
|
|
29
29
|
VERIFY_RATE_LIMITED: "VERIFY_RATE_LIMITED",
|
|
30
30
|
INSUFFICIENT_BALANCE: "INSUFFICIENT_BALANCE",
|
|
31
|
-
INVALID_PHONE: "INVALID_PHONE"
|
|
31
|
+
INVALID_PHONE: "INVALID_PHONE",
|
|
32
|
+
IDENTITY_NOT_FOUND: "IDENTITY_NOT_FOUND",
|
|
33
|
+
IDENTITY_DELETE_DISABLED: "IDENTITY_DELETE_DISABLED",
|
|
34
|
+
IDENTITY_LOOKUP_DISABLED: "IDENTITY_LOOKUP_DISABLED"
|
|
32
35
|
};
|
|
33
36
|
async function handleResponse(response) {
|
|
34
37
|
if (response.ok) return response.json();
|
|
@@ -68,6 +71,35 @@ async function apiGet(path, apiKey) {
|
|
|
68
71
|
}
|
|
69
72
|
return handleResponse(response);
|
|
70
73
|
}
|
|
74
|
+
async function apiDelete(path, apiKey) {
|
|
75
|
+
let response;
|
|
76
|
+
try {
|
|
77
|
+
response = await fetch(`${BASE_URL}${path}`, {
|
|
78
|
+
method: "DELETE",
|
|
79
|
+
headers: {
|
|
80
|
+
"X-Api-Key": apiKey,
|
|
81
|
+
"User-Agent": USER_AGENT
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
} catch (err) {
|
|
85
|
+
throw new MiniMothError("NETWORK_ERROR", "Network request failed", 0, err);
|
|
86
|
+
}
|
|
87
|
+
return handleResponse(response);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/phone.ts
|
|
91
|
+
function normalizePhone(raw) {
|
|
92
|
+
if (!raw || typeof raw !== "string") {
|
|
93
|
+
throw new MiniMothError("INVALID_PHONE", "Phone number is required", 422);
|
|
94
|
+
}
|
|
95
|
+
if (/[\s-]/.test(raw)) {
|
|
96
|
+
throw new MiniMothError("INVALID_PHONE", "Phone number must not contain spaces or hyphens", 422);
|
|
97
|
+
}
|
|
98
|
+
let phone = raw;
|
|
99
|
+
if (phone.startsWith("+")) phone = phone.slice(1);
|
|
100
|
+
if (phone.length === 10) phone = "91" + phone;
|
|
101
|
+
return phone;
|
|
102
|
+
}
|
|
71
103
|
|
|
72
104
|
// src/otp/OtpClient.ts
|
|
73
105
|
var OtpClient = class {
|
|
@@ -120,7 +152,8 @@ var OtpClient = class {
|
|
|
120
152
|
valid: true,
|
|
121
153
|
accessToken: res.access_token,
|
|
122
154
|
refreshToken: res.refresh_token,
|
|
123
|
-
sessionId: payload.session_id
|
|
155
|
+
sessionId: payload.session_id,
|
|
156
|
+
...payload.identity_id ? { identityId: payload.identity_id } : {}
|
|
124
157
|
};
|
|
125
158
|
} catch (err) {
|
|
126
159
|
if (err instanceof MiniMothError) {
|
|
@@ -133,18 +166,6 @@ var OtpClient = class {
|
|
|
133
166
|
}
|
|
134
167
|
}
|
|
135
168
|
};
|
|
136
|
-
function normalizePhone(raw) {
|
|
137
|
-
if (!raw || typeof raw !== "string") {
|
|
138
|
-
throw new MiniMothError("INVALID_PHONE", "Phone number is required", 422);
|
|
139
|
-
}
|
|
140
|
-
if (/[\s-]/.test(raw)) {
|
|
141
|
-
throw new MiniMothError("INVALID_PHONE", "Phone number must not contain spaces or hyphens", 422);
|
|
142
|
-
}
|
|
143
|
-
let phone = raw;
|
|
144
|
-
if (phone.startsWith("+")) phone = phone.slice(1);
|
|
145
|
-
if (phone.length === 10) phone = "91" + phone;
|
|
146
|
-
return phone;
|
|
147
|
-
}
|
|
148
169
|
function validateOtp(otp) {
|
|
149
170
|
if (!otp || typeof otp !== "string") {
|
|
150
171
|
throw new MiniMothError("INVALID_OTP", "OTP is required", 422);
|
|
@@ -227,6 +248,7 @@ var SessionClient = class {
|
|
|
227
248
|
sessionId: payload.session_id,
|
|
228
249
|
expiresAt: new Date(payload.exp * 1e3)
|
|
229
250
|
};
|
|
251
|
+
if (payload.identity_id) session.identityId = payload.identity_id;
|
|
230
252
|
if (newTokens) session.newTokens = newTokens;
|
|
231
253
|
this.logger.info("session.validated", { sessionId: payload.session_id.slice(0, 8) });
|
|
232
254
|
return session;
|
|
@@ -295,6 +317,37 @@ var SessionClient = class {
|
|
|
295
317
|
}
|
|
296
318
|
};
|
|
297
319
|
|
|
320
|
+
// src/identity/IdentityClient.ts
|
|
321
|
+
var IdentityClient = class {
|
|
322
|
+
constructor(apiKey, logger) {
|
|
323
|
+
this.apiKey = apiKey;
|
|
324
|
+
this.logger = logger;
|
|
325
|
+
}
|
|
326
|
+
apiKey;
|
|
327
|
+
logger;
|
|
328
|
+
async get(identityId) {
|
|
329
|
+
const res = await apiGet(`/v1/identity/${encodeURIComponent(identityId)}`, this.apiKey);
|
|
330
|
+
return toIdentity(res);
|
|
331
|
+
}
|
|
332
|
+
async getByPhone(phone) {
|
|
333
|
+
const normalized = normalizePhone(phone);
|
|
334
|
+
const res = await apiGet(`/v1/identity?phone=${encodeURIComponent(normalized)}`, this.apiKey);
|
|
335
|
+
return toIdentity(res);
|
|
336
|
+
}
|
|
337
|
+
async delete(identityId) {
|
|
338
|
+
await apiDelete(`/v1/identity/${encodeURIComponent(identityId)}`, this.apiKey);
|
|
339
|
+
this.logger.info("identity.deleted", { identityId: identityId.slice(0, 8) });
|
|
340
|
+
return { deleted: true };
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
function toIdentity(res) {
|
|
344
|
+
return {
|
|
345
|
+
id: res.id,
|
|
346
|
+
createdAt: new Date(res.created_at),
|
|
347
|
+
factors: res.factors
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
298
351
|
// src/session/JwksCache.ts
|
|
299
352
|
import crypto from "crypto";
|
|
300
353
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -491,6 +544,7 @@ var ConsoleLogger = class {
|
|
|
491
544
|
var MiniMoth = class {
|
|
492
545
|
otp;
|
|
493
546
|
session;
|
|
547
|
+
identity;
|
|
494
548
|
consoleLogger;
|
|
495
549
|
constructor(config) {
|
|
496
550
|
this.consoleLogger = new ConsoleLogger(config.logLevel ?? "info");
|
|
@@ -509,6 +563,7 @@ var MiniMoth = class {
|
|
|
509
563
|
store,
|
|
510
564
|
logger
|
|
511
565
|
);
|
|
566
|
+
this.identity = new IdentityClient(config.apiKey, logger);
|
|
512
567
|
}
|
|
513
568
|
// Only affects the built-in ConsoleLogger. Has no effect if a custom logger was provided.
|
|
514
569
|
setLogLevel(level) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/otp/OtpClient.ts","../src/MiniMothError.ts","../src/http.ts","../src/session/SessionClient.ts","../src/session/JwksCache.ts","../src/session/RevocationCache.ts","../src/session/RefreshDeduplicator.ts","../src/store/DefaultSessionStore.ts","../src/logger/ConsoleLogger.ts","../src/MiniMoth.ts"],"sourcesContent":["import jwt from 'jsonwebtoken'\nimport { apiPost, apiGet } from '../http'\nimport { MiniMothError, type MiniMothErrorCode } from '../MiniMothError'\nimport type { MiniMothSessionStore } from '../store/MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { AccessTokenPayload } from '../types'\n\ntype VerifyResult =\n | { valid: true; accessToken: string; refreshToken: string; sessionId: string }\n | { valid: false; code: MiniMothErrorCode }\n\ntype OtpStatus = {\n otpId: string\n channel: string | null\n status: 'queued' | 'delivered' | 'failed'\n deliveredAt: string | null\n}\n\nexport class OtpClient {\n constructor(\n private readonly apiKey: string,\n private readonly store: MiniMothSessionStore,\n private readonly logger: MiniMothLogger\n ) {}\n\n async send(params: { phone: string }): Promise<{ otpId: string }> {\n const phone = normalizePhone(params.phone)\n const res = await apiPost<{ message: string; otp_id: string }>('/v1/otp/send', this.apiKey, { phone })\n this.logger.info('otp.sent', { phone: maskPhone(phone) })\n return { otpId: res.otp_id }\n }\n\n async status(otpId: string): Promise<OtpStatus> {\n const res = await apiGet<{\n otp_id: string\n channel: string | null\n status: 'queued' | 'delivered' | 'failed'\n delivered_at: string | null\n }>(`/v1/otp/status/${encodeURIComponent(otpId)}`, this.apiKey)\n return {\n otpId: res.otp_id,\n channel: res.channel,\n status: res.status,\n deliveredAt: res.delivered_at,\n }\n }\n\n async verify(params: { phone: string; otp: string }): Promise<VerifyResult> {\n const phone = normalizePhone(params.phone)\n validateOtp(params.otp)\n\n try {\n const res = await apiPost<{ access_token: string; refresh_token: string; expires_at: string }>(\n '/v1/otp/verify',\n this.apiKey,\n { phone, code: params.otp }\n )\n\n const payload = jwt.decode(res.access_token) as AccessTokenPayload | null\n if (!payload?.session_id) {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Could not decode session_id from access token', 0)\n }\n\n try {\n await this.store.setTokens(payload.session_id, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch {\n this.logger.error('otp.store.setTokens.failed', { sessionId: payload.session_id.slice(0, 8) })\n }\n\n this.logger.info('otp.verified', { sessionId: payload.session_id.slice(0, 8) })\n\n return {\n valid: true,\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n sessionId: payload.session_id,\n }\n } catch (err) {\n if (err instanceof MiniMothError) {\n if (\n err.code === 'INVALID_OTP' ||\n err.code === 'OTP_NOT_FOUND' ||\n err.code === 'INVALID_PHONE' ||\n err.code === 'VERIFY_RATE_LIMITED'\n ) {\n this.logger.debug('otp.verify.failed', { code: err.code })\n return { valid: false, code: err.code }\n }\n }\n throw err\n }\n }\n}\n\n// Normalizes to 12-digit canonical Indian format (91XXXXXXXXXX).\n// Rejects if spaces or hyphens are present.\nfunction normalizePhone(raw: string): string {\n if (!raw || typeof raw !== 'string') {\n throw new MiniMothError('INVALID_PHONE', 'Phone number is required', 422)\n }\n if (/[\\s-]/.test(raw)) {\n throw new MiniMothError('INVALID_PHONE', 'Phone number must not contain spaces or hyphens', 422)\n }\n let phone = raw\n if (phone.startsWith('+')) phone = phone.slice(1)\n // 10-digit subscriber number — prepend country code\n if (phone.length === 10) phone = '91' + phone\n return phone\n}\n\nfunction validateOtp(otp: string): void {\n if (!otp || typeof otp !== 'string') {\n throw new MiniMothError('INVALID_OTP', 'OTP is required', 422)\n }\n}\n\nexport function maskPhone(phone: string): string {\n if (phone.length <= 4) return '****'\n return phone.slice(0, 4) + '*'.repeat(Math.max(phone.length - 6, 1)) + phone.slice(-2)\n}\n","export type MiniMothErrorCode =\n | 'INVALID_ACCESS_TOKEN'\n | 'SESSION_EXPIRED'\n | 'INVALID_OTP'\n | 'OTP_NOT_FOUND'\n | 'OTP_RATE_LIMITED'\n | 'VERIFY_RATE_LIMITED'\n | 'INSUFFICIENT_BALANCE'\n | 'NETWORK_ERROR'\n | 'INVALID_PHONE'\n | 'UNKNOWN_ERROR'\n\nexport class MiniMothError extends Error {\n readonly code: MiniMothErrorCode\n readonly statusCode: number\n\n constructor(code: MiniMothErrorCode, message: string, statusCode: number, cause?: unknown) {\n super(message, cause !== undefined ? { cause } : undefined)\n this.name = 'MiniMothError'\n this.code = code\n this.statusCode = statusCode\n // Restore prototype chain for instanceof checks across module boundaries\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n","import { MiniMothError, type MiniMothErrorCode } from './MiniMothError'\nimport { createRequire } from 'module'\n\nconst require = createRequire(import.meta.url)\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\nconst pkg = require('../package.json') as { version: string }\n\nconst BASE_URL = 'https://api.minimoth.dev'\nconst USER_AGENT = `minimoth-sdk-node/${pkg.version}`\n\nconst BACKEND_CODE_MAP: Record<string, MiniMothErrorCode> = {\n INVALID_ACCESS_TOKEN: 'INVALID_ACCESS_TOKEN',\n SESSION_EXPIRED: 'SESSION_EXPIRED',\n INVALID_OTP: 'INVALID_OTP',\n OTP_NOT_FOUND: 'OTP_NOT_FOUND',\n OTP_RATE_LIMITED: 'OTP_RATE_LIMITED',\n VERIFY_RATE_LIMITED: 'VERIFY_RATE_LIMITED',\n INSUFFICIENT_BALANCE: 'INSUFFICIENT_BALANCE',\n INVALID_PHONE: 'INVALID_PHONE',\n}\n\nasync function handleResponse<T>(response: Response): Promise<T> {\n if (response.ok) return response.json() as Promise<T>\n\n let body: { code?: string; error?: string } = {}\n try { body = await response.json() as { code?: string; error?: string } } catch {}\n\n const sdkCode: MiniMothErrorCode = BACKEND_CODE_MAP[body.code ?? ''] ?? 'UNKNOWN_ERROR'\n throw new MiniMothError(sdkCode, body.error ?? 'Unknown error', response.status)\n}\n\nexport async function apiPost<T>(\n path: string,\n apiKey: string,\n body: Record<string, unknown>\n): Promise<T> {\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Api-Key': apiKey,\n 'User-Agent': USER_AGENT,\n },\n body: JSON.stringify(body),\n })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n\nexport async function apiGet<T>(path: string, apiKey?: string): Promise<T> {\n const headers: Record<string, string> = { 'User-Agent': USER_AGENT }\n if (apiKey) headers['X-Api-Key'] = apiKey\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, { headers })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n","import jwt from 'jsonwebtoken'\nimport { apiPost } from '../http'\nimport { MiniMothError, type MiniMothErrorCode } from '../MiniMothError'\nimport type { JwksCache } from './JwksCache'\nimport type { RevocationCache } from './RevocationCache'\nimport type { RefreshDeduplicator } from './RefreshDeduplicator'\nimport type { MiniMothSessionStore } from '../store/MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { Session, AccessTokenPayload } from '../types'\n\ntype Tokens = { accessToken: string; refreshToken: string }\n\ntype SafeValidateResult =\n | { valid: true; session: Session }\n | { valid: false; code: MiniMothErrorCode }\n\nexport class SessionClient {\n constructor(\n private readonly apiKey: string,\n private readonly jwksCache: JwksCache,\n private readonly revocationCache: RevocationCache,\n private readonly deduplicator: RefreshDeduplicator,\n private readonly store: MiniMothSessionStore,\n private readonly logger: MiniMothLogger\n ) {}\n\n async validate(accessToken: string): Promise<Session> {\n const decoded = jwt.decode(accessToken, { complete: true })\n if (!decoded || typeof decoded === 'string') {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is malformed', 401)\n }\n\n const kid = (decoded.header as unknown as Record<string, string>)['kid']\n if (!kid) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is missing kid header', 401)\n\n const publicKey = await this.jwksCache.getKey(kid)\n\n let currentToken = accessToken\n let newTokens: Tokens | undefined\n\n try {\n jwt.verify(accessToken, publicKey, { algorithms: ['RS256'] })\n } catch (err) {\n if (err instanceof jwt.TokenExpiredError) {\n const expiredPayload = decoded.payload as AccessTokenPayload\n const sessionId = expiredPayload?.session_id\n if (!sessionId) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is invalid', 401)\n\n newTokens = await this.deduplicator.getOrRun(sessionId, async () => {\n const refreshToken = await this.store.getRefreshToken(sessionId)\n if (!refreshToken) {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Access token expired and no refresh token available', 401)\n }\n\n this.logger.info('session.auto_refresh', { sessionId: sessionId.slice(0, 8) })\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: refreshToken }\n )\n\n try {\n await this.store.setTokens(sessionId, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: sessionId.slice(0, 8) })\n }\n\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n })\n\n currentToken = newTokens.accessToken\n\n // Verify the new token\n const newDecoded = jwt.decode(currentToken, { complete: true })\n const newKid = (newDecoded?.header as Record<string, string> | undefined)?.['kid']\n const newKey = newKid ? await this.jwksCache.getKey(newKid) : publicKey\n jwt.verify(currentToken, newKey, { algorithms: ['RS256'] })\n } else {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token signature is invalid', 401)\n }\n }\n\n const payload = jwt.decode(currentToken) as AccessTokenPayload\n const isValid = await this.revocationCache.check(payload.jti, currentToken)\n if (!isValid) throw new MiniMothError('SESSION_EXPIRED', 'Session has been revoked', 401)\n\n const session: Session = {\n projectId: payload.project_id,\n sessionId: payload.session_id,\n expiresAt: new Date(payload.exp * 1000),\n }\n if (newTokens) session.newTokens = newTokens\n\n this.logger.info('session.validated', { sessionId: payload.session_id.slice(0, 8) })\n return session\n }\n\n async safeValidate(accessToken: string): Promise<SafeValidateResult> {\n try {\n const session = await this.validate(accessToken)\n return { valid: true, session }\n } catch (err) {\n if (err instanceof MiniMothError) return { valid: false, code: err.code }\n throw err\n }\n }\n\n async refresh(refreshToken: string): Promise<Tokens> {\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: refreshToken }\n )\n\n // Update store if session_id is decodable from new token\n const payload = jwt.decode(res.access_token) as AccessTokenPayload | null\n if (payload?.session_id) {\n try {\n await this.store.setTokens(payload.session_id, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: payload.session_id.slice(0, 8) })\n }\n }\n\n this.logger.info('session.refreshed')\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n }\n\n async logout(params: { accessToken: string; refreshToken: string }): Promise<void> {\n const payload = jwt.decode(params.accessToken) as AccessTokenPayload | null\n const sessionId = payload?.session_id ?? null\n\n if (!sessionId) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Cannot decode token', 401)\n\n let currentAccessToken = params.accessToken\n\n // If token is expired, refresh before logout — deduplicated to prevent concurrent refresh races\n if (payload && payload.exp < Math.floor(Date.now() / 1000)) {\n const newTokens = await this.deduplicator.getOrRun(sessionId, async () => {\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: params.refreshToken }\n )\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n })\n currentAccessToken = newTokens.accessToken\n try {\n await this.store.setTokens(sessionId, newTokens)\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: sessionId.slice(0, 8) })\n }\n }\n\n await apiPost<{ message: string }>(\n '/v1/session/logout',\n this.apiKey,\n { access_token: currentAccessToken }\n )\n\n try {\n await this.store.deleteSession(sessionId)\n } catch (err) {\n this.logger.error('session.store.deleteSession.failed', { sessionId: sessionId.slice(0, 8) })\n }\n this.logger.info('session.logged_out', { sessionId: sessionId.slice(0, 8) })\n }\n}\n","import crypto from 'crypto'\nimport { apiGet } from '../http'\nimport { MiniMothError } from '../MiniMothError'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\n\nconst CACHE_TTL_MS = 60 * 60 * 1000 // 1 hour\n\ntype JwkEntry = Record<string, string>\n\nexport class JwksCache {\n private keyMap = new Map<string, crypto.KeyObject>()\n private fetchedAt = 0\n private fetching: Promise<void> | null = null\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n async getKey(kid: string): Promise<crypto.KeyObject> {\n if (this.keyMap.size === 0 || Date.now() - this.fetchedAt > CACHE_TTL_MS) {\n await this.fetch()\n }\n\n let key = this.keyMap.get(kid)\n if (!key) {\n this.logger.debug('jwks.unknown_kid', { kid })\n await this.fetch()\n key = this.keyMap.get(kid)\n }\n\n if (!key) throw new MiniMothError('INVALID_ACCESS_TOKEN', `No public key found for kid: ${kid}`, 401)\n return key\n }\n\n private fetch(): Promise<void> {\n if (this.fetching) return this.fetching\n this.fetching = this.doFetch().finally(() => { this.fetching = null })\n return this.fetching\n }\n\n private async doFetch(): Promise<void> {\n this.logger.debug('jwks.fetch')\n const data = await apiGet<{ keys: JwkEntry[] }>('/.well-known/jwks.json')\n const newMap = new Map<string, crypto.KeyObject>()\n for (const jwk of data.keys) {\n if (jwk['kid'] && jwk['kty'] === 'RSA') {\n const key = crypto.createPublicKey({ key: jwk as unknown as crypto.JsonWebKey, format: 'jwk' })\n newMap.set(jwk['kid'], key)\n }\n }\n this.keyMap = newMap\n this.fetchedAt = Date.now()\n this.logger.debug('jwks.updated', { keyCount: newMap.size })\n }\n}\n","import { apiPost } from '../http'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { ValidateMode } from '../types'\n\nconst MODE_TTL_MS: Partial<Record<ValidateMode, number>> = {\n recheck_1m: 60_000,\n recheck_3m: 180_000,\n}\n\nconst EVICTION_TTL_MS = 5 * 60 * 1000 // JWT max lifetime\nconst CLEANUP_WINDOW_MS = 5 * 60 * 1000\n\ntype Entry = { checkedAt: number }\n\nexport class RevocationCache {\n private readonly cache = new Map<string, Entry>()\n private lastCleanedAt = 0\n\n constructor(\n private readonly mode: ValidateMode,\n private readonly apiKey: string,\n private readonly logger: MiniMothLogger\n ) {}\n\n async check(jti: string, accessToken: string): Promise<boolean> {\n if (this.mode === 'instant') return true\n\n if (this.mode !== 'strict') this.maybeCleanup()\n\n const ttl = MODE_TTL_MS[this.mode] ?? 0\n if (ttl > 0) {\n const entry = this.cache.get(jti)\n if (entry && Date.now() - entry.checkedAt < ttl) {\n this.logger.debug('revocation.cache.hit', { jti: jti.slice(0, 8) })\n return true\n }\n }\n\n try {\n const result = await apiPost<{ valid: boolean }>(\n '/v1/session/validate',\n this.apiKey,\n { access_token: accessToken }\n )\n\n if (result.valid && ttl > 0) {\n this.cache.set(jti, { checkedAt: Date.now() })\n }\n\n return result.valid\n } catch (err) {\n if (this.mode === 'strict') throw err\n\n // recheck_*m: fail open\n this.logger.warn('revocation.check.failed_open', {\n jti: jti.slice(0, 8),\n error: err instanceof Error ? err.message : 'unknown',\n })\n return true\n }\n }\n\n private maybeCleanup(): void {\n const now = Date.now()\n if (now - this.lastCleanedAt < CLEANUP_WINDOW_MS) return\n this.lastCleanedAt = now // set before iteration to prevent concurrent double-clean\n for (const [jti, entry] of this.cache) {\n if (now - entry.checkedAt > EVICTION_TTL_MS) {\n this.cache.delete(jti)\n }\n }\n }\n}\n","import { MiniMothLogger } from '../logger/MiniMothLogger'\n\ntype Tokens = { accessToken: string; refreshToken: string }\n\nexport class RefreshDeduplicator {\n private readonly inflight = new Map<string, Promise<unknown>>()\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n getOrRun<T>(sessionId: string, fn: () => Promise<T>): Promise<T> {\n const existing = this.inflight.get(sessionId)\n if (existing) {\n this.logger.debug('refresh dedup hit', { key: sessionId })\n return existing as Promise<T>\n }\n\n const promise = fn().finally(() => {\n this.inflight.delete(sessionId)\n })\n\n this.inflight.set(sessionId, promise)\n return promise\n }\n}\n","import type { MiniMothSessionStore } from './MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\n\ntype Entry = { accessToken: string; refreshToken: string }\n\nexport class DefaultSessionStore implements MiniMothSessionStore {\n private readonly map = new Map<string, Entry>()\n private warnedProduction = false\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n private maybeWarn(): void {\n if (process.env['NODE_ENV'] === 'production' && !this.warnedProduction) {\n this.warnedProduction = true\n this.logger.warn('using default in-memory session store — not suitable for multi-replica deployments')\n }\n }\n\n async getRefreshToken(sessionId: string): Promise<string | null> {\n this.maybeWarn()\n return this.map.get(sessionId)?.refreshToken ?? null\n }\n\n async setTokens(sessionId: string, tokens: { accessToken: string; refreshToken: string }): Promise<void> {\n this.maybeWarn()\n this.map.set(sessionId, tokens)\n }\n\n async deleteSession(sessionId: string): Promise<void> {\n this.map.delete(sessionId)\n }\n}\n","import type { MiniMothLogger } from './MiniMothLogger'\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0, info: 1, warn: 2, error: 3, silent: 4,\n}\n\nexport class ConsoleLogger implements MiniMothLogger {\n private level: LogLevel\n\n constructor(level: LogLevel = 'info') {\n this.level = level\n }\n\n setLevel(level: LogLevel): void {\n this.level = level\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[this.level]\n }\n\n private format(msg: string, meta?: Record<string, unknown>): string {\n if (!meta || Object.keys(meta).length === 0) return `[minimoth] ${msg}`\n return `[minimoth] ${msg} ${JSON.stringify(meta)}`\n }\n\n debug(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('debug')) console.debug(this.format(msg, meta))\n }\n\n info(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('info')) console.info(this.format(msg, meta))\n }\n\n warn(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('warn')) console.warn(this.format(msg, meta))\n }\n\n error(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('error')) console.error(this.format(msg, meta))\n }\n}\n","import { OtpClient } from './otp/OtpClient'\nimport { SessionClient } from './session/SessionClient'\nimport { JwksCache } from './session/JwksCache'\nimport { RevocationCache } from './session/RevocationCache'\nimport { RefreshDeduplicator } from './session/RefreshDeduplicator'\nimport { DefaultSessionStore } from './store/DefaultSessionStore'\nimport { ConsoleLogger } from './logger/ConsoleLogger'\nimport type { MiniMothConfig } from './types'\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nexport class MiniMoth {\n readonly otp: OtpClient\n readonly session: SessionClient\n private readonly consoleLogger: ConsoleLogger\n\n constructor(config: MiniMothConfig) {\n this.consoleLogger = new ConsoleLogger(config.logLevel ?? 'info')\n const logger = config.logger ?? this.consoleLogger\n\n const store = config.session?.store ?? new DefaultSessionStore(logger)\n const validateMode = config.session?.validateMode ?? 'instant'\n\n const jwksCache = new JwksCache(logger)\n const revocationCache = new RevocationCache(validateMode, config.apiKey, logger)\n const deduplicator = new RefreshDeduplicator(logger)\n\n this.otp = new OtpClient(config.apiKey, store, logger)\n this.session = new SessionClient(\n config.apiKey,\n jwksCache,\n revocationCache,\n deduplicator,\n store,\n logger\n )\n }\n\n // Only affects the built-in ConsoleLogger. Has no effect if a custom logger was provided.\n setLogLevel(level: LogLevel): void {\n this.consoleLogger.setLevel(level)\n }\n}\n"],"mappings":";AAAA,OAAO,SAAS;;;ACYT,IAAM,gBAAN,cAA4B,MAAM;AAAA,EAC9B;AAAA,EACA;AAAA,EAET,YAAY,MAAyB,SAAiB,YAAoB,OAAiB;AACzF,UAAM,SAAS,UAAU,SAAY,EAAE,MAAM,IAAI,MAAS;AAC1D,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,aAAa;AAElB,WAAO,eAAe,MAAM,WAAW,SAAS;AAAA,EAClD;AACF;;;ACvBA,SAAS,qBAAqB;AAE9B,IAAMA,WAAU,cAAc,YAAY,GAAG;AAE7C,IAAM,MAAMA,SAAQ,iBAAiB;AAErC,IAAM,WAAW;AACjB,IAAM,aAAa,qBAAqB,IAAI,OAAO;AAEnD,IAAM,mBAAsD;AAAA,EAC1D,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,eAAe;AACjB;AAEA,eAAe,eAAkB,UAAgC;AAC/D,MAAI,SAAS,GAAI,QAAO,SAAS,KAAK;AAEtC,MAAI,OAA0C,CAAC;AAC/C,MAAI;AAAE,WAAO,MAAM,SAAS,KAAK;AAAA,EAAuC,QAAQ;AAAA,EAAC;AAEjF,QAAM,UAA6B,iBAAiB,KAAK,QAAQ,EAAE,KAAK;AACxE,QAAM,IAAI,cAAc,SAAS,KAAK,SAAS,iBAAiB,SAAS,MAAM;AACjF;AAEA,eAAsB,QACpB,MACA,QACA,MACY;AACZ,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,GAAG,QAAQ,GAAG,IAAI,IAAI;AAAA,MAC3C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,cAAc;AAAA,MAChB;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,UAAM,IAAI,cAAc,iBAAiB,0BAA0B,GAAG,GAAG;AAAA,EAC3E;AACA,SAAO,eAAkB,QAAQ;AACnC;AAEA,eAAsB,OAAU,MAAc,QAA6B;AACzE,QAAM,UAAkC,EAAE,cAAc,WAAW;AACnE,MAAI,OAAQ,SAAQ,WAAW,IAAI;AACnC,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,GAAG,QAAQ,GAAG,IAAI,IAAI,EAAE,QAAQ,CAAC;AAAA,EAC1D,SAAS,KAAK;AACZ,UAAM,IAAI,cAAc,iBAAiB,0BAA0B,GAAG,GAAG;AAAA,EAC3E;AACA,SAAO,eAAkB,QAAQ;AACnC;;;AF7CO,IAAM,YAAN,MAAgB;AAAA,EACrB,YACmB,QACA,OACA,QACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EAGnB,MAAM,KAAK,QAAuD;AAChE,UAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,UAAM,MAAM,MAAM,QAA6C,gBAAgB,KAAK,QAAQ,EAAE,MAAM,CAAC;AACrG,SAAK,OAAO,KAAK,YAAY,EAAE,OAAO,UAAU,KAAK,EAAE,CAAC;AACxD,WAAO,EAAE,OAAO,IAAI,OAAO;AAAA,EAC7B;AAAA,EAEA,MAAM,OAAO,OAAmC;AAC9C,UAAM,MAAM,MAAM,OAKf,kBAAkB,mBAAmB,KAAK,CAAC,IAAI,KAAK,MAAM;AAC7D,WAAO;AAAA,MACL,OAAO,IAAI;AAAA,MACX,SAAS,IAAI;AAAA,MACb,QAAQ,IAAI;AAAA,MACZ,aAAa,IAAI;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,QAA+D;AAC1E,UAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,gBAAY,OAAO,GAAG;AAEtB,QAAI;AACF,YAAM,MAAM,MAAM;AAAA,QAChB;AAAA,QACA,KAAK;AAAA,QACL,EAAE,OAAO,MAAM,OAAO,IAAI;AAAA,MAC5B;AAEA,YAAM,UAAU,IAAI,OAAO,IAAI,YAAY;AAC3C,UAAI,CAAC,SAAS,YAAY;AACxB,cAAM,IAAI,cAAc,wBAAwB,iDAAiD,CAAC;AAAA,MACpG;AAEA,UAAI;AACF,cAAM,KAAK,MAAM,UAAU,QAAQ,YAAY;AAAA,UAC7C,aAAa,IAAI;AAAA,UACjB,cAAc,IAAI;AAAA,QACpB,CAAC;AAAA,MACH,QAAQ;AACN,aAAK,OAAO,MAAM,8BAA8B,EAAE,WAAW,QAAQ,WAAW,MAAM,GAAG,CAAC,EAAE,CAAC;AAAA,MAC/F;AAEA,WAAK,OAAO,KAAK,gBAAgB,EAAE,WAAW,QAAQ,WAAW,MAAM,GAAG,CAAC,EAAE,CAAC;AAE9E,aAAO;AAAA,QACL,OAAO;AAAA,QACP,aAAa,IAAI;AAAA,QACjB,cAAc,IAAI;AAAA,QAClB,WAAW,QAAQ;AAAA,MACrB;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,eAAe;AAChC,YACE,IAAI,SAAS,iBACb,IAAI,SAAS,mBACb,IAAI,SAAS,mBACb,IAAI,SAAS,uBACb;AACA,eAAK,OAAO,MAAM,qBAAqB,EAAE,MAAM,IAAI,KAAK,CAAC;AACzD,iBAAO,EAAE,OAAO,OAAO,MAAM,IAAI,KAAK;AAAA,QACxC;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAIA,SAAS,eAAe,KAAqB;AAC3C,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,UAAM,IAAI,cAAc,iBAAiB,4BAA4B,GAAG;AAAA,EAC1E;AACA,MAAI,QAAQ,KAAK,GAAG,GAAG;AACrB,UAAM,IAAI,cAAc,iBAAiB,mDAAmD,GAAG;AAAA,EACjG;AACA,MAAI,QAAQ;AACZ,MAAI,MAAM,WAAW,GAAG,EAAG,SAAQ,MAAM,MAAM,CAAC;AAEhD,MAAI,MAAM,WAAW,GAAI,SAAQ,OAAO;AACxC,SAAO;AACT;AAEA,SAAS,YAAY,KAAmB;AACtC,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,UAAM,IAAI,cAAc,eAAe,mBAAmB,GAAG;AAAA,EAC/D;AACF;AAEO,SAAS,UAAU,OAAuB;AAC/C,MAAI,MAAM,UAAU,EAAG,QAAO;AAC9B,SAAO,MAAM,MAAM,GAAG,CAAC,IAAI,IAAI,OAAO,KAAK,IAAI,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,MAAM,MAAM,EAAE;AACvF;;;AG1HA,OAAOC,UAAS;AAgBT,IAAM,gBAAN,MAAoB;AAAA,EACzB,YACmB,QACA,WACA,iBACA,cACA,OACA,QACjB;AANiB;AACA;AACA;AACA;AACA;AACA;AAAA,EAChB;AAAA,EANgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGnB,MAAM,SAAS,aAAuC;AACpD,UAAM,UAAUC,KAAI,OAAO,aAAa,EAAE,UAAU,KAAK,CAAC;AAC1D,QAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,YAAM,IAAI,cAAc,wBAAwB,sBAAsB,GAAG;AAAA,IAC3E;AAEA,UAAM,MAAO,QAAQ,OAA6C,KAAK;AACvE,QAAI,CAAC,IAAK,OAAM,IAAI,cAAc,wBAAwB,+BAA+B,GAAG;AAE5F,UAAM,YAAY,MAAM,KAAK,UAAU,OAAO,GAAG;AAEjD,QAAI,eAAe;AACnB,QAAI;AAEJ,QAAI;AACF,MAAAA,KAAI,OAAO,aAAa,WAAW,EAAE,YAAY,CAAC,OAAO,EAAE,CAAC;AAAA,IAC9D,SAAS,KAAK;AACZ,UAAI,eAAeA,KAAI,mBAAmB;AACxC,cAAM,iBAAiB,QAAQ;AAC/B,cAAM,YAAY,gBAAgB;AAClC,YAAI,CAAC,UAAW,OAAM,IAAI,cAAc,wBAAwB,oBAAoB,GAAG;AAEvF,oBAAY,MAAM,KAAK,aAAa,SAAS,WAAW,YAAY;AAClE,gBAAM,eAAe,MAAM,KAAK,MAAM,gBAAgB,SAAS;AAC/D,cAAI,CAAC,cAAc;AACjB,kBAAM,IAAI,cAAc,wBAAwB,uDAAuD,GAAG;AAAA,UAC5G;AAEA,eAAK,OAAO,KAAK,wBAAwB,EAAE,WAAW,UAAU,MAAM,GAAG,CAAC,EAAE,CAAC;AAC7E,gBAAM,MAAM,MAAM;AAAA,YAChB;AAAA,YACA,KAAK;AAAA,YACL,EAAE,eAAe,aAAa;AAAA,UAChC;AAEA,cAAI;AACF,kBAAM,KAAK,MAAM,UAAU,WAAW;AAAA,cACpC,aAAa,IAAI;AAAA,cACjB,cAAc,IAAI;AAAA,YACpB,CAAC;AAAA,UACH,SAASC,MAAK;AACZ,iBAAK,OAAO,MAAM,kCAAkC,EAAE,WAAW,UAAU,MAAM,GAAG,CAAC,EAAE,CAAC;AAAA,UAC1F;AAEA,iBAAO,EAAE,aAAa,IAAI,cAAc,cAAc,IAAI,cAAc;AAAA,QAC1E,CAAC;AAED,uBAAe,UAAU;AAGzB,cAAM,aAAaD,KAAI,OAAO,cAAc,EAAE,UAAU,KAAK,CAAC;AAC9D,cAAM,SAAU,YAAY,SAAgD,KAAK;AACjF,cAAM,SAAS,SAAS,MAAM,KAAK,UAAU,OAAO,MAAM,IAAI;AAC9D,QAAAA,KAAI,OAAO,cAAc,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,CAAC;AAAA,MAC5D,OAAO;AACL,cAAM,IAAI,cAAc,wBAAwB,8BAA8B,GAAG;AAAA,MACnF;AAAA,IACF;AAEA,UAAM,UAAUA,KAAI,OAAO,YAAY;AACvC,UAAM,UAAU,MAAM,KAAK,gBAAgB,MAAM,QAAQ,KAAK,YAAY;AAC1E,QAAI,CAAC,QAAS,OAAM,IAAI,cAAc,mBAAmB,4BAA4B,GAAG;AAExF,UAAM,UAAmB;AAAA,MACvB,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,MACnB,WAAW,IAAI,KAAK,QAAQ,MAAM,GAAI;AAAA,IACxC;AACA,QAAI,UAAW,SAAQ,YAAY;AAEnC,SAAK,OAAO,KAAK,qBAAqB,EAAE,WAAW,QAAQ,WAAW,MAAM,GAAG,CAAC,EAAE,CAAC;AACnF,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,aAAkD;AACnE,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,SAAS,WAAW;AAC/C,aAAO,EAAE,OAAO,MAAM,QAAQ;AAAA,IAChC,SAAS,KAAK;AACZ,UAAI,eAAe,cAAe,QAAO,EAAE,OAAO,OAAO,MAAM,IAAI,KAAK;AACxE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,cAAuC;AACnD,UAAM,MAAM,MAAM;AAAA,MAChB;AAAA,MACA,KAAK;AAAA,MACL,EAAE,eAAe,aAAa;AAAA,IAChC;AAGA,UAAM,UAAUA,KAAI,OAAO,IAAI,YAAY;AAC3C,QAAI,SAAS,YAAY;AACvB,UAAI;AACF,cAAM,KAAK,MAAM,UAAU,QAAQ,YAAY;AAAA,UAC7C,aAAa,IAAI;AAAA,UACjB,cAAc,IAAI;AAAA,QACpB,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,aAAK,OAAO,MAAM,kCAAkC,EAAE,WAAW,QAAQ,WAAW,MAAM,GAAG,CAAC,EAAE,CAAC;AAAA,MACnG;AAAA,IACF;AAEA,SAAK,OAAO,KAAK,mBAAmB;AACpC,WAAO,EAAE,aAAa,IAAI,cAAc,cAAc,IAAI,cAAc;AAAA,EAC1E;AAAA,EAEA,MAAM,OAAO,QAAsE;AACjF,UAAM,UAAUA,KAAI,OAAO,OAAO,WAAW;AAC7C,UAAM,YAAY,SAAS,cAAc;AAEzC,QAAI,CAAC,UAAW,OAAM,IAAI,cAAc,wBAAwB,uBAAuB,GAAG;AAE1F,QAAI,qBAAqB,OAAO;AAGhC,QAAI,WAAW,QAAQ,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,GAAG;AAC1D,YAAM,YAAY,MAAM,KAAK,aAAa,SAAS,WAAW,YAAY;AACxE,cAAM,MAAM,MAAM;AAAA,UAChB;AAAA,UACA,KAAK;AAAA,UACL,EAAE,eAAe,OAAO,aAAa;AAAA,QACvC;AACA,eAAO,EAAE,aAAa,IAAI,cAAc,cAAc,IAAI,cAAc;AAAA,MAC1E,CAAC;AACD,2BAAqB,UAAU;AAC/B,UAAI;AACF,cAAM,KAAK,MAAM,UAAU,WAAW,SAAS;AAAA,MACjD,SAAS,KAAK;AACZ,aAAK,OAAO,MAAM,kCAAkC,EAAE,WAAW,UAAU,MAAM,GAAG,CAAC,EAAE,CAAC;AAAA,MAC1F;AAAA,IACF;AAEA,UAAM;AAAA,MACJ;AAAA,MACA,KAAK;AAAA,MACL,EAAE,cAAc,mBAAmB;AAAA,IACrC;AAEA,QAAI;AACF,YAAM,KAAK,MAAM,cAAc,SAAS;AAAA,IAC1C,SAAS,KAAK;AACZ,WAAK,OAAO,MAAM,sCAAsC,EAAE,WAAW,UAAU,MAAM,GAAG,CAAC,EAAE,CAAC;AAAA,IAC9F;AACA,SAAK,OAAO,KAAK,sBAAsB,EAAE,WAAW,UAAU,MAAM,GAAG,CAAC,EAAE,CAAC;AAAA,EAC7E;AACF;;;AC7KA,OAAO,YAAY;AAKnB,IAAM,eAAe,KAAK,KAAK;AAIxB,IAAM,YAAN,MAAgB;AAAA,EAKrB,YAA6B,QAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EAJrB,SAAS,oBAAI,IAA8B;AAAA,EAC3C,YAAY;AAAA,EACZ,WAAiC;AAAA,EAIzC,MAAM,OAAO,KAAwC;AACnD,QAAI,KAAK,OAAO,SAAS,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY,cAAc;AACxE,YAAM,KAAK,MAAM;AAAA,IACnB;AAEA,QAAI,MAAM,KAAK,OAAO,IAAI,GAAG;AAC7B,QAAI,CAAC,KAAK;AACR,WAAK,OAAO,MAAM,oBAAoB,EAAE,IAAI,CAAC;AAC7C,YAAM,KAAK,MAAM;AACjB,YAAM,KAAK,OAAO,IAAI,GAAG;AAAA,IAC3B;AAEA,QAAI,CAAC,IAAK,OAAM,IAAI,cAAc,wBAAwB,gCAAgC,GAAG,IAAI,GAAG;AACpG,WAAO;AAAA,EACT;AAAA,EAEQ,QAAuB;AAC7B,QAAI,KAAK,SAAU,QAAO,KAAK;AAC/B,SAAK,WAAW,KAAK,QAAQ,EAAE,QAAQ,MAAM;AAAE,WAAK,WAAW;AAAA,IAAK,CAAC;AACrE,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,UAAyB;AACrC,SAAK,OAAO,MAAM,YAAY;AAC9B,UAAM,OAAO,MAAM,OAA6B,wBAAwB;AACxE,UAAM,SAAS,oBAAI,IAA8B;AACjD,eAAW,OAAO,KAAK,MAAM;AAC3B,UAAI,IAAI,KAAK,KAAK,IAAI,KAAK,MAAM,OAAO;AACtC,cAAM,MAAM,OAAO,gBAAgB,EAAE,KAAK,KAAqC,QAAQ,MAAM,CAAC;AAC9F,eAAO,IAAI,IAAI,KAAK,GAAG,GAAG;AAAA,MAC5B;AAAA,IACF;AACA,SAAK,SAAS;AACd,SAAK,YAAY,KAAK,IAAI;AAC1B,SAAK,OAAO,MAAM,gBAAgB,EAAE,UAAU,OAAO,KAAK,CAAC;AAAA,EAC7D;AACF;;;AChDA,IAAM,cAAqD;AAAA,EACzD,YAAY;AAAA,EACZ,YAAY;AACd;AAEA,IAAM,kBAAkB,IAAI,KAAK;AACjC,IAAM,oBAAoB,IAAI,KAAK;AAI5B,IAAM,kBAAN,MAAsB;AAAA,EAI3B,YACmB,MACA,QACA,QACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EANF,QAAQ,oBAAI,IAAmB;AAAA,EACxC,gBAAgB;AAAA,EAQxB,MAAM,MAAM,KAAa,aAAuC;AAC9D,QAAI,KAAK,SAAS,UAAW,QAAO;AAEpC,QAAI,KAAK,SAAS,SAAU,MAAK,aAAa;AAE9C,UAAM,MAAM,YAAY,KAAK,IAAI,KAAK;AACtC,QAAI,MAAM,GAAG;AACX,YAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,UAAI,SAAS,KAAK,IAAI,IAAI,MAAM,YAAY,KAAK;AAC/C,aAAK,OAAO,MAAM,wBAAwB,EAAE,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;AAClE,eAAO;AAAA,MACT;AAAA,IACF;AAEA,QAAI;AACF,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA,KAAK;AAAA,QACL,EAAE,cAAc,YAAY;AAAA,MAC9B;AAEA,UAAI,OAAO,SAAS,MAAM,GAAG;AAC3B,aAAK,MAAM,IAAI,KAAK,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,MAC/C;AAEA,aAAO,OAAO;AAAA,IAChB,SAAS,KAAK;AACZ,UAAI,KAAK,SAAS,SAAU,OAAM;AAGlC,WAAK,OAAO,KAAK,gCAAgC;AAAA,QAC/C,KAAK,IAAI,MAAM,GAAG,CAAC;AAAA,QACnB,OAAO,eAAe,QAAQ,IAAI,UAAU;AAAA,MAC9C,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,eAAqB;AAC3B,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,MAAM,KAAK,gBAAgB,kBAAmB;AAClD,SAAK,gBAAgB;AACrB,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,OAAO;AACrC,UAAI,MAAM,MAAM,YAAY,iBAAiB;AAC3C,aAAK,MAAM,OAAO,GAAG;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;;;ACpEO,IAAM,sBAAN,MAA0B;AAAA,EAG/B,YAA6B,QAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EAFZ,WAAW,oBAAI,IAA8B;AAAA,EAI9D,SAAY,WAAmB,IAAkC;AAC/D,UAAM,WAAW,KAAK,SAAS,IAAI,SAAS;AAC5C,QAAI,UAAU;AACZ,WAAK,OAAO,MAAM,qBAAqB,EAAE,KAAK,UAAU,CAAC;AACzD,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,GAAG,EAAE,QAAQ,MAAM;AACjC,WAAK,SAAS,OAAO,SAAS;AAAA,IAChC,CAAC;AAED,SAAK,SAAS,IAAI,WAAW,OAAO;AACpC,WAAO;AAAA,EACT;AACF;;;AClBO,IAAM,sBAAN,MAA0D;AAAA,EAI/D,YAA6B,QAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EAHZ,MAAM,oBAAI,IAAmB;AAAA,EACtC,mBAAmB;AAAA,EAInB,YAAkB;AACxB,QAAI,QAAQ,IAAI,UAAU,MAAM,gBAAgB,CAAC,KAAK,kBAAkB;AACtE,WAAK,mBAAmB;AACxB,WAAK,OAAO,KAAK,yFAAoF;AAAA,IACvG;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,WAA2C;AAC/D,SAAK,UAAU;AACf,WAAO,KAAK,IAAI,IAAI,SAAS,GAAG,gBAAgB;AAAA,EAClD;AAAA,EAEA,MAAM,UAAU,WAAmB,QAAsE;AACvG,SAAK,UAAU;AACf,SAAK,IAAI,IAAI,WAAW,MAAM;AAAA,EAChC;AAAA,EAEA,MAAM,cAAc,WAAkC;AACpD,SAAK,IAAI,OAAO,SAAS;AAAA,EAC3B;AACF;;;AC3BA,IAAM,cAAwC;AAAA,EAC5C,OAAO;AAAA,EAAG,MAAM;AAAA,EAAG,MAAM;AAAA,EAAG,OAAO;AAAA,EAAG,QAAQ;AAChD;AAEO,IAAM,gBAAN,MAA8C;AAAA,EAC3C;AAAA,EAER,YAAY,QAAkB,QAAQ;AACpC,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,SAAS,OAAuB;AAC9B,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,UAAU,OAA0B;AAC1C,WAAO,YAAY,KAAK,KAAK,YAAY,KAAK,KAAK;AAAA,EACrD;AAAA,EAEQ,OAAO,KAAa,MAAwC;AAClE,QAAI,CAAC,QAAQ,OAAO,KAAK,IAAI,EAAE,WAAW,EAAG,QAAO,cAAc,GAAG;AACrE,WAAO,cAAc,GAAG,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,EAClD;AAAA,EAEA,MAAM,KAAa,MAAsC;AACvD,QAAI,KAAK,UAAU,OAAO,EAAG,SAAQ,MAAM,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,EACnE;AAAA,EAEA,KAAK,KAAa,MAAsC;AACtD,QAAI,KAAK,UAAU,MAAM,EAAG,SAAQ,KAAK,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,EACjE;AAAA,EAEA,KAAK,KAAa,MAAsC;AACtD,QAAI,KAAK,UAAU,MAAM,EAAG,SAAQ,KAAK,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,EACjE;AAAA,EAEA,MAAM,KAAa,MAAsC;AACvD,QAAI,KAAK,UAAU,OAAO,EAAG,SAAQ,MAAM,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,EACnE;AACF;;;AChCO,IAAM,WAAN,MAAe;AAAA,EACX;AAAA,EACA;AAAA,EACQ;AAAA,EAEjB,YAAY,QAAwB;AAClC,SAAK,gBAAgB,IAAI,cAAc,OAAO,YAAY,MAAM;AAChE,UAAM,SAAS,OAAO,UAAU,KAAK;AAErC,UAAM,QAAQ,OAAO,SAAS,SAAS,IAAI,oBAAoB,MAAM;AACrE,UAAM,eAAe,OAAO,SAAS,gBAAgB;AAErD,UAAM,YAAY,IAAI,UAAU,MAAM;AACtC,UAAM,kBAAkB,IAAI,gBAAgB,cAAc,OAAO,QAAQ,MAAM;AAC/E,UAAM,eAAe,IAAI,oBAAoB,MAAM;AAEnD,SAAK,MAAM,IAAI,UAAU,OAAO,QAAQ,OAAO,MAAM;AACrD,SAAK,UAAU,IAAI;AAAA,MACjB,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,YAAY,OAAuB;AACjC,SAAK,cAAc,SAAS,KAAK;AAAA,EACnC;AACF;","names":["require","jwt","jwt","err"]}
|
|
1
|
+
{"version":3,"sources":["../src/otp/OtpClient.ts","../src/MiniMothError.ts","../src/http.ts","../src/phone.ts","../src/session/SessionClient.ts","../src/identity/IdentityClient.ts","../src/session/JwksCache.ts","../src/session/RevocationCache.ts","../src/session/RefreshDeduplicator.ts","../src/store/DefaultSessionStore.ts","../src/logger/ConsoleLogger.ts","../src/MiniMoth.ts"],"sourcesContent":["import jwt from 'jsonwebtoken'\nimport { apiPost, apiGet } from '../http'\nimport { MiniMothError, type MiniMothErrorCode } from '../MiniMothError'\nimport { normalizePhone } from '../phone'\nimport type { MiniMothSessionStore } from '../store/MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { AccessTokenPayload } from '../types'\n\ntype VerifyResult =\n | { valid: true; accessToken: string; refreshToken: string; sessionId: string; identityId?: string }\n | { valid: false; code: MiniMothErrorCode }\n\ntype OtpStatus = {\n otpId: string\n channel: string | null\n status: 'queued' | 'delivered' | 'failed'\n deliveredAt: string | null\n}\n\nexport class OtpClient {\n constructor(\n private readonly apiKey: string,\n private readonly store: MiniMothSessionStore,\n private readonly logger: MiniMothLogger\n ) {}\n\n async send(params: { phone: string }): Promise<{ otpId: string }> {\n const phone = normalizePhone(params.phone)\n const res = await apiPost<{ message: string; otp_id: string }>('/v1/otp/send', this.apiKey, { phone })\n this.logger.info('otp.sent', { phone: maskPhone(phone) })\n return { otpId: res.otp_id }\n }\n\n async status(otpId: string): Promise<OtpStatus> {\n const res = await apiGet<{\n otp_id: string\n channel: string | null\n status: 'queued' | 'delivered' | 'failed'\n delivered_at: string | null\n }>(`/v1/otp/status/${encodeURIComponent(otpId)}`, this.apiKey)\n return {\n otpId: res.otp_id,\n channel: res.channel,\n status: res.status,\n deliveredAt: res.delivered_at,\n }\n }\n\n async verify(params: { phone: string; otp: string }): Promise<VerifyResult> {\n const phone = normalizePhone(params.phone)\n validateOtp(params.otp)\n\n try {\n const res = await apiPost<{ access_token: string; refresh_token: string; expires_at: string }>(\n '/v1/otp/verify',\n this.apiKey,\n { phone, code: params.otp }\n )\n\n const payload = jwt.decode(res.access_token) as AccessTokenPayload | null\n if (!payload?.session_id) {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Could not decode session_id from access token', 0)\n }\n\n try {\n await this.store.setTokens(payload.session_id, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch {\n this.logger.error('otp.store.setTokens.failed', { sessionId: payload.session_id.slice(0, 8) })\n }\n\n this.logger.info('otp.verified', { sessionId: payload.session_id.slice(0, 8) })\n\n return {\n valid: true,\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n sessionId: payload.session_id,\n ...(payload.identity_id ? { identityId: payload.identity_id } : {}),\n }\n } catch (err) {\n if (err instanceof MiniMothError) {\n if (\n err.code === 'INVALID_OTP' ||\n err.code === 'OTP_NOT_FOUND' ||\n err.code === 'INVALID_PHONE' ||\n err.code === 'VERIFY_RATE_LIMITED'\n ) {\n this.logger.debug('otp.verify.failed', { code: err.code })\n return { valid: false, code: err.code }\n }\n }\n throw err\n }\n }\n}\n\nfunction validateOtp(otp: string): void {\n if (!otp || typeof otp !== 'string') {\n throw new MiniMothError('INVALID_OTP', 'OTP is required', 422)\n }\n}\n\nexport function maskPhone(phone: string): string {\n if (phone.length <= 4) return '****'\n return phone.slice(0, 4) + '*'.repeat(Math.max(phone.length - 6, 1)) + phone.slice(-2)\n}\n","export type MiniMothErrorCode =\n | 'INVALID_ACCESS_TOKEN'\n | 'SESSION_EXPIRED'\n | 'INVALID_OTP'\n | 'OTP_NOT_FOUND'\n | 'OTP_RATE_LIMITED'\n | 'VERIFY_RATE_LIMITED'\n | 'INSUFFICIENT_BALANCE'\n | 'NETWORK_ERROR'\n | 'INVALID_PHONE'\n | 'IDENTITY_NOT_FOUND'\n | 'IDENTITY_DELETE_DISABLED'\n | 'IDENTITY_LOOKUP_DISABLED'\n | 'UNKNOWN_ERROR'\n\nexport class MiniMothError extends Error {\n readonly code: MiniMothErrorCode\n readonly statusCode: number\n\n constructor(code: MiniMothErrorCode, message: string, statusCode: number, cause?: unknown) {\n super(message, cause !== undefined ? { cause } : undefined)\n this.name = 'MiniMothError'\n this.code = code\n this.statusCode = statusCode\n // Restore prototype chain for instanceof checks across module boundaries\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n","import { MiniMothError, type MiniMothErrorCode } from './MiniMothError'\nimport { createRequire } from 'module'\n\nconst require = createRequire(import.meta.url)\n// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\nconst pkg = require('../package.json') as { version: string }\n\nconst BASE_URL = 'https://api.minimoth.dev'\nconst USER_AGENT = `minimoth-sdk-node/${pkg.version}`\n\nconst BACKEND_CODE_MAP: Record<string, MiniMothErrorCode> = {\n INVALID_ACCESS_TOKEN: 'INVALID_ACCESS_TOKEN',\n SESSION_EXPIRED: 'SESSION_EXPIRED',\n INVALID_OTP: 'INVALID_OTP',\n OTP_NOT_FOUND: 'OTP_NOT_FOUND',\n OTP_RATE_LIMITED: 'OTP_RATE_LIMITED',\n VERIFY_RATE_LIMITED: 'VERIFY_RATE_LIMITED',\n INSUFFICIENT_BALANCE: 'INSUFFICIENT_BALANCE',\n INVALID_PHONE: 'INVALID_PHONE',\n IDENTITY_NOT_FOUND: 'IDENTITY_NOT_FOUND',\n IDENTITY_DELETE_DISABLED: 'IDENTITY_DELETE_DISABLED',\n IDENTITY_LOOKUP_DISABLED: 'IDENTITY_LOOKUP_DISABLED',\n}\n\nasync function handleResponse<T>(response: Response): Promise<T> {\n if (response.ok) return response.json() as Promise<T>\n\n let body: { code?: string; error?: string } = {}\n try { body = await response.json() as { code?: string; error?: string } } catch {}\n\n const sdkCode: MiniMothErrorCode = BACKEND_CODE_MAP[body.code ?? ''] ?? 'UNKNOWN_ERROR'\n throw new MiniMothError(sdkCode, body.error ?? 'Unknown error', response.status)\n}\n\nexport async function apiPost<T>(\n path: string,\n apiKey: string,\n body: Record<string, unknown>\n): Promise<T> {\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Api-Key': apiKey,\n 'User-Agent': USER_AGENT,\n },\n body: JSON.stringify(body),\n })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n\nexport async function apiGet<T>(path: string, apiKey?: string): Promise<T> {\n const headers: Record<string, string> = { 'User-Agent': USER_AGENT }\n if (apiKey) headers['X-Api-Key'] = apiKey\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, { headers })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n\nexport async function apiDelete<T>(path: string, apiKey: string): Promise<T> {\n let response: Response\n try {\n response = await fetch(`${BASE_URL}${path}`, {\n method: 'DELETE',\n headers: {\n 'X-Api-Key': apiKey,\n 'User-Agent': USER_AGENT,\n },\n })\n } catch (err) {\n throw new MiniMothError('NETWORK_ERROR', 'Network request failed', 0, err)\n }\n return handleResponse<T>(response)\n}\n","import { MiniMothError } from './MiniMothError'\n\n// Normalizes to 12-digit canonical Indian format (91XXXXXXXXXX).\n// Rejects if spaces or hyphens are present.\nexport function normalizePhone(raw: string): string {\n if (!raw || typeof raw !== 'string') {\n throw new MiniMothError('INVALID_PHONE', 'Phone number is required', 422)\n }\n if (/[\\s-]/.test(raw)) {\n throw new MiniMothError('INVALID_PHONE', 'Phone number must not contain spaces or hyphens', 422)\n }\n let phone = raw\n if (phone.startsWith('+')) phone = phone.slice(1)\n // 10-digit subscriber number — prepend country code\n if (phone.length === 10) phone = '91' + phone\n return phone\n}\n","import jwt from 'jsonwebtoken'\nimport { apiPost } from '../http'\nimport { MiniMothError, type MiniMothErrorCode } from '../MiniMothError'\nimport type { JwksCache } from './JwksCache'\nimport type { RevocationCache } from './RevocationCache'\nimport type { RefreshDeduplicator } from './RefreshDeduplicator'\nimport type { MiniMothSessionStore } from '../store/MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { Session, AccessTokenPayload } from '../types'\n\ntype Tokens = { accessToken: string; refreshToken: string }\n\ntype SafeValidateResult =\n | { valid: true; session: Session }\n | { valid: false; code: MiniMothErrorCode }\n\nexport class SessionClient {\n constructor(\n private readonly apiKey: string,\n private readonly jwksCache: JwksCache,\n private readonly revocationCache: RevocationCache,\n private readonly deduplicator: RefreshDeduplicator,\n private readonly store: MiniMothSessionStore,\n private readonly logger: MiniMothLogger\n ) {}\n\n async validate(accessToken: string): Promise<Session> {\n const decoded = jwt.decode(accessToken, { complete: true })\n if (!decoded || typeof decoded === 'string') {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is malformed', 401)\n }\n\n const kid = (decoded.header as unknown as Record<string, string>)['kid']\n if (!kid) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is missing kid header', 401)\n\n const publicKey = await this.jwksCache.getKey(kid)\n\n let currentToken = accessToken\n let newTokens: Tokens | undefined\n\n try {\n jwt.verify(accessToken, publicKey, { algorithms: ['RS256'] })\n } catch (err) {\n if (err instanceof jwt.TokenExpiredError) {\n const expiredPayload = decoded.payload as AccessTokenPayload\n const sessionId = expiredPayload?.session_id\n if (!sessionId) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token is invalid', 401)\n\n newTokens = await this.deduplicator.getOrRun(sessionId, async () => {\n const refreshToken = await this.store.getRefreshToken(sessionId)\n if (!refreshToken) {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Access token expired and no refresh token available', 401)\n }\n\n this.logger.info('session.auto_refresh', { sessionId: sessionId.slice(0, 8) })\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: refreshToken }\n )\n\n try {\n await this.store.setTokens(sessionId, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: sessionId.slice(0, 8) })\n }\n\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n })\n\n currentToken = newTokens.accessToken\n\n // Verify the new token\n const newDecoded = jwt.decode(currentToken, { complete: true })\n const newKid = (newDecoded?.header as Record<string, string> | undefined)?.['kid']\n const newKey = newKid ? await this.jwksCache.getKey(newKid) : publicKey\n jwt.verify(currentToken, newKey, { algorithms: ['RS256'] })\n } else {\n throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Token signature is invalid', 401)\n }\n }\n\n const payload = jwt.decode(currentToken) as AccessTokenPayload\n const isValid = await this.revocationCache.check(payload.jti, currentToken)\n if (!isValid) throw new MiniMothError('SESSION_EXPIRED', 'Session has been revoked', 401)\n\n const session: Session = {\n projectId: payload.project_id,\n sessionId: payload.session_id,\n expiresAt: new Date(payload.exp * 1000),\n }\n if (payload.identity_id) session.identityId = payload.identity_id\n if (newTokens) session.newTokens = newTokens\n\n this.logger.info('session.validated', { sessionId: payload.session_id.slice(0, 8) })\n return session\n }\n\n async safeValidate(accessToken: string): Promise<SafeValidateResult> {\n try {\n const session = await this.validate(accessToken)\n return { valid: true, session }\n } catch (err) {\n if (err instanceof MiniMothError) return { valid: false, code: err.code }\n throw err\n }\n }\n\n async refresh(refreshToken: string): Promise<Tokens> {\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: refreshToken }\n )\n\n // Update store if session_id is decodable from new token\n const payload = jwt.decode(res.access_token) as AccessTokenPayload | null\n if (payload?.session_id) {\n try {\n await this.store.setTokens(payload.session_id, {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n })\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: payload.session_id.slice(0, 8) })\n }\n }\n\n this.logger.info('session.refreshed')\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n }\n\n async logout(params: { accessToken: string; refreshToken: string }): Promise<void> {\n const payload = jwt.decode(params.accessToken) as AccessTokenPayload | null\n const sessionId = payload?.session_id ?? null\n\n if (!sessionId) throw new MiniMothError('INVALID_ACCESS_TOKEN', 'Cannot decode token', 401)\n\n let currentAccessToken = params.accessToken\n\n // If token is expired, refresh before logout — deduplicated to prevent concurrent refresh races\n if (payload && payload.exp < Math.floor(Date.now() / 1000)) {\n const newTokens = await this.deduplicator.getOrRun(sessionId, async () => {\n const res = await apiPost<{ access_token: string; refresh_token: string }>(\n '/v1/session/refresh',\n this.apiKey,\n { refresh_token: params.refreshToken }\n )\n return { accessToken: res.access_token, refreshToken: res.refresh_token }\n })\n currentAccessToken = newTokens.accessToken\n try {\n await this.store.setTokens(sessionId, newTokens)\n } catch (err) {\n this.logger.error('session.store.setTokens.failed', { sessionId: sessionId.slice(0, 8) })\n }\n }\n\n await apiPost<{ message: string }>(\n '/v1/session/logout',\n this.apiKey,\n { access_token: currentAccessToken }\n )\n\n try {\n await this.store.deleteSession(sessionId)\n } catch (err) {\n this.logger.error('session.store.deleteSession.failed', { sessionId: sessionId.slice(0, 8) })\n }\n this.logger.info('session.logged_out', { sessionId: sessionId.slice(0, 8) })\n }\n}\n","import { apiGet, apiDelete } from '../http'\nimport { normalizePhone } from '../phone'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { Identity, IdentityFactor } from '../types'\n\ntype IdentityResponse = {\n id: string\n created_at: string\n factors: IdentityFactor[]\n}\n\nexport class IdentityClient {\n constructor(\n private readonly apiKey: string,\n private readonly logger: MiniMothLogger\n ) {}\n\n async get(identityId: string): Promise<Identity> {\n const res = await apiGet<IdentityResponse>(`/v1/identity/${encodeURIComponent(identityId)}`, this.apiKey)\n return toIdentity(res)\n }\n\n async getByPhone(phone: string): Promise<Identity> {\n const normalized = normalizePhone(phone)\n const res = await apiGet<IdentityResponse>(`/v1/identity?phone=${encodeURIComponent(normalized)}`, this.apiKey)\n return toIdentity(res)\n }\n\n async delete(identityId: string): Promise<{ deleted: true }> {\n await apiDelete<{ deleted: boolean }>(`/v1/identity/${encodeURIComponent(identityId)}`, this.apiKey)\n this.logger.info('identity.deleted', { identityId: identityId.slice(0, 8) })\n return { deleted: true }\n }\n}\n\nfunction toIdentity(res: IdentityResponse): Identity {\n return {\n id: res.id,\n createdAt: new Date(res.created_at),\n factors: res.factors,\n }\n}\n","import crypto from 'crypto'\nimport { apiGet } from '../http'\nimport { MiniMothError } from '../MiniMothError'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\n\nconst CACHE_TTL_MS = 60 * 60 * 1000 // 1 hour\n\ntype JwkEntry = Record<string, string>\n\nexport class JwksCache {\n private keyMap = new Map<string, crypto.KeyObject>()\n private fetchedAt = 0\n private fetching: Promise<void> | null = null\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n async getKey(kid: string): Promise<crypto.KeyObject> {\n if (this.keyMap.size === 0 || Date.now() - this.fetchedAt > CACHE_TTL_MS) {\n await this.fetch()\n }\n\n let key = this.keyMap.get(kid)\n if (!key) {\n this.logger.debug('jwks.unknown_kid', { kid })\n await this.fetch()\n key = this.keyMap.get(kid)\n }\n\n if (!key) throw new MiniMothError('INVALID_ACCESS_TOKEN', `No public key found for kid: ${kid}`, 401)\n return key\n }\n\n private fetch(): Promise<void> {\n if (this.fetching) return this.fetching\n this.fetching = this.doFetch().finally(() => { this.fetching = null })\n return this.fetching\n }\n\n private async doFetch(): Promise<void> {\n this.logger.debug('jwks.fetch')\n const data = await apiGet<{ keys: JwkEntry[] }>('/.well-known/jwks.json')\n const newMap = new Map<string, crypto.KeyObject>()\n for (const jwk of data.keys) {\n if (jwk['kid'] && jwk['kty'] === 'RSA') {\n const key = crypto.createPublicKey({ key: jwk as unknown as crypto.JsonWebKey, format: 'jwk' })\n newMap.set(jwk['kid'], key)\n }\n }\n this.keyMap = newMap\n this.fetchedAt = Date.now()\n this.logger.debug('jwks.updated', { keyCount: newMap.size })\n }\n}\n","import { apiPost } from '../http'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\nimport type { ValidateMode } from '../types'\n\nconst MODE_TTL_MS: Partial<Record<ValidateMode, number>> = {\n recheck_1m: 60_000,\n recheck_3m: 180_000,\n}\n\nconst EVICTION_TTL_MS = 5 * 60 * 1000 // JWT max lifetime\nconst CLEANUP_WINDOW_MS = 5 * 60 * 1000\n\ntype Entry = { checkedAt: number }\n\nexport class RevocationCache {\n private readonly cache = new Map<string, Entry>()\n private lastCleanedAt = 0\n\n constructor(\n private readonly mode: ValidateMode,\n private readonly apiKey: string,\n private readonly logger: MiniMothLogger\n ) {}\n\n async check(jti: string, accessToken: string): Promise<boolean> {\n if (this.mode === 'instant') return true\n\n if (this.mode !== 'strict') this.maybeCleanup()\n\n const ttl = MODE_TTL_MS[this.mode] ?? 0\n if (ttl > 0) {\n const entry = this.cache.get(jti)\n if (entry && Date.now() - entry.checkedAt < ttl) {\n this.logger.debug('revocation.cache.hit', { jti: jti.slice(0, 8) })\n return true\n }\n }\n\n try {\n const result = await apiPost<{ valid: boolean }>(\n '/v1/session/validate',\n this.apiKey,\n { access_token: accessToken }\n )\n\n if (result.valid && ttl > 0) {\n this.cache.set(jti, { checkedAt: Date.now() })\n }\n\n return result.valid\n } catch (err) {\n if (this.mode === 'strict') throw err\n\n // recheck_*m: fail open\n this.logger.warn('revocation.check.failed_open', {\n jti: jti.slice(0, 8),\n error: err instanceof Error ? err.message : 'unknown',\n })\n return true\n }\n }\n\n private maybeCleanup(): void {\n const now = Date.now()\n if (now - this.lastCleanedAt < CLEANUP_WINDOW_MS) return\n this.lastCleanedAt = now // set before iteration to prevent concurrent double-clean\n for (const [jti, entry] of this.cache) {\n if (now - entry.checkedAt > EVICTION_TTL_MS) {\n this.cache.delete(jti)\n }\n }\n }\n}\n","import { MiniMothLogger } from '../logger/MiniMothLogger'\n\ntype Tokens = { accessToken: string; refreshToken: string }\n\nexport class RefreshDeduplicator {\n private readonly inflight = new Map<string, Promise<unknown>>()\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n getOrRun<T>(sessionId: string, fn: () => Promise<T>): Promise<T> {\n const existing = this.inflight.get(sessionId)\n if (existing) {\n this.logger.debug('refresh dedup hit', { key: sessionId })\n return existing as Promise<T>\n }\n\n const promise = fn().finally(() => {\n this.inflight.delete(sessionId)\n })\n\n this.inflight.set(sessionId, promise)\n return promise\n }\n}\n","import type { MiniMothSessionStore } from './MiniMothSessionStore'\nimport type { MiniMothLogger } from '../logger/MiniMothLogger'\n\ntype Entry = { accessToken: string; refreshToken: string }\n\nexport class DefaultSessionStore implements MiniMothSessionStore {\n private readonly map = new Map<string, Entry>()\n private warnedProduction = false\n\n constructor(private readonly logger: MiniMothLogger) {}\n\n private maybeWarn(): void {\n if (process.env['NODE_ENV'] === 'production' && !this.warnedProduction) {\n this.warnedProduction = true\n this.logger.warn('using default in-memory session store — not suitable for multi-replica deployments')\n }\n }\n\n async getRefreshToken(sessionId: string): Promise<string | null> {\n this.maybeWarn()\n return this.map.get(sessionId)?.refreshToken ?? null\n }\n\n async setTokens(sessionId: string, tokens: { accessToken: string; refreshToken: string }): Promise<void> {\n this.maybeWarn()\n this.map.set(sessionId, tokens)\n }\n\n async deleteSession(sessionId: string): Promise<void> {\n this.map.delete(sessionId)\n }\n}\n","import type { MiniMothLogger } from './MiniMothLogger'\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0, info: 1, warn: 2, error: 3, silent: 4,\n}\n\nexport class ConsoleLogger implements MiniMothLogger {\n private level: LogLevel\n\n constructor(level: LogLevel = 'info') {\n this.level = level\n }\n\n setLevel(level: LogLevel): void {\n this.level = level\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[this.level]\n }\n\n private format(msg: string, meta?: Record<string, unknown>): string {\n if (!meta || Object.keys(meta).length === 0) return `[minimoth] ${msg}`\n return `[minimoth] ${msg} ${JSON.stringify(meta)}`\n }\n\n debug(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('debug')) console.debug(this.format(msg, meta))\n }\n\n info(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('info')) console.info(this.format(msg, meta))\n }\n\n warn(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('warn')) console.warn(this.format(msg, meta))\n }\n\n error(msg: string, meta?: Record<string, unknown>): void {\n if (this.shouldLog('error')) console.error(this.format(msg, meta))\n }\n}\n","import { OtpClient } from './otp/OtpClient'\nimport { SessionClient } from './session/SessionClient'\nimport { IdentityClient } from './identity/IdentityClient'\nimport { JwksCache } from './session/JwksCache'\nimport { RevocationCache } from './session/RevocationCache'\nimport { RefreshDeduplicator } from './session/RefreshDeduplicator'\nimport { DefaultSessionStore } from './store/DefaultSessionStore'\nimport { ConsoleLogger } from './logger/ConsoleLogger'\nimport type { MiniMothConfig } from './types'\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nexport class MiniMoth {\n readonly otp: OtpClient\n readonly session: SessionClient\n readonly identity: IdentityClient\n private readonly consoleLogger: ConsoleLogger\n\n constructor(config: MiniMothConfig) {\n this.consoleLogger = new ConsoleLogger(config.logLevel ?? 'info')\n const logger = config.logger ?? this.consoleLogger\n\n const store = config.session?.store ?? new DefaultSessionStore(logger)\n const validateMode = config.session?.validateMode ?? 'instant'\n\n const jwksCache = new JwksCache(logger)\n const revocationCache = new RevocationCache(validateMode, config.apiKey, logger)\n const deduplicator = new RefreshDeduplicator(logger)\n\n this.otp = new OtpClient(config.apiKey, store, logger)\n this.session = new SessionClient(\n config.apiKey,\n jwksCache,\n revocationCache,\n deduplicator,\n store,\n logger\n )\n this.identity = new IdentityClient(config.apiKey, logger)\n }\n\n // Only affects the built-in ConsoleLogger. Has no effect if a custom logger was provided.\n setLogLevel(level: LogLevel): void {\n this.consoleLogger.setLevel(level)\n }\n}\n"],"mappings":"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","names":["require","jwt","jwt","err"]}
|