@learncard/partner-connect 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partner-connect.esm.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * LearnCard Partner Connect SDK\n * \n * A Promise-based JavaScript utility for managing cross-origin message communication\n * between partner apps and the LearnCard host application.\n * \n * @example\n * ```typescript\n * import { createPartnerConnect } from '@learncard/partner-connect';\n * \n * const learnCard = createPartnerConnect({\n * hostOrigin: 'https://learncard.app'\n * });\n * \n * // Request user identity (SSO)\n * const identity = await learnCard.requestIdentity();\n * console.log('User DID:', identity.user.did);\n * ```\n */\n\nimport type {\n PartnerConnectOptions,\n IdentityResponse,\n SendCredentialResponse,\n VerifiablePresentationRequest,\n CredentialSearchResponse,\n CredentialSpecificResponse,\n ConsentResponse,\n TemplateIssueResponse,\n LearnCardError,\n PostMessageRequest,\n PostMessageResponse,\n PendingRequest,\n} from './types';\n\nexport type * from './types';\n\n/**\n * LearnCard Partner Connect SDK class\n */\nexport class PartnerConnect {\n /** Default host origin (security anchor) */\n public static readonly DEFAULT_HOST_ORIGIN = 'https://learncard.app';\n \n private hostOrigins: string[] = ['https://learncard.app'];\n private activeHostOrigin: string = 'https://learncard.app';\n private allowNativeAppOrigins: boolean = true;\n private protocol: string = 'LEARNCARD_V1';\n private requestTimeout: number = 30000;\n private pendingRequests: Map<string, PendingRequest>;\n private messageListener: ((event: MessageEvent) => void) | null = null;\n private isInitialized = false;\n\n constructor(options?: PartnerConnectOptions) {\n // Normalize hostOrigin to an array for whitelist validation\n const hostOrigin = options?.hostOrigin || PartnerConnect.DEFAULT_HOST_ORIGIN;\n this.hostOrigins = Array.isArray(hostOrigin) ? hostOrigin : [hostOrigin];\n \n this.protocol = options?.protocol || 'LEARNCARD_V1';\n this.requestTimeout = options?.requestTimeout || 30000;\n this.allowNativeAppOrigins = options?.allowNativeAppOrigins ?? true;\n this.pendingRequests = new Map();\n this.configureActiveOrigin();\n this.setupMessageListener();\n }\n\n /**\n * Configure the active host origin using the following hierarchy:\n * 1. Check for `lc_host_override` query parameter (for staging/testing)\n * 2. Fall back to first configured origin\n * 3. Fall back to DEFAULT_HOST_ORIGIN\n * \n * This origin will be used for all outgoing messages and incoming message validation.\n */\n private configureActiveOrigin(): void {\n if (typeof window === 'undefined') {\n this.activeHostOrigin = this.hostOrigins[0] || PartnerConnect.DEFAULT_HOST_ORIGIN;\n return;\n }\n\n try {\n // Check for lc_host_override query parameter\n const urlParams = new URLSearchParams(window.location.search);\n const hostOverride = urlParams.get('lc_host_override');\n\n if (hostOverride) {\n // Validate override against whitelist (if provided)\n if (this.hostOrigins.length > 0 && !this.isOriginInWhitelist(hostOverride)) {\n console.warn(\n '[LearnCard SDK] lc_host_override value is not in the configured whitelist:',\n hostOverride,\n 'Allowed:',\n this.hostOrigins\n );\n this.activeHostOrigin = this.hostOrigins[0] || PartnerConnect.DEFAULT_HOST_ORIGIN;\n } else {\n this.activeHostOrigin = hostOverride;\n console.log('[LearnCard SDK] Using lc_host_override:', hostOverride);\n }\n } else {\n // Use first configured origin or default\n this.activeHostOrigin = this.hostOrigins[0] || PartnerConnect.DEFAULT_HOST_ORIGIN;\n console.log('[LearnCard SDK] Using configured origin:', this.activeHostOrigin);\n }\n } catch (error) {\n console.error('[LearnCard SDK] Error configuring active origin:', error);\n this.activeHostOrigin = this.hostOrigins[0] || PartnerConnect.DEFAULT_HOST_ORIGIN;\n }\n }\n\n private isOriginNativeApp(origin: string): boolean {\n return origin.startsWith('capacitor://') || origin.startsWith('ionic://') || origin.startsWith('https://localhost') || origin.startsWith('http://localhost') || origin.startsWith('http://127.0.0.1') || origin.startsWith('http://192.168.1.164')\n }\n\n /**\n * Check if an origin is in the configured whitelist\n */\n private isOriginInWhitelist(origin: string): boolean {\n return this.hostOrigins.includes(origin) || (this.allowNativeAppOrigins && this.isOriginNativeApp(origin));\n }\n\n /**\n * Check if an event origin is valid against the active host origin\n * \n * Security Rule: Incoming messages must exactly match the active host origin.\n * This prevents malicious actors from spoofing origins via query parameters.\n * \n * @param eventOrigin - The origin from the MessageEvent\n * @returns true if the origin is valid\n */\n private isValidOrigin(eventOrigin: string): boolean {\n // STRICT: Exact match with active host origin only\n return eventOrigin === this.activeHostOrigin;\n }\n\n /**\n * Set up the central message listener to handle responses from the LearnCard host\n */\n private setupMessageListener(): void {\n if (typeof window === 'undefined') {\n throw new Error('PartnerConnect SDK can only be used in a browser environment');\n }\n\n this.messageListener = (event: MessageEvent) => {\n // SECURITY CHECK 1: Strict origin validation - must exactly match active host origin\n if (!this.isValidOrigin(event.origin)) {\n // Silently ignore messages from unauthorized origins\n return;\n }\n\n const data = event.data as PostMessageResponse;\n\n // SECURITY CHECK 2: Validate protocol and requestId\n if (data.protocol !== this.protocol || !data.requestId) {\n return;\n }\n\n // Look up the pending request\n const pending = this.pendingRequests.get(data.requestId);\n if (!pending) {\n return; // Ignore stale or unrecognized responses\n }\n\n // Clean up\n clearTimeout(pending.timeoutId);\n this.pendingRequests.delete(data.requestId);\n\n // Resolve or reject the promise\n if (data.type === 'SUCCESS') {\n pending.resolve(data.data);\n } else if (data.type === 'ERROR') {\n pending.reject(data.error || { code: 'UNKNOWN_ERROR', message: 'An unknown error occurred' });\n }\n };\n\n window.addEventListener('message', this.messageListener);\n this.isInitialized = true;\n }\n\n /**\n * Generate a unique request ID\n */\n private generateRequestId(action: string): string {\n return `${action}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n\n /**\n * Send a message to the parent window and return a Promise\n */\n private sendMessage<T = unknown>(action: string, payload?: unknown): Promise<T> {\n if (!this.isInitialized) {\n return Promise.reject({\n code: 'SDK_NOT_INITIALIZED',\n message: 'SDK is not initialized',\n } as LearnCardError);\n }\n\n return new Promise<T>((resolve, reject) => {\n const requestId = this.generateRequestId(action);\n\n // Set up timeout\n const timeoutId = setTimeout(() => {\n if (this.pendingRequests.has(requestId)) {\n this.pendingRequests.delete(requestId);\n reject({\n code: 'LC_TIMEOUT',\n message: `Request ${action} timed out after ${this.requestTimeout}ms`,\n } as LearnCardError);\n }\n }, this.requestTimeout);\n\n // Store the pending request\n this.pendingRequests.set(requestId, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timeoutId,\n });\n\n // Construct the message\n const message: PostMessageRequest = {\n protocol: this.protocol,\n action,\n requestId,\n payload,\n };\n\n // Send to parent window with the active host origin (configured or overridden)\n window.parent.postMessage(message, this.activeHostOrigin);\n });\n }\n\n /**\n * Request user identity (Single Sign-On)\n * \n * @returns Promise resolving to user identity including DID and JWT token\n * @throws {LearnCardError} When user is not authenticated or request fails\n * \n * @example\n * ```typescript\n * const identity = await learnCard.requestIdentity();\n * console.log('User DID:', identity.user.did);\n * console.log('JWT Token:', identity.token);\n * ```\n */\n public requestIdentity(): Promise<IdentityResponse> {\n return this.sendMessage<IdentityResponse>('REQUEST_IDENTITY', { challenge: `${Date.now()}-${Math.random().toString(36).substring(2, 9)}` });\n }\n\n /**\n * Send a credential to the user's LearnCard wallet\n * \n * @param credential - The verifiable credential to send\n * @returns Promise resolving to credential ID\n * \n * @example\n * ```typescript\n * const response = await learnCard.sendCredential({\n * '@context': ['https://www.w3.org/2018/credentials/v1'],\n * type: ['VerifiableCredential'],\n * credentialSubject: { id: 'did:example:123' }\n * });\n * console.log('Credential ID:', response.credentialId);\n * ```\n */\n public sendCredential(credential: unknown): Promise<SendCredentialResponse> {\n return this.sendMessage<SendCredentialResponse>('SEND_CREDENTIAL', { credential });\n }\n\n /**\n * Launch a feature in the LearnCard host application\n * \n * @param featurePath - Path to the feature (e.g., '/ai/topics')\n * @param initialPrompt - Optional initial prompt or data\n * \n * @example\n * ```typescript\n * await learnCard.launchFeature(\n * '/ai/topics?shortCircuitStep=newTopic',\n * 'Help me understand cryptography'\n * );\n * ```\n */\n public launchFeature(featurePath: string, initialPrompt?: string): Promise<void> {\n return this.sendMessage<void>('LAUNCH_FEATURE', { featurePath, initialPrompt });\n }\n\n /**\n * Request credentials from the user's wallet using a query\n * \n * @param verifiablePresentationRequest - VPR with query criteria\n * @returns Promise resolving to verifiable presentation\n * \n * @example\n * ```typescript\n * const response = await learnCard.askCredentialSearch({\n * query: [{\n * type: 'QueryByTitle',\n * credentialQuery: {\n * reason: 'We need to verify your skills',\n * title: 'JavaScript Expert'\n * }\n * }],\n * challenge: 'challenge-123',\n * domain: window.location.hostname\n * });\n * \n * if (response.verifiablePresentation) {\n * console.log('Received credentials:', response.verifiablePresentation.verifiableCredential);\n * }\n * ```\n */\n public askCredentialSearch(\n verifiablePresentationRequest: VerifiablePresentationRequest\n ): Promise<CredentialSearchResponse> {\n return this.sendMessage<CredentialSearchResponse>('ASK_CREDENTIAL_SEARCH', {\n verifiablePresentationRequest,\n });\n }\n\n /**\n * Request a specific credential by ID\n * \n * @param credentialId - The ID of the credential to request\n * @returns Promise resolving to the credential\n * \n * @example\n * ```typescript\n * const response = await learnCard.askCredentialSpecific('credential-id-123');\n * if (response.credential) {\n * console.log('Received credential:', response.credential);\n * }\n * ```\n */\n public askCredentialSpecific(credentialId: string): Promise<CredentialSpecificResponse> {\n return this.sendMessage<CredentialSpecificResponse>('ASK_CREDENTIAL_SPECIFIC', {\n credentialId,\n });\n }\n\n /**\n * Request user consent for permissions\n * \n * @param contractUri - URI of the consent contract\n * @returns Promise resolving to consent response\n * \n * @example\n * ```typescript\n * const response = await learnCard.requestConsent('lc:network:network.learncard.com/trpc:contract:abc123');\n * if (response.granted) {\n * console.log('User granted consent');\n * }\n * ```\n */\n public requestConsent(contractUri: string): Promise<ConsentResponse> {\n return this.sendMessage<ConsentResponse>('REQUEST_CONSENT', { contractUri });\n }\n\n /**\n * Initiate a template-based credential issuance flow\n * \n * @param templateId - ID of the template/boost to issue\n * @param draftRecipients - Optional array of recipient DIDs\n * @returns Promise resolving to template issue response\n * \n * @example\n * ```typescript\n * const response = await learnCard.initiateTemplateIssue(\n * 'lc:network:network.learncard.com/trpc:boost:xyz789',\n * ['did:key:abc', 'did:key:def']\n * );\n * \n * if (response.issued) {\n * console.log('Template issued successfully');\n * }\n * ```\n */\n public initiateTemplateIssue(\n templateId: string,\n draftRecipients?: string[]\n ): Promise<TemplateIssueResponse> {\n return this.sendMessage<TemplateIssueResponse>('INITIATE_TEMPLATE_ISSUE', {\n templateId,\n draftRecipients: draftRecipients || [],\n });\n }\n\n /**\n * Clean up the SDK and remove event listeners\n */\n public destroy(): void {\n if (this.messageListener) {\n window.removeEventListener('message', this.messageListener);\n this.messageListener = null;\n }\n\n // Reject all pending requests\n for (const [requestId, pending] of this.pendingRequests.entries()) {\n clearTimeout(pending.timeoutId);\n pending.reject({\n code: 'SDK_DESTROYED',\n message: 'SDK was destroyed before request completed',\n });\n }\n\n this.pendingRequests.clear();\n this.isInitialized = false;\n }\n}\n\n/**\n * Factory function to create a PartnerConnect instance\n * \n * @param options - Configuration options\n * @returns PartnerConnect instance\n * \n * @example\n * ```typescript\n * const learnCard = createPartnerConnect({\n * hostOrigin: 'https://learncard.app',\n * protocol: 'LEARNCARD_V1',\n * requestTimeout: 30000\n * });\n * ```\n */\nexport function createPartnerConnect(options: PartnerConnectOptions): PartnerConnect {\n return new PartnerConnect(options);\n}\n\n// Default export for convenience\nexport default createPartnerConnect;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,330 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
+ const _PartnerConnect = class _PartnerConnect {
9
+ constructor(options) {
10
+ __publicField(this, "hostOrigins", ["https://learncard.app"]);
11
+ __publicField(this, "activeHostOrigin", "https://learncard.app");
12
+ __publicField(this, "allowNativeAppOrigins", true);
13
+ __publicField(this, "protocol", "LEARNCARD_V1");
14
+ __publicField(this, "requestTimeout", 3e4);
15
+ __publicField(this, "pendingRequests");
16
+ __publicField(this, "messageListener", null);
17
+ __publicField(this, "isInitialized", false);
18
+ var _a;
19
+ const hostOrigin = (options == null ? void 0 : options.hostOrigin) || _PartnerConnect.DEFAULT_HOST_ORIGIN;
20
+ this.hostOrigins = Array.isArray(hostOrigin) ? hostOrigin : [hostOrigin];
21
+ this.protocol = (options == null ? void 0 : options.protocol) || "LEARNCARD_V1";
22
+ this.requestTimeout = (options == null ? void 0 : options.requestTimeout) || 3e4;
23
+ this.allowNativeAppOrigins = (_a = options == null ? void 0 : options.allowNativeAppOrigins) != null ? _a : true;
24
+ this.pendingRequests = /* @__PURE__ */ new Map();
25
+ this.configureActiveOrigin();
26
+ this.setupMessageListener();
27
+ }
28
+ /**
29
+ * Configure the active host origin using the following hierarchy:
30
+ * 1. Check for `lc_host_override` query parameter (for staging/testing)
31
+ * 2. Fall back to first configured origin
32
+ * 3. Fall back to DEFAULT_HOST_ORIGIN
33
+ *
34
+ * This origin will be used for all outgoing messages and incoming message validation.
35
+ */
36
+ configureActiveOrigin() {
37
+ if (typeof window === "undefined") {
38
+ this.activeHostOrigin = this.hostOrigins[0] || _PartnerConnect.DEFAULT_HOST_ORIGIN;
39
+ return;
40
+ }
41
+ try {
42
+ const urlParams = new URLSearchParams(window.location.search);
43
+ const hostOverride = urlParams.get("lc_host_override");
44
+ if (hostOverride) {
45
+ if (this.hostOrigins.length > 0 && !this.isOriginInWhitelist(hostOverride)) {
46
+ console.warn(
47
+ "[LearnCard SDK] lc_host_override value is not in the configured whitelist:",
48
+ hostOverride,
49
+ "Allowed:",
50
+ this.hostOrigins
51
+ );
52
+ this.activeHostOrigin = this.hostOrigins[0] || _PartnerConnect.DEFAULT_HOST_ORIGIN;
53
+ } else {
54
+ this.activeHostOrigin = hostOverride;
55
+ console.log("[LearnCard SDK] Using lc_host_override:", hostOverride);
56
+ }
57
+ } else {
58
+ this.activeHostOrigin = this.hostOrigins[0] || _PartnerConnect.DEFAULT_HOST_ORIGIN;
59
+ console.log("[LearnCard SDK] Using configured origin:", this.activeHostOrigin);
60
+ }
61
+ } catch (error) {
62
+ console.error("[LearnCard SDK] Error configuring active origin:", error);
63
+ this.activeHostOrigin = this.hostOrigins[0] || _PartnerConnect.DEFAULT_HOST_ORIGIN;
64
+ }
65
+ }
66
+ isOriginNativeApp(origin) {
67
+ return origin.startsWith("capacitor://") || origin.startsWith("ionic://") || origin.startsWith("https://localhost") || origin.startsWith("http://localhost") || origin.startsWith("http://127.0.0.1") || origin.startsWith("http://192.168.1.164");
68
+ }
69
+ /**
70
+ * Check if an origin is in the configured whitelist
71
+ */
72
+ isOriginInWhitelist(origin) {
73
+ return this.hostOrigins.includes(origin) || this.allowNativeAppOrigins && this.isOriginNativeApp(origin);
74
+ }
75
+ /**
76
+ * Check if an event origin is valid against the active host origin
77
+ *
78
+ * Security Rule: Incoming messages must exactly match the active host origin.
79
+ * This prevents malicious actors from spoofing origins via query parameters.
80
+ *
81
+ * @param eventOrigin - The origin from the MessageEvent
82
+ * @returns true if the origin is valid
83
+ */
84
+ isValidOrigin(eventOrigin) {
85
+ return eventOrigin === this.activeHostOrigin;
86
+ }
87
+ /**
88
+ * Set up the central message listener to handle responses from the LearnCard host
89
+ */
90
+ setupMessageListener() {
91
+ if (typeof window === "undefined") {
92
+ throw new Error("PartnerConnect SDK can only be used in a browser environment");
93
+ }
94
+ this.messageListener = (event) => {
95
+ if (!this.isValidOrigin(event.origin)) {
96
+ return;
97
+ }
98
+ const data = event.data;
99
+ if (data.protocol !== this.protocol || !data.requestId) {
100
+ return;
101
+ }
102
+ const pending = this.pendingRequests.get(data.requestId);
103
+ if (!pending) {
104
+ return;
105
+ }
106
+ clearTimeout(pending.timeoutId);
107
+ this.pendingRequests.delete(data.requestId);
108
+ if (data.type === "SUCCESS") {
109
+ pending.resolve(data.data);
110
+ } else if (data.type === "ERROR") {
111
+ pending.reject(data.error || { code: "UNKNOWN_ERROR", message: "An unknown error occurred" });
112
+ }
113
+ };
114
+ window.addEventListener("message", this.messageListener);
115
+ this.isInitialized = true;
116
+ }
117
+ /**
118
+ * Generate a unique request ID
119
+ */
120
+ generateRequestId(action) {
121
+ return `${action}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
122
+ }
123
+ /**
124
+ * Send a message to the parent window and return a Promise
125
+ */
126
+ sendMessage(action, payload) {
127
+ if (!this.isInitialized) {
128
+ return Promise.reject({
129
+ code: "SDK_NOT_INITIALIZED",
130
+ message: "SDK is not initialized"
131
+ });
132
+ }
133
+ return new Promise((resolve, reject) => {
134
+ const requestId = this.generateRequestId(action);
135
+ const timeoutId = setTimeout(() => {
136
+ if (this.pendingRequests.has(requestId)) {
137
+ this.pendingRequests.delete(requestId);
138
+ reject({
139
+ code: "LC_TIMEOUT",
140
+ message: `Request ${action} timed out after ${this.requestTimeout}ms`
141
+ });
142
+ }
143
+ }, this.requestTimeout);
144
+ this.pendingRequests.set(requestId, {
145
+ resolve,
146
+ reject,
147
+ timeoutId
148
+ });
149
+ const message = {
150
+ protocol: this.protocol,
151
+ action,
152
+ requestId,
153
+ payload
154
+ };
155
+ window.parent.postMessage(message, this.activeHostOrigin);
156
+ });
157
+ }
158
+ /**
159
+ * Request user identity (Single Sign-On)
160
+ *
161
+ * @returns Promise resolving to user identity including DID and JWT token
162
+ * @throws {LearnCardError} When user is not authenticated or request fails
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const identity = await learnCard.requestIdentity();
167
+ * console.log('User DID:', identity.user.did);
168
+ * console.log('JWT Token:', identity.token);
169
+ * ```
170
+ */
171
+ requestIdentity() {
172
+ return this.sendMessage("REQUEST_IDENTITY", { challenge: `${Date.now()}-${Math.random().toString(36).substring(2, 9)}` });
173
+ }
174
+ /**
175
+ * Send a credential to the user's LearnCard wallet
176
+ *
177
+ * @param credential - The verifiable credential to send
178
+ * @returns Promise resolving to credential ID
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const response = await learnCard.sendCredential({
183
+ * '@context': ['https://www.w3.org/2018/credentials/v1'],
184
+ * type: ['VerifiableCredential'],
185
+ * credentialSubject: { id: 'did:example:123' }
186
+ * });
187
+ * console.log('Credential ID:', response.credentialId);
188
+ * ```
189
+ */
190
+ sendCredential(credential) {
191
+ return this.sendMessage("SEND_CREDENTIAL", { credential });
192
+ }
193
+ /**
194
+ * Launch a feature in the LearnCard host application
195
+ *
196
+ * @param featurePath - Path to the feature (e.g., '/ai/topics')
197
+ * @param initialPrompt - Optional initial prompt or data
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * await learnCard.launchFeature(
202
+ * '/ai/topics?shortCircuitStep=newTopic',
203
+ * 'Help me understand cryptography'
204
+ * );
205
+ * ```
206
+ */
207
+ launchFeature(featurePath, initialPrompt) {
208
+ return this.sendMessage("LAUNCH_FEATURE", { featurePath, initialPrompt });
209
+ }
210
+ /**
211
+ * Request credentials from the user's wallet using a query
212
+ *
213
+ * @param verifiablePresentationRequest - VPR with query criteria
214
+ * @returns Promise resolving to verifiable presentation
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * const response = await learnCard.askCredentialSearch({
219
+ * query: [{
220
+ * type: 'QueryByTitle',
221
+ * credentialQuery: {
222
+ * reason: 'We need to verify your skills',
223
+ * title: 'JavaScript Expert'
224
+ * }
225
+ * }],
226
+ * challenge: 'challenge-123',
227
+ * domain: window.location.hostname
228
+ * });
229
+ *
230
+ * if (response.verifiablePresentation) {
231
+ * console.log('Received credentials:', response.verifiablePresentation.verifiableCredential);
232
+ * }
233
+ * ```
234
+ */
235
+ askCredentialSearch(verifiablePresentationRequest) {
236
+ return this.sendMessage("ASK_CREDENTIAL_SEARCH", {
237
+ verifiablePresentationRequest
238
+ });
239
+ }
240
+ /**
241
+ * Request a specific credential by ID
242
+ *
243
+ * @param credentialId - The ID of the credential to request
244
+ * @returns Promise resolving to the credential
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * const response = await learnCard.askCredentialSpecific('credential-id-123');
249
+ * if (response.credential) {
250
+ * console.log('Received credential:', response.credential);
251
+ * }
252
+ * ```
253
+ */
254
+ askCredentialSpecific(credentialId) {
255
+ return this.sendMessage("ASK_CREDENTIAL_SPECIFIC", {
256
+ credentialId
257
+ });
258
+ }
259
+ /**
260
+ * Request user consent for permissions
261
+ *
262
+ * @param contractUri - URI of the consent contract
263
+ * @returns Promise resolving to consent response
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * const response = await learnCard.requestConsent('lc:network:network.learncard.com/trpc:contract:abc123');
268
+ * if (response.granted) {
269
+ * console.log('User granted consent');
270
+ * }
271
+ * ```
272
+ */
273
+ requestConsent(contractUri) {
274
+ return this.sendMessage("REQUEST_CONSENT", { contractUri });
275
+ }
276
+ /**
277
+ * Initiate a template-based credential issuance flow
278
+ *
279
+ * @param templateId - ID of the template/boost to issue
280
+ * @param draftRecipients - Optional array of recipient DIDs
281
+ * @returns Promise resolving to template issue response
282
+ *
283
+ * @example
284
+ * ```typescript
285
+ * const response = await learnCard.initiateTemplateIssue(
286
+ * 'lc:network:network.learncard.com/trpc:boost:xyz789',
287
+ * ['did:key:abc', 'did:key:def']
288
+ * );
289
+ *
290
+ * if (response.issued) {
291
+ * console.log('Template issued successfully');
292
+ * }
293
+ * ```
294
+ */
295
+ initiateTemplateIssue(templateId, draftRecipients) {
296
+ return this.sendMessage("INITIATE_TEMPLATE_ISSUE", {
297
+ templateId,
298
+ draftRecipients: draftRecipients || []
299
+ });
300
+ }
301
+ /**
302
+ * Clean up the SDK and remove event listeners
303
+ */
304
+ destroy() {
305
+ if (this.messageListener) {
306
+ window.removeEventListener("message", this.messageListener);
307
+ this.messageListener = null;
308
+ }
309
+ for (const [requestId, pending] of this.pendingRequests.entries()) {
310
+ clearTimeout(pending.timeoutId);
311
+ pending.reject({
312
+ code: "SDK_DESTROYED",
313
+ message: "SDK was destroyed before request completed"
314
+ });
315
+ }
316
+ this.pendingRequests.clear();
317
+ this.isInitialized = false;
318
+ }
319
+ };
320
+ /** Default host origin (security anchor) */
321
+ __publicField(_PartnerConnect, "DEFAULT_HOST_ORIGIN", "https://learncard.app");
322
+ let PartnerConnect = _PartnerConnect;
323
+ function createPartnerConnect(options) {
324
+ return new PartnerConnect(options);
325
+ }
326
+
327
+ exports.PartnerConnect = PartnerConnect;
328
+ exports.createPartnerConnect = createPartnerConnect;
329
+ exports["default"] = createPartnerConnect;
330
+ //# sourceMappingURL=partner-connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partner-connect.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * LearnCard Partner Connect SDK\n * \n * A Promise-based JavaScript utility for managing cross-origin message communication\n * between partner apps and the LearnCard host application.\n * \n * @example\n * ```typescript\n * import { createPartnerConnect } from '@learncard/partner-connect';\n * \n * const learnCard = createPartnerConnect({\n * hostOrigin: 'https://learncard.app'\n * });\n * \n * // Request user identity (SSO)\n * const identity = await learnCard.requestIdentity();\n * console.log('User DID:', identity.user.did);\n * ```\n */\n\nimport type {\n PartnerConnectOptions,\n IdentityResponse,\n SendCredentialResponse,\n VerifiablePresentationRequest,\n CredentialSearchResponse,\n CredentialSpecificResponse,\n ConsentResponse,\n TemplateIssueResponse,\n LearnCardError,\n PostMessageRequest,\n PostMessageResponse,\n PendingRequest,\n} from './types';\n\nexport type * from './types';\n\n/**\n * LearnCard Partner Connect SDK class\n */\nexport class PartnerConnect {\n /** Default host origin (security anchor) */\n public static readonly DEFAULT_HOST_ORIGIN = 'https://learncard.app';\n \n private hostOrigins: string[] = ['https://learncard.app'];\n private activeHostOrigin: string = 'https://learncard.app';\n private allowNativeAppOrigins: boolean = true;\n private protocol: string = 'LEARNCARD_V1';\n private requestTimeout: number = 30000;\n private pendingRequests: Map<string, PendingRequest>;\n private messageListener: ((event: MessageEvent) => void) | null = null;\n private isInitialized = false;\n\n constructor(options?: PartnerConnectOptions) {\n // Normalize hostOrigin to an array for whitelist validation\n const hostOrigin = options?.hostOrigin || PartnerConnect.DEFAULT_HOST_ORIGIN;\n this.hostOrigins = Array.isArray(hostOrigin) ? hostOrigin : [hostOrigin];\n \n this.protocol = options?.protocol || 'LEARNCARD_V1';\n this.requestTimeout = options?.requestTimeout || 30000;\n this.allowNativeAppOrigins = options?.allowNativeAppOrigins ?? true;\n this.pendingRequests = new Map();\n this.configureActiveOrigin();\n this.setupMessageListener();\n }\n\n /**\n * Configure the active host origin using the following hierarchy:\n * 1. Check for `lc_host_override` query parameter (for staging/testing)\n * 2. Fall back to first configured origin\n * 3. Fall back to DEFAULT_HOST_ORIGIN\n * \n * This origin will be used for all outgoing messages and incoming message validation.\n */\n private configureActiveOrigin(): void {\n if (typeof window === 'undefined') {\n this.activeHostOrigin = this.hostOrigins[0] || PartnerConnect.DEFAULT_HOST_ORIGIN;\n return;\n }\n\n try {\n // Check for lc_host_override query parameter\n const urlParams = new URLSearchParams(window.location.search);\n const hostOverride = urlParams.get('lc_host_override');\n\n if (hostOverride) {\n // Validate override against whitelist (if provided)\n if (this.hostOrigins.length > 0 && !this.isOriginInWhitelist(hostOverride)) {\n console.warn(\n '[LearnCard SDK] lc_host_override value is not in the configured whitelist:',\n hostOverride,\n 'Allowed:',\n this.hostOrigins\n );\n this.activeHostOrigin = this.hostOrigins[0] || PartnerConnect.DEFAULT_HOST_ORIGIN;\n } else {\n this.activeHostOrigin = hostOverride;\n console.log('[LearnCard SDK] Using lc_host_override:', hostOverride);\n }\n } else {\n // Use first configured origin or default\n this.activeHostOrigin = this.hostOrigins[0] || PartnerConnect.DEFAULT_HOST_ORIGIN;\n console.log('[LearnCard SDK] Using configured origin:', this.activeHostOrigin);\n }\n } catch (error) {\n console.error('[LearnCard SDK] Error configuring active origin:', error);\n this.activeHostOrigin = this.hostOrigins[0] || PartnerConnect.DEFAULT_HOST_ORIGIN;\n }\n }\n\n private isOriginNativeApp(origin: string): boolean {\n return origin.startsWith('capacitor://') || origin.startsWith('ionic://') || origin.startsWith('https://localhost') || origin.startsWith('http://localhost') || origin.startsWith('http://127.0.0.1') || origin.startsWith('http://192.168.1.164')\n }\n\n /**\n * Check if an origin is in the configured whitelist\n */\n private isOriginInWhitelist(origin: string): boolean {\n return this.hostOrigins.includes(origin) || (this.allowNativeAppOrigins && this.isOriginNativeApp(origin));\n }\n\n /**\n * Check if an event origin is valid against the active host origin\n * \n * Security Rule: Incoming messages must exactly match the active host origin.\n * This prevents malicious actors from spoofing origins via query parameters.\n * \n * @param eventOrigin - The origin from the MessageEvent\n * @returns true if the origin is valid\n */\n private isValidOrigin(eventOrigin: string): boolean {\n // STRICT: Exact match with active host origin only\n return eventOrigin === this.activeHostOrigin;\n }\n\n /**\n * Set up the central message listener to handle responses from the LearnCard host\n */\n private setupMessageListener(): void {\n if (typeof window === 'undefined') {\n throw new Error('PartnerConnect SDK can only be used in a browser environment');\n }\n\n this.messageListener = (event: MessageEvent) => {\n // SECURITY CHECK 1: Strict origin validation - must exactly match active host origin\n if (!this.isValidOrigin(event.origin)) {\n // Silently ignore messages from unauthorized origins\n return;\n }\n\n const data = event.data as PostMessageResponse;\n\n // SECURITY CHECK 2: Validate protocol and requestId\n if (data.protocol !== this.protocol || !data.requestId) {\n return;\n }\n\n // Look up the pending request\n const pending = this.pendingRequests.get(data.requestId);\n if (!pending) {\n return; // Ignore stale or unrecognized responses\n }\n\n // Clean up\n clearTimeout(pending.timeoutId);\n this.pendingRequests.delete(data.requestId);\n\n // Resolve or reject the promise\n if (data.type === 'SUCCESS') {\n pending.resolve(data.data);\n } else if (data.type === 'ERROR') {\n pending.reject(data.error || { code: 'UNKNOWN_ERROR', message: 'An unknown error occurred' });\n }\n };\n\n window.addEventListener('message', this.messageListener);\n this.isInitialized = true;\n }\n\n /**\n * Generate a unique request ID\n */\n private generateRequestId(action: string): string {\n return `${action}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n\n /**\n * Send a message to the parent window and return a Promise\n */\n private sendMessage<T = unknown>(action: string, payload?: unknown): Promise<T> {\n if (!this.isInitialized) {\n return Promise.reject({\n code: 'SDK_NOT_INITIALIZED',\n message: 'SDK is not initialized',\n } as LearnCardError);\n }\n\n return new Promise<T>((resolve, reject) => {\n const requestId = this.generateRequestId(action);\n\n // Set up timeout\n const timeoutId = setTimeout(() => {\n if (this.pendingRequests.has(requestId)) {\n this.pendingRequests.delete(requestId);\n reject({\n code: 'LC_TIMEOUT',\n message: `Request ${action} timed out after ${this.requestTimeout}ms`,\n } as LearnCardError);\n }\n }, this.requestTimeout);\n\n // Store the pending request\n this.pendingRequests.set(requestId, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timeoutId,\n });\n\n // Construct the message\n const message: PostMessageRequest = {\n protocol: this.protocol,\n action,\n requestId,\n payload,\n };\n\n // Send to parent window with the active host origin (configured or overridden)\n window.parent.postMessage(message, this.activeHostOrigin);\n });\n }\n\n /**\n * Request user identity (Single Sign-On)\n * \n * @returns Promise resolving to user identity including DID and JWT token\n * @throws {LearnCardError} When user is not authenticated or request fails\n * \n * @example\n * ```typescript\n * const identity = await learnCard.requestIdentity();\n * console.log('User DID:', identity.user.did);\n * console.log('JWT Token:', identity.token);\n * ```\n */\n public requestIdentity(): Promise<IdentityResponse> {\n return this.sendMessage<IdentityResponse>('REQUEST_IDENTITY', { challenge: `${Date.now()}-${Math.random().toString(36).substring(2, 9)}` });\n }\n\n /**\n * Send a credential to the user's LearnCard wallet\n * \n * @param credential - The verifiable credential to send\n * @returns Promise resolving to credential ID\n * \n * @example\n * ```typescript\n * const response = await learnCard.sendCredential({\n * '@context': ['https://www.w3.org/2018/credentials/v1'],\n * type: ['VerifiableCredential'],\n * credentialSubject: { id: 'did:example:123' }\n * });\n * console.log('Credential ID:', response.credentialId);\n * ```\n */\n public sendCredential(credential: unknown): Promise<SendCredentialResponse> {\n return this.sendMessage<SendCredentialResponse>('SEND_CREDENTIAL', { credential });\n }\n\n /**\n * Launch a feature in the LearnCard host application\n * \n * @param featurePath - Path to the feature (e.g., '/ai/topics')\n * @param initialPrompt - Optional initial prompt or data\n * \n * @example\n * ```typescript\n * await learnCard.launchFeature(\n * '/ai/topics?shortCircuitStep=newTopic',\n * 'Help me understand cryptography'\n * );\n * ```\n */\n public launchFeature(featurePath: string, initialPrompt?: string): Promise<void> {\n return this.sendMessage<void>('LAUNCH_FEATURE', { featurePath, initialPrompt });\n }\n\n /**\n * Request credentials from the user's wallet using a query\n * \n * @param verifiablePresentationRequest - VPR with query criteria\n * @returns Promise resolving to verifiable presentation\n * \n * @example\n * ```typescript\n * const response = await learnCard.askCredentialSearch({\n * query: [{\n * type: 'QueryByTitle',\n * credentialQuery: {\n * reason: 'We need to verify your skills',\n * title: 'JavaScript Expert'\n * }\n * }],\n * challenge: 'challenge-123',\n * domain: window.location.hostname\n * });\n * \n * if (response.verifiablePresentation) {\n * console.log('Received credentials:', response.verifiablePresentation.verifiableCredential);\n * }\n * ```\n */\n public askCredentialSearch(\n verifiablePresentationRequest: VerifiablePresentationRequest\n ): Promise<CredentialSearchResponse> {\n return this.sendMessage<CredentialSearchResponse>('ASK_CREDENTIAL_SEARCH', {\n verifiablePresentationRequest,\n });\n }\n\n /**\n * Request a specific credential by ID\n * \n * @param credentialId - The ID of the credential to request\n * @returns Promise resolving to the credential\n * \n * @example\n * ```typescript\n * const response = await learnCard.askCredentialSpecific('credential-id-123');\n * if (response.credential) {\n * console.log('Received credential:', response.credential);\n * }\n * ```\n */\n public askCredentialSpecific(credentialId: string): Promise<CredentialSpecificResponse> {\n return this.sendMessage<CredentialSpecificResponse>('ASK_CREDENTIAL_SPECIFIC', {\n credentialId,\n });\n }\n\n /**\n * Request user consent for permissions\n * \n * @param contractUri - URI of the consent contract\n * @returns Promise resolving to consent response\n * \n * @example\n * ```typescript\n * const response = await learnCard.requestConsent('lc:network:network.learncard.com/trpc:contract:abc123');\n * if (response.granted) {\n * console.log('User granted consent');\n * }\n * ```\n */\n public requestConsent(contractUri: string): Promise<ConsentResponse> {\n return this.sendMessage<ConsentResponse>('REQUEST_CONSENT', { contractUri });\n }\n\n /**\n * Initiate a template-based credential issuance flow\n * \n * @param templateId - ID of the template/boost to issue\n * @param draftRecipients - Optional array of recipient DIDs\n * @returns Promise resolving to template issue response\n * \n * @example\n * ```typescript\n * const response = await learnCard.initiateTemplateIssue(\n * 'lc:network:network.learncard.com/trpc:boost:xyz789',\n * ['did:key:abc', 'did:key:def']\n * );\n * \n * if (response.issued) {\n * console.log('Template issued successfully');\n * }\n * ```\n */\n public initiateTemplateIssue(\n templateId: string,\n draftRecipients?: string[]\n ): Promise<TemplateIssueResponse> {\n return this.sendMessage<TemplateIssueResponse>('INITIATE_TEMPLATE_ISSUE', {\n templateId,\n draftRecipients: draftRecipients || [],\n });\n }\n\n /**\n * Clean up the SDK and remove event listeners\n */\n public destroy(): void {\n if (this.messageListener) {\n window.removeEventListener('message', this.messageListener);\n this.messageListener = null;\n }\n\n // Reject all pending requests\n for (const [requestId, pending] of this.pendingRequests.entries()) {\n clearTimeout(pending.timeoutId);\n pending.reject({\n code: 'SDK_DESTROYED',\n message: 'SDK was destroyed before request completed',\n });\n }\n\n this.pendingRequests.clear();\n this.isInitialized = false;\n }\n}\n\n/**\n * Factory function to create a PartnerConnect instance\n * \n * @param options - Configuration options\n * @returns PartnerConnect instance\n * \n * @example\n * ```typescript\n * const learnCard = createPartnerConnect({\n * hostOrigin: 'https://learncard.app',\n * protocol: 'LEARNCARD_V1',\n * requestTimeout: 30000\n * });\n * ```\n */\nexport function createPartnerConnect(options: PartnerConnectOptions): PartnerConnect {\n return new PartnerConnect(options);\n}\n\n// Default export for convenience\nexport default createPartnerConnect;\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@learncard/partner-connect",
3
+ "version": "0.2.0",
4
+ "description": "LearnCard Partner Connect SDK - Promise-based cross-origin messaging for partner apps",
5
+ "main": "dist/partner-connect.js",
6
+ "module": "dist/partner-connect.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/partner-connect.esm.js",
11
+ "require": "./dist/partner-connect.js",
12
+ "default": "./dist/partner-connect.js",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "sideEffects": false,
17
+ "keywords": [
18
+ "learncard",
19
+ "partner",
20
+ "connect",
21
+ "postmessage",
22
+ "iframe",
23
+ "credentials",
24
+ "sso"
25
+ ],
26
+ "license": "MIT",
27
+ "author": "Learning Economy Foundation (www.learningeconomy.io)",
28
+ "devDependencies": {
29
+ "@rollup/plugin-commonjs": "^22.0.2",
30
+ "@rollup/plugin-node-resolve": "^13.3.0",
31
+ "@types/node": "^18.19.64",
32
+ "rollup": "^2.79.1",
33
+ "rollup-plugin-dts": "^4.2.2",
34
+ "rollup-plugin-esbuild": "^4.9.1",
35
+ "typescript": "^5.4.5"
36
+ },
37
+ "files": [
38
+ "dist/**"
39
+ ],
40
+ "scripts": {
41
+ "build": "rollup -c",
42
+ "dev": "rollup -c -w",
43
+ "typecheck": "tsc --noEmit"
44
+ }
45
+ }