@openeudi/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +198 -0
- package/dist/index.cjs +278 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +262 -0
- package/dist/index.d.ts +262 -0
- package/dist/index.js +268 -0
- package/dist/index.js.map +1 -0
- package/dist/qr.cjs +22 -0
- package/dist/qr.cjs.map +1 -0
- package/dist/qr.d.cts +13 -0
- package/dist/qr.d.ts +13 -0
- package/dist/qr.js +20 -0
- package/dist/qr.js.map +1 -0
- package/package.json +81 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { v4 } from 'uuid';
|
|
3
|
+
|
|
4
|
+
// src/types/verification.ts
|
|
5
|
+
var VerificationType = /* @__PURE__ */ ((VerificationType2) => {
|
|
6
|
+
VerificationType2["AGE"] = "AGE";
|
|
7
|
+
VerificationType2["COUNTRY"] = "COUNTRY";
|
|
8
|
+
VerificationType2["BOTH"] = "BOTH";
|
|
9
|
+
return VerificationType2;
|
|
10
|
+
})(VerificationType || {});
|
|
11
|
+
var VerificationStatus = /* @__PURE__ */ ((VerificationStatus2) => {
|
|
12
|
+
VerificationStatus2["PENDING"] = "PENDING";
|
|
13
|
+
VerificationStatus2["SCANNED"] = "SCANNED";
|
|
14
|
+
VerificationStatus2["VERIFIED"] = "VERIFIED";
|
|
15
|
+
VerificationStatus2["REJECTED"] = "REJECTED";
|
|
16
|
+
VerificationStatus2["EXPIRED"] = "EXPIRED";
|
|
17
|
+
return VerificationStatus2;
|
|
18
|
+
})(VerificationStatus || {});
|
|
19
|
+
|
|
20
|
+
// src/errors.ts
|
|
21
|
+
var SessionNotFoundError = class extends Error {
|
|
22
|
+
constructor(sessionId) {
|
|
23
|
+
super(`Session not found: ${sessionId}`);
|
|
24
|
+
this.name = "SessionNotFoundError";
|
|
25
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var SessionExpiredError = class extends Error {
|
|
29
|
+
constructor(sessionId) {
|
|
30
|
+
super(`Session expired: ${sessionId}`);
|
|
31
|
+
this.name = "SessionExpiredError";
|
|
32
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// src/storage/memory.store.ts
|
|
37
|
+
var InMemorySessionStore = class {
|
|
38
|
+
sessions = /* @__PURE__ */ new Map();
|
|
39
|
+
async get(id) {
|
|
40
|
+
return this.sessions.get(id) ?? null;
|
|
41
|
+
}
|
|
42
|
+
async set(session) {
|
|
43
|
+
this.sessions.set(session.id, session);
|
|
44
|
+
}
|
|
45
|
+
async delete(id) {
|
|
46
|
+
this.sessions.delete(id);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/modes/demo.mode.ts
|
|
51
|
+
var EU_COUNTRIES = [
|
|
52
|
+
"AT",
|
|
53
|
+
"BE",
|
|
54
|
+
"BG",
|
|
55
|
+
"HR",
|
|
56
|
+
"CY",
|
|
57
|
+
"CZ",
|
|
58
|
+
"DK",
|
|
59
|
+
"EE",
|
|
60
|
+
"FI",
|
|
61
|
+
"FR",
|
|
62
|
+
"DE",
|
|
63
|
+
"GR",
|
|
64
|
+
"HU",
|
|
65
|
+
"IE",
|
|
66
|
+
"IT",
|
|
67
|
+
"LV",
|
|
68
|
+
"LT",
|
|
69
|
+
"LU",
|
|
70
|
+
"MT",
|
|
71
|
+
"NL",
|
|
72
|
+
"PL",
|
|
73
|
+
"PT",
|
|
74
|
+
"RO",
|
|
75
|
+
"SK",
|
|
76
|
+
"SI",
|
|
77
|
+
"ES",
|
|
78
|
+
"SE"
|
|
79
|
+
];
|
|
80
|
+
var DemoMode = class {
|
|
81
|
+
name = "demo";
|
|
82
|
+
delayMs;
|
|
83
|
+
constructor(config = {}) {
|
|
84
|
+
this.delayMs = config.delayMs ?? 3e3;
|
|
85
|
+
}
|
|
86
|
+
async processCallback(session, _walletResponse) {
|
|
87
|
+
const country = this.pickCountry(session.countryWhitelist);
|
|
88
|
+
return this.buildResult(session.type, country);
|
|
89
|
+
}
|
|
90
|
+
async simulateCompletion(session) {
|
|
91
|
+
await new Promise((resolve) => setTimeout(resolve, this.delayMs));
|
|
92
|
+
return this.processCallback(session, {});
|
|
93
|
+
}
|
|
94
|
+
pickCountry(whitelist) {
|
|
95
|
+
const pool = whitelist && whitelist.length > 0 ? whitelist : EU_COUNTRIES;
|
|
96
|
+
return pool[Math.floor(Math.random() * pool.length)];
|
|
97
|
+
}
|
|
98
|
+
buildResult(type, country) {
|
|
99
|
+
const includeAge = type === "AGE" /* AGE */ || type === "BOTH" /* BOTH */;
|
|
100
|
+
const includeCountry = type === "COUNTRY" /* COUNTRY */ || type === "BOTH" /* BOTH */;
|
|
101
|
+
return {
|
|
102
|
+
verified: true,
|
|
103
|
+
country,
|
|
104
|
+
ageVerified: includeAge ? true : void 0,
|
|
105
|
+
countryVerified: includeCountry ? true : void 0
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// src/modes/mock.mode.ts
|
|
111
|
+
var DEFAULT_RESULT = {
|
|
112
|
+
verified: true,
|
|
113
|
+
country: "DE",
|
|
114
|
+
ageVerified: true,
|
|
115
|
+
countryVerified: true
|
|
116
|
+
};
|
|
117
|
+
var MockMode = class {
|
|
118
|
+
name = "mock";
|
|
119
|
+
defaultResult;
|
|
120
|
+
delayMs;
|
|
121
|
+
sessionOverrides = /* @__PURE__ */ new Map();
|
|
122
|
+
constructor(config = {}) {
|
|
123
|
+
this.defaultResult = config.defaultResult ?? { ...DEFAULT_RESULT };
|
|
124
|
+
this.delayMs = config.delayMs ?? 0;
|
|
125
|
+
}
|
|
126
|
+
/** Set a per-session result override */
|
|
127
|
+
setSessionResult(sessionId, result) {
|
|
128
|
+
this.sessionOverrides.set(sessionId, result);
|
|
129
|
+
}
|
|
130
|
+
/** Clear a per-session result override */
|
|
131
|
+
clearSessionResult(sessionId) {
|
|
132
|
+
this.sessionOverrides.delete(sessionId);
|
|
133
|
+
}
|
|
134
|
+
async processCallback(session, _walletResponse) {
|
|
135
|
+
if (this.delayMs > 0) {
|
|
136
|
+
await new Promise((resolve) => setTimeout(resolve, this.delayMs));
|
|
137
|
+
}
|
|
138
|
+
return this.sessionOverrides.get(session.id) ?? { ...this.defaultResult };
|
|
139
|
+
}
|
|
140
|
+
async simulateCompletion(session) {
|
|
141
|
+
return this.processCallback(session, {});
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
var DEFAULT_TTL_MS = 3e5;
|
|
145
|
+
var DEFAULT_WALLET_BASE_URL = "openid4vp://verify";
|
|
146
|
+
var VerificationService = class extends EventEmitter {
|
|
147
|
+
store;
|
|
148
|
+
mode;
|
|
149
|
+
sessionTtlMs;
|
|
150
|
+
walletBaseUrl;
|
|
151
|
+
/** Track session IDs for cleanup (store interface has no list method) */
|
|
152
|
+
sessionIds = /* @__PURE__ */ new Set();
|
|
153
|
+
constructor(config) {
|
|
154
|
+
super();
|
|
155
|
+
this.mode = config.mode;
|
|
156
|
+
this.store = config.store ?? new InMemorySessionStore();
|
|
157
|
+
this.sessionTtlMs = config.sessionTtlMs ?? DEFAULT_TTL_MS;
|
|
158
|
+
this.walletBaseUrl = config.walletBaseUrl ?? DEFAULT_WALLET_BASE_URL;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Create a new verification session
|
|
162
|
+
*/
|
|
163
|
+
async createSession(input) {
|
|
164
|
+
const id = v4();
|
|
165
|
+
const now = /* @__PURE__ */ new Date();
|
|
166
|
+
const session = {
|
|
167
|
+
id,
|
|
168
|
+
type: input.type,
|
|
169
|
+
status: "PENDING" /* PENDING */,
|
|
170
|
+
walletUrl: "",
|
|
171
|
+
// set below, may be async from mode
|
|
172
|
+
countryWhitelist: input.countryWhitelist,
|
|
173
|
+
countryBlacklist: input.countryBlacklist,
|
|
174
|
+
redirectUrl: input.redirectUrl,
|
|
175
|
+
metadata: input.metadata,
|
|
176
|
+
createdAt: now,
|
|
177
|
+
expiresAt: new Date(now.getTime() + this.sessionTtlMs)
|
|
178
|
+
};
|
|
179
|
+
session.walletUrl = this.mode.buildWalletUrl ? await this.mode.buildWalletUrl(id, input) : `${this.walletBaseUrl}?session=${id}`;
|
|
180
|
+
await this.store.set(session);
|
|
181
|
+
this.sessionIds.add(id);
|
|
182
|
+
this.emit("session:created", session);
|
|
183
|
+
if (this.mode.simulateCompletion) {
|
|
184
|
+
this.mode.simulateCompletion(session).then(async (result) => {
|
|
185
|
+
const current = await this.store.get(id);
|
|
186
|
+
if (current && current.status === "PENDING" /* PENDING */) {
|
|
187
|
+
await this.completeSession(current, result);
|
|
188
|
+
}
|
|
189
|
+
}).catch(() => {
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return session;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get a session by ID
|
|
196
|
+
* @throws SessionNotFoundError
|
|
197
|
+
*/
|
|
198
|
+
async getSession(id) {
|
|
199
|
+
const session = await this.store.get(id);
|
|
200
|
+
if (!session) {
|
|
201
|
+
throw new SessionNotFoundError(id);
|
|
202
|
+
}
|
|
203
|
+
return session;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Handle a callback from the wallet
|
|
207
|
+
* @throws SessionNotFoundError
|
|
208
|
+
* @throws SessionExpiredError
|
|
209
|
+
*/
|
|
210
|
+
async handleCallback(sessionId, walletResponse) {
|
|
211
|
+
const session = await this.store.get(sessionId);
|
|
212
|
+
if (!session) {
|
|
213
|
+
throw new SessionNotFoundError(sessionId);
|
|
214
|
+
}
|
|
215
|
+
if (/* @__PURE__ */ new Date() > session.expiresAt) {
|
|
216
|
+
throw new SessionExpiredError(sessionId);
|
|
217
|
+
}
|
|
218
|
+
const result = await this.mode.processCallback(session, walletResponse);
|
|
219
|
+
await this.completeSession(session, result);
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Remove expired sessions from the store
|
|
224
|
+
* @returns Number of sessions cleaned up
|
|
225
|
+
*/
|
|
226
|
+
async cleanupExpired() {
|
|
227
|
+
const now = /* @__PURE__ */ new Date();
|
|
228
|
+
let count = 0;
|
|
229
|
+
for (const id of this.sessionIds) {
|
|
230
|
+
const session = await this.store.get(id);
|
|
231
|
+
if (!session) {
|
|
232
|
+
this.sessionIds.delete(id);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (now > session.expiresAt && session.status === "PENDING" /* PENDING */) {
|
|
236
|
+
const expired = { ...session, status: "EXPIRED" /* EXPIRED */ };
|
|
237
|
+
await this.store.set(expired);
|
|
238
|
+
await this.store.delete(id);
|
|
239
|
+
this.sessionIds.delete(id);
|
|
240
|
+
this.emit("session:expired", expired);
|
|
241
|
+
count++;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return count;
|
|
245
|
+
}
|
|
246
|
+
async completeSession(session, result) {
|
|
247
|
+
const status = result.verified ? "VERIFIED" /* VERIFIED */ : "REJECTED" /* REJECTED */;
|
|
248
|
+
const updated = {
|
|
249
|
+
...session,
|
|
250
|
+
status,
|
|
251
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
252
|
+
result
|
|
253
|
+
};
|
|
254
|
+
await this.store.set(updated);
|
|
255
|
+
if (result.verified) {
|
|
256
|
+
this.emit("session:verified", updated, result);
|
|
257
|
+
} else {
|
|
258
|
+
this.emit("session:rejected", updated, result.rejectionReason);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// src/index.ts
|
|
264
|
+
var VERSION = "0.1.0";
|
|
265
|
+
|
|
266
|
+
export { DemoMode, InMemorySessionStore, MockMode, SessionExpiredError, SessionNotFoundError, VERSION, VerificationService, VerificationStatus, VerificationType };
|
|
267
|
+
//# sourceMappingURL=index.js.map
|
|
268
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/verification.ts","../src/errors.ts","../src/storage/memory.store.ts","../src/modes/demo.mode.ts","../src/modes/mock.mode.ts","../src/verification.service.ts","../src/index.ts"],"names":["VerificationType","VerificationStatus","uuidv4"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Type of verification to perform\n */\nexport enum VerificationType {\n /** Verify age (over_18 attribute) */\n AGE = 'AGE',\n /** Verify country of residence */\n COUNTRY = 'COUNTRY',\n /** Verify both age and country */\n BOTH = 'BOTH',\n}\n\n/**\n * Status of a verification session\n */\nexport enum VerificationStatus {\n /** Session created, waiting for wallet scan */\n PENDING = 'PENDING',\n /** QR code scanned, credential exchange in progress */\n SCANNED = 'SCANNED',\n /** Verification completed successfully */\n VERIFIED = 'VERIFIED',\n /** Verification rejected (age, country, or policy) */\n REJECTED = 'REJECTED',\n /** Session expired before completion */\n EXPIRED = 'EXPIRED',\n}\n","/**\n * Thrown when a session ID is not found in the store\n */\nexport class SessionNotFoundError extends Error {\n constructor(sessionId: string) {\n super(`Session not found: ${sessionId}`);\n this.name = 'SessionNotFoundError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown when an operation is attempted on an expired session\n */\nexport class SessionExpiredError extends Error {\n constructor(sessionId: string) {\n super(`Session expired: ${sessionId}`);\n this.name = 'SessionExpiredError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import type { VerificationSession } from '../types/session.js';\n\nimport type { ISessionStore } from './store.interface.js';\n\n/**\n * In-memory session store using a Map.\n * Suitable for development, testing, and single-process deployments.\n * Sessions are lost on process restart.\n */\nexport class InMemorySessionStore implements ISessionStore {\n private sessions = new Map<string, VerificationSession>();\n\n async get(id: string): Promise<VerificationSession | null> {\n return this.sessions.get(id) ?? null;\n }\n\n async set(session: VerificationSession): Promise<void> {\n this.sessions.set(session.id, session);\n }\n\n async delete(id: string): Promise<void> {\n this.sessions.delete(id);\n }\n}\n","import type { VerificationSession, VerificationResult } from '../types/session.js';\nimport { VerificationType } from '../types/verification.js';\n\nimport type { IVerificationMode } from './mode.interface.js';\n\nconst EU_COUNTRIES = [\n 'AT',\n 'BE',\n 'BG',\n 'HR',\n 'CY',\n 'CZ',\n 'DK',\n 'EE',\n 'FI',\n 'FR',\n 'DE',\n 'GR',\n 'HU',\n 'IE',\n 'IT',\n 'LV',\n 'LT',\n 'LU',\n 'MT',\n 'NL',\n 'PL',\n 'PT',\n 'RO',\n 'SK',\n 'SI',\n 'ES',\n 'SE',\n];\n\nexport interface DemoModeConfig {\n /** Delay in ms before auto-completion (default: 3000) */\n delayMs?: number;\n}\n\n/**\n * Demo mode — auto-completes verification with randomized EU data.\n * Used for product demos and landing page previews.\n */\nexport class DemoMode implements IVerificationMode {\n readonly name = 'demo';\n private delayMs: number;\n\n constructor(config: DemoModeConfig = {}) {\n this.delayMs = config.delayMs ?? 3000;\n }\n\n async processCallback(session: VerificationSession, _walletResponse: unknown): Promise<VerificationResult> {\n const country = this.pickCountry(session.countryWhitelist);\n return this.buildResult(session.type, country);\n }\n\n async simulateCompletion(session: VerificationSession): Promise<VerificationResult> {\n await new Promise((resolve) => setTimeout(resolve, this.delayMs));\n return this.processCallback(session, {});\n }\n\n private pickCountry(whitelist?: string[]): string {\n const pool = whitelist && whitelist.length > 0 ? whitelist : EU_COUNTRIES;\n return pool[Math.floor(Math.random() * pool.length)];\n }\n\n private buildResult(type: VerificationType, country: string): VerificationResult {\n const includeAge = type === VerificationType.AGE || type === VerificationType.BOTH;\n const includeCountry = type === VerificationType.COUNTRY || type === VerificationType.BOTH;\n\n return {\n verified: true,\n country,\n ageVerified: includeAge ? true : undefined,\n countryVerified: includeCountry ? true : undefined,\n };\n }\n}\n","import type { VerificationSession, VerificationResult } from '../types/session.js';\n\nimport type { IVerificationMode } from './mode.interface.js';\n\nexport interface MockModeConfig {\n /** Default result returned for all sessions (default: verified with DE) */\n defaultResult?: VerificationResult;\n /** Delay in ms before returning result (default: 0) */\n delayMs?: number;\n}\n\nconst DEFAULT_RESULT: VerificationResult = {\n verified: true,\n country: 'DE',\n ageVerified: true,\n countryVerified: true,\n};\n\n/**\n * Mock mode — configurable responses for integration testing.\n * Supports global defaults and per-session overrides.\n */\nexport class MockMode implements IVerificationMode {\n readonly name = 'mock';\n private defaultResult: VerificationResult;\n private delayMs: number;\n private sessionOverrides = new Map<string, VerificationResult>();\n\n constructor(config: MockModeConfig = {}) {\n this.defaultResult = config.defaultResult ?? { ...DEFAULT_RESULT };\n this.delayMs = config.delayMs ?? 0;\n }\n\n /** Set a per-session result override */\n setSessionResult(sessionId: string, result: VerificationResult): void {\n this.sessionOverrides.set(sessionId, result);\n }\n\n /** Clear a per-session result override */\n clearSessionResult(sessionId: string): void {\n this.sessionOverrides.delete(sessionId);\n }\n\n async processCallback(session: VerificationSession, _walletResponse: unknown): Promise<VerificationResult> {\n if (this.delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, this.delayMs));\n }\n return this.sessionOverrides.get(session.id) ?? { ...this.defaultResult };\n }\n\n async simulateCompletion(session: VerificationSession): Promise<VerificationResult> {\n return this.processCallback(session, {});\n }\n}\n","import { EventEmitter } from 'node:events';\n\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { SessionNotFoundError, SessionExpiredError } from './errors.js';\nimport type { IVerificationMode } from './modes/mode.interface.js';\nimport { InMemorySessionStore } from './storage/memory.store.js';\nimport type { ISessionStore } from './storage/store.interface.js';\nimport type { VerificationServiceConfig } from './types/config.js';\nimport type { VerificationSession, VerificationResult, CreateSessionInput } from './types/session.js';\nimport { VerificationStatus } from './types/verification.js';\n\nconst DEFAULT_TTL_MS = 300_000; // 5 minutes\nconst DEFAULT_WALLET_BASE_URL = 'openid4vp://verify';\n\n/**\n * EUDI Wallet verification session orchestrator.\n *\n * Manages the lifecycle of verification sessions: creation, status tracking,\n * wallet callback handling, expiration, and event emission.\n *\n * Transport-agnostic — consumers wire events to SSE, WebSocket, polling, etc.\n */\nexport class VerificationService extends EventEmitter {\n private store: ISessionStore;\n private mode: IVerificationMode;\n private sessionTtlMs: number;\n private walletBaseUrl: string;\n /** Track session IDs for cleanup (store interface has no list method) */\n private sessionIds = new Set<string>();\n\n constructor(config: VerificationServiceConfig) {\n super();\n this.mode = config.mode;\n this.store = config.store ?? new InMemorySessionStore();\n this.sessionTtlMs = config.sessionTtlMs ?? DEFAULT_TTL_MS;\n this.walletBaseUrl = config.walletBaseUrl ?? DEFAULT_WALLET_BASE_URL;\n }\n\n /**\n * Create a new verification session\n */\n async createSession(input: CreateSessionInput): Promise<VerificationSession> {\n const id = uuidv4();\n const now = new Date();\n\n const session: VerificationSession = {\n id,\n type: input.type,\n status: VerificationStatus.PENDING,\n walletUrl: '', // set below, may be async from mode\n countryWhitelist: input.countryWhitelist,\n countryBlacklist: input.countryBlacklist,\n redirectUrl: input.redirectUrl,\n metadata: input.metadata,\n createdAt: now,\n expiresAt: new Date(now.getTime() + this.sessionTtlMs),\n };\n\n session.walletUrl = this.mode.buildWalletUrl\n ? await this.mode.buildWalletUrl(id, input)\n : `${this.walletBaseUrl}?session=${id}`;\n\n await this.store.set(session);\n this.sessionIds.add(id);\n this.emit('session:created', session);\n\n // If mode supports auto-completion (DemoMode), trigger it in background\n if (this.mode.simulateCompletion) {\n this.mode\n .simulateCompletion(session)\n .then(async (result) => {\n // Only auto-complete if session is still pending\n const current = await this.store.get(id);\n if (current && current.status === VerificationStatus.PENDING) {\n await this.completeSession(current, result);\n }\n })\n .catch(() => {\n // Ignore simulation errors (session may have been completed manually)\n });\n }\n\n return session;\n }\n\n /**\n * Get a session by ID\n * @throws SessionNotFoundError\n */\n async getSession(id: string): Promise<VerificationSession> {\n const session = await this.store.get(id);\n if (!session) {\n throw new SessionNotFoundError(id);\n }\n return session;\n }\n\n /**\n * Handle a callback from the wallet\n * @throws SessionNotFoundError\n * @throws SessionExpiredError\n */\n async handleCallback(sessionId: string, walletResponse: unknown): Promise<VerificationResult> {\n const session = await this.store.get(sessionId);\n if (!session) {\n throw new SessionNotFoundError(sessionId);\n }\n if (new Date() > session.expiresAt) {\n throw new SessionExpiredError(sessionId);\n }\n\n const result = await this.mode.processCallback(session, walletResponse);\n await this.completeSession(session, result);\n return result;\n }\n\n /**\n * Remove expired sessions from the store\n * @returns Number of sessions cleaned up\n */\n async cleanupExpired(): Promise<number> {\n const now = new Date();\n let count = 0;\n\n for (const id of this.sessionIds) {\n const session = await this.store.get(id);\n if (!session) {\n this.sessionIds.delete(id);\n continue;\n }\n if (now > session.expiresAt && session.status === VerificationStatus.PENDING) {\n const expired = { ...session, status: VerificationStatus.EXPIRED };\n await this.store.set(expired);\n await this.store.delete(id);\n this.sessionIds.delete(id);\n this.emit('session:expired', expired);\n count++;\n }\n }\n\n return count;\n }\n\n private async completeSession(session: VerificationSession, result: VerificationResult): Promise<void> {\n const status = result.verified ? VerificationStatus.VERIFIED : VerificationStatus.REJECTED;\n const updated: VerificationSession = {\n ...session,\n status,\n completedAt: new Date(),\n result,\n };\n\n await this.store.set(updated);\n\n if (result.verified) {\n this.emit('session:verified', updated, result);\n } else {\n this.emit('session:rejected', updated, result.rejectionReason);\n }\n }\n}\n","// @openeudi/core — EUDI Wallet verification protocol engine\nexport const VERSION = '0.1.0';\n\n// Types\nexport { VerificationType, VerificationStatus } from './types/index.js';\n\nexport type {\n VerificationSession,\n VerificationResult,\n CreateSessionInput,\n VerificationServiceConfig,\n} from './types/index.js';\n\n// Errors\nexport { SessionNotFoundError, SessionExpiredError } from './errors.js';\n\n// Storage\nexport type { ISessionStore } from './storage/store.interface.js';\nexport { InMemorySessionStore } from './storage/memory.store.js';\n\n// Modes\nexport type { IVerificationMode } from './modes/mode.interface.js';\nexport { DemoMode } from './modes/demo.mode.js';\nexport type { DemoModeConfig } from './modes/demo.mode.js';\nexport { MockMode } from './modes/mock.mode.js';\nexport type { MockModeConfig } from './modes/mock.mode.js';\n\n// Service\nexport { VerificationService } from './verification.service.js';\n"]}
|
package/dist/qr.cjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/qr.ts
|
|
4
|
+
async function generateQRCode(url) {
|
|
5
|
+
try {
|
|
6
|
+
const QRCode = await import('qrcode');
|
|
7
|
+
return await QRCode.toDataURL(url, {
|
|
8
|
+
width: 300,
|
|
9
|
+
margin: 2,
|
|
10
|
+
color: { dark: "#000000", light: "#ffffff" }
|
|
11
|
+
});
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (error instanceof Error && error.message.includes("Cannot find module")) {
|
|
14
|
+
throw new Error('@openeudi/core/qr requires the "qrcode" package. Install it: npm install qrcode');
|
|
15
|
+
}
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.generateQRCode = generateQRCode;
|
|
21
|
+
//# sourceMappingURL=qr.cjs.map
|
|
22
|
+
//# sourceMappingURL=qr.cjs.map
|
package/dist/qr.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/qr.ts"],"names":[],"mappings":";;;AAUA,eAAsB,eAAe,GAAA,EAA8B;AAC/D,EAAA,IAAI;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,OAAO,QAAQ,CAAA;AACpC,IAAA,OAAO,MAAM,MAAA,CAAO,SAAA,CAAU,GAAA,EAAK;AAAA,MAC/B,KAAA,EAAO,GAAA;AAAA,MACP,MAAA,EAAQ,CAAA;AAAA,MACR,KAAA,EAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAO,SAAA;AAAU,KAC9C,CAAA;AAAA,EACL,SAAS,KAAA,EAAO;AACZ,IAAA,IAAI,iBAAiB,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,oBAAoB,CAAA,EAAG;AACxE,MAAA,MAAM,IAAI,MAAM,iFAAiF,CAAA;AAAA,IACrG;AACA,IAAA,MAAM,KAAA;AAAA,EACV;AACJ","file":"qr.cjs","sourcesContent":["/**\n * Generate a QR code data URI from a wallet URL.\n *\n * Requires `qrcode` as an optional peer dependency.\n * Import from `@openeudi/core/qr` to use this function.\n *\n * @param url - The wallet URL to encode as QR code\n * @returns Base64 PNG data URI string\n * @throws Error if `qrcode` package is not installed\n */\nexport async function generateQRCode(url: string): Promise<string> {\n try {\n const QRCode = await import('qrcode');\n return await QRCode.toDataURL(url, {\n width: 300,\n margin: 2,\n color: { dark: '#000000', light: '#ffffff' },\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('Cannot find module')) {\n throw new Error('@openeudi/core/qr requires the \"qrcode\" package. Install it: npm install qrcode');\n }\n throw error;\n }\n}\n"]}
|
package/dist/qr.d.cts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a QR code data URI from a wallet URL.
|
|
3
|
+
*
|
|
4
|
+
* Requires `qrcode` as an optional peer dependency.
|
|
5
|
+
* Import from `@openeudi/core/qr` to use this function.
|
|
6
|
+
*
|
|
7
|
+
* @param url - The wallet URL to encode as QR code
|
|
8
|
+
* @returns Base64 PNG data URI string
|
|
9
|
+
* @throws Error if `qrcode` package is not installed
|
|
10
|
+
*/
|
|
11
|
+
declare function generateQRCode(url: string): Promise<string>;
|
|
12
|
+
|
|
13
|
+
export { generateQRCode };
|
package/dist/qr.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a QR code data URI from a wallet URL.
|
|
3
|
+
*
|
|
4
|
+
* Requires `qrcode` as an optional peer dependency.
|
|
5
|
+
* Import from `@openeudi/core/qr` to use this function.
|
|
6
|
+
*
|
|
7
|
+
* @param url - The wallet URL to encode as QR code
|
|
8
|
+
* @returns Base64 PNG data URI string
|
|
9
|
+
* @throws Error if `qrcode` package is not installed
|
|
10
|
+
*/
|
|
11
|
+
declare function generateQRCode(url: string): Promise<string>;
|
|
12
|
+
|
|
13
|
+
export { generateQRCode };
|
package/dist/qr.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/qr.ts
|
|
2
|
+
async function generateQRCode(url) {
|
|
3
|
+
try {
|
|
4
|
+
const QRCode = await import('qrcode');
|
|
5
|
+
return await QRCode.toDataURL(url, {
|
|
6
|
+
width: 300,
|
|
7
|
+
margin: 2,
|
|
8
|
+
color: { dark: "#000000", light: "#ffffff" }
|
|
9
|
+
});
|
|
10
|
+
} catch (error) {
|
|
11
|
+
if (error instanceof Error && error.message.includes("Cannot find module")) {
|
|
12
|
+
throw new Error('@openeudi/core/qr requires the "qrcode" package. Install it: npm install qrcode');
|
|
13
|
+
}
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { generateQRCode };
|
|
19
|
+
//# sourceMappingURL=qr.js.map
|
|
20
|
+
//# sourceMappingURL=qr.js.map
|
package/dist/qr.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/qr.ts"],"names":[],"mappings":";AAUA,eAAsB,eAAe,GAAA,EAA8B;AAC/D,EAAA,IAAI;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,OAAO,QAAQ,CAAA;AACpC,IAAA,OAAO,MAAM,MAAA,CAAO,SAAA,CAAU,GAAA,EAAK;AAAA,MAC/B,KAAA,EAAO,GAAA;AAAA,MACP,MAAA,EAAQ,CAAA;AAAA,MACR,KAAA,EAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAO,SAAA;AAAU,KAC9C,CAAA;AAAA,EACL,SAAS,KAAA,EAAO;AACZ,IAAA,IAAI,iBAAiB,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,oBAAoB,CAAA,EAAG;AACxE,MAAA,MAAM,IAAI,MAAM,iFAAiF,CAAA;AAAA,IACrG;AACA,IAAA,MAAM,KAAA;AAAA,EACV;AACJ","file":"qr.js","sourcesContent":["/**\n * Generate a QR code data URI from a wallet URL.\n *\n * Requires `qrcode` as an optional peer dependency.\n * Import from `@openeudi/core/qr` to use this function.\n *\n * @param url - The wallet URL to encode as QR code\n * @returns Base64 PNG data URI string\n * @throws Error if `qrcode` package is not installed\n */\nexport async function generateQRCode(url: string): Promise<string> {\n try {\n const QRCode = await import('qrcode');\n return await QRCode.toDataURL(url, {\n width: 300,\n margin: 2,\n color: { dark: '#000000', light: '#ffffff' },\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('Cannot find module')) {\n throw new Error('@openeudi/core/qr requires the \"qrcode\" package. Install it: npm install qrcode');\n }\n throw error;\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openeudi/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Framework-agnostic EUDI Wallet verification protocol engine",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./qr": {
|
|
22
|
+
"import": {
|
|
23
|
+
"types": "./dist/qr.d.ts",
|
|
24
|
+
"default": "./dist/qr.js"
|
|
25
|
+
},
|
|
26
|
+
"require": {
|
|
27
|
+
"types": "./dist/qr.d.cts",
|
|
28
|
+
"default": "./dist/qr.cjs"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"dev": "tsup --watch",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
"type-check": "tsc --noEmit"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"uuid": "^11.1.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"qrcode": "^1.5.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"qrcode": {
|
|
52
|
+
"optional": true
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"qrcode": "^1.5.4",
|
|
57
|
+
"@types/qrcode": "^1.5.5",
|
|
58
|
+
"@types/uuid": "^10.0.0",
|
|
59
|
+
"typescript": "^5.8.3",
|
|
60
|
+
"tsup": "^8.5.1",
|
|
61
|
+
"vitest": "^4.0.18"
|
|
62
|
+
},
|
|
63
|
+
"keywords": [
|
|
64
|
+
"eudi",
|
|
65
|
+
"eidas",
|
|
66
|
+
"verification",
|
|
67
|
+
"identity",
|
|
68
|
+
"wallet",
|
|
69
|
+
"openid4vp",
|
|
70
|
+
"age-verification"
|
|
71
|
+
],
|
|
72
|
+
"repository": {
|
|
73
|
+
"type": "git",
|
|
74
|
+
"url": "https://github.com/openeudi/core"
|
|
75
|
+
},
|
|
76
|
+
"homepage": "https://github.com/openeudi/core#readme",
|
|
77
|
+
"bugs": {
|
|
78
|
+
"url": "https://github.com/openeudi/core/issues"
|
|
79
|
+
},
|
|
80
|
+
"author": "OpenEUDI Contributors"
|
|
81
|
+
}
|