@learncard/partner-connect 0.3.10 → 0.4.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 +184 -0
- package/dist/index.d.ts +209 -3
- package/dist/partner-connect.esm.js +822 -9
- package/dist/partner-connect.esm.js.map +1 -1
- package/dist/partner-connect.js +822 -8
- package/dist/partner-connect.js.map +1 -1
- package/dist/partner-connect.mjs +822 -9
- package/dist/partner-connect.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +274 -4
- package/src/mock-host.ts +887 -0
- package/src/mock-mode.test.ts +478 -0
- package/src/types.ts +158 -0
package/README.md
CHANGED
|
@@ -77,6 +77,25 @@ interface PartnerConnectOptions {
|
|
|
77
77
|
* Request timeout in milliseconds (default: 30000)
|
|
78
78
|
*/
|
|
79
79
|
requestTimeout?: number;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Controls automatic standalone mock mode.
|
|
83
|
+
* 'auto' (default) mocks only when no LearnCard host is present AND the
|
|
84
|
+
* page runs on a local dev host; 'standalone' mocks whenever no host is
|
|
85
|
+
* present, on any origin; true always mocks; false never mocks.
|
|
86
|
+
*/
|
|
87
|
+
mock?: boolean | 'auto' | 'standalone';
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Fine-grained mock behavior (UI, logging, persistence, fake DID).
|
|
91
|
+
*/
|
|
92
|
+
mockOptions?: MockHostOptions;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* How long (ms) to wait for the host presence probe when embedded in a
|
|
96
|
+
* frame whose parent can't be confirmed as LearnCard (default: 1500).
|
|
97
|
+
*/
|
|
98
|
+
hostProbeTimeout?: number;
|
|
80
99
|
}
|
|
81
100
|
```
|
|
82
101
|
|
|
@@ -166,6 +185,169 @@ The SDK enforces an exact match between incoming message origins and the active
|
|
|
166
185
|
// ❌ Rejects: messages from any other origin
|
|
167
186
|
```
|
|
168
187
|
|
|
188
|
+
## Standalone / Mock Mode
|
|
189
|
+
|
|
190
|
+
The SDK only works when embedded inside a LearnCard host — that's the host that
|
|
191
|
+
answers its `postMessage` requests. When you run your app on its own (local dev,
|
|
192
|
+
Storybook, a preview deploy, CI), there is no host. Standalone calls that aren't
|
|
193
|
+
mocked reject immediately with `LC_NOT_EMBEDDED` (rather than hanging until the
|
|
194
|
+
request timeout), and the SDK logs a one-time hint pointing you to mock mode.
|
|
195
|
+
|
|
196
|
+
**Mock mode fixes this automatically in local development.** Whenever no
|
|
197
|
+
LearnCard host is present and your app runs on a local dev host (`localhost`,
|
|
198
|
+
`127.0.0.1`, `[::1]`, `*.localhost`, `*.local`) — plain local dev or a local
|
|
199
|
+
Storybook — the SDK simulates the host locally:
|
|
200
|
+
|
|
201
|
+
- **Every method shows a branded toast** describing what would happen once embedded — e.g. `sendCredential` → _"✅ In LearnCard, the user would receive **[name]** here."_, `incrementCounter` → _"Counter **coins** → **10**."_, `launchFeature` → _"Would open **/wallet**."_ So you get strong, visible feedback for every call, not just console logs.
|
|
202
|
+
- `requestConsent(...)` auto-grants and shows a "mock consent" toast; `incrementCounter` / `getCounter` / `getCounters` persist to `localStorage` so values survive reloads.
|
|
203
|
+
- Identical or polled calls **coalesce** into a single toast with a ×N counter, so nothing spams the screen.
|
|
204
|
+
- `requestIdentity`, notifications, learner context, sync status, etc. all resolve with sensible fake data.
|
|
205
|
+
- Every simulated interaction is also logged to the console with a `[LearnCard SDK · MOCK]` prefix.
|
|
206
|
+
|
|
207
|
+
**No code changes, no environment flags in local dev.** Your app is fully
|
|
208
|
+
buildable and demo-able locally, and behaves identically against the real host
|
|
209
|
+
once embedded.
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// Mocks in local dev when standalone; real host when embedded in LearnCard.
|
|
213
|
+
const learnCard = createPartnerConnect({ hostOrigin: 'https://learncard.app' });
|
|
214
|
+
|
|
215
|
+
const res = await learnCard.sendCredential({ templateAlias: 'course-completion' });
|
|
216
|
+
// Local dev, standalone: resolves with a mock URI + shows a toast.
|
|
217
|
+
// Embedded: goes to the real LearnCard host.
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**`'auto'` is deliberately scoped to local dev hosts.** A standalone page on a
|
|
221
|
+
production or remote preview origin never auto-mocks — otherwise a real user
|
|
222
|
+
opening your app's URL directly would receive a fabricated identity and
|
|
223
|
+
auto-granted consent. For remote deploy previews (Netlify, Lovable, Vercel, …)
|
|
224
|
+
that should demo standalone anywhere but go real once embedded, opt in with
|
|
225
|
+
`mock: 'standalone'`; for CI and tests that should always mock, use
|
|
226
|
+
`mock: true`. Every mocked call shows a labeled toast and a
|
|
227
|
+
`[LearnCard SDK · MOCK]` console log, so it's clear the SDK is simulating
|
|
228
|
+
rather than talking to a real host.
|
|
229
|
+
|
|
230
|
+
| `mock` | Standalone, local dev | Standalone, remote origin | Embedded in LearnCard |
|
|
231
|
+
| ------------------ | --------------------- | ----------------------------- | --------------------- |
|
|
232
|
+
| `'auto'` (default) | mock | fail fast (`LC_NOT_EMBEDDED`) | real host |
|
|
233
|
+
| `'standalone'` | mock | mock | real host |
|
|
234
|
+
| `true` | mock | mock | mock |
|
|
235
|
+
| `false` | fail fast | fail fast | real host |
|
|
236
|
+
|
|
237
|
+
**Unrelated iframes don't fool it.** If your app is embedded in something that
|
|
238
|
+
isn't LearnCard (a cross-origin Storybook canvas, a preview shell), calls no
|
|
239
|
+
longer hang: the SDK mocks on local dev hosts and otherwise rejects fast with
|
|
240
|
+
`LC_NOT_EMBEDDED`. When the parent can't be identified (Firefox, or a
|
|
241
|
+
same-origin localhost wrapper), the SDK sends a one-time, side-effect-free
|
|
242
|
+
presence probe and only mocks if no host answers within `hostProbeTimeout`
|
|
243
|
+
(default 1500 ms).
|
|
244
|
+
|
|
245
|
+
For a **production build that's meant to run only inside LearnCard**, set
|
|
246
|
+
`mock: false`; standalone calls then reject immediately with `LC_NOT_EMBEDDED`
|
|
247
|
+
instead of showing simulated data.
|
|
248
|
+
|
|
249
|
+
Override the default behavior when needed:
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
// Mock wherever no host is present (remote previews), real host when embedded:
|
|
253
|
+
createPartnerConnect({ mock: 'standalone' });
|
|
254
|
+
|
|
255
|
+
// Always mock, even while embedded (CI, tests):
|
|
256
|
+
createPartnerConnect({ mock: true });
|
|
257
|
+
|
|
258
|
+
// Never mock (standalone calls reject fast with LC_NOT_EMBEDDED):
|
|
259
|
+
createPartnerConnect({ mock: false });
|
|
260
|
+
|
|
261
|
+
// Configure mock behavior:
|
|
262
|
+
createPartnerConnect({
|
|
263
|
+
mock: 'auto',
|
|
264
|
+
mockOptions: {
|
|
265
|
+
ui: true, // show toasts/banners (default true)
|
|
266
|
+
log: true, // console logging (default true)
|
|
267
|
+
persist: true, // localStorage-backed counters (default true)
|
|
268
|
+
did: 'did:web:example.com:me', // fake identity DID
|
|
269
|
+
namespace: 'my-app-mock', // localStorage namespace for mock state
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Check whether an instance is currently mocking:
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
if (learnCard.isMocked()) {
|
|
278
|
+
console.log('Running against the local mock host.');
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Coherent state: reads reflect writes
|
|
283
|
+
|
|
284
|
+
The mock keeps a small session store so it behaves like a real host, not a set of
|
|
285
|
+
disconnected stubs. Anything you do in a session shows up in later reads:
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
await learnCard.sendCredential({ templateAlias: 'course-completion' });
|
|
289
|
+
|
|
290
|
+
// Now reflects the credential you just issued:
|
|
291
|
+
await learnCard.checkUserHasCredential({ templateAlias: 'course-completion' }); // { hasCredential: true, ... }
|
|
292
|
+
await learnCard.requestLearnerContext(); // raw.credentials includes it
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
This means happy-path UI (e.g. a "you already earned this" banner) actually
|
|
296
|
+
lights up standalone. Counters persist to `localStorage`; issued credentials and
|
|
297
|
+
identity live for the session (a reload re-applies your seeds — see below). Mock
|
|
298
|
+
credentials are clearly marked (`_mock: true`) and never cryptographically valid,
|
|
299
|
+
so they can't be mistaken for real ones.
|
|
300
|
+
|
|
301
|
+
### Seeding data for demos
|
|
302
|
+
|
|
303
|
+
To demo a pre-populated state (a returning user who already has credentials, a
|
|
304
|
+
starting coin balance) without performing actions first, seed via `mockOptions`:
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
createPartnerConnect({
|
|
308
|
+
mockOptions: {
|
|
309
|
+
identity: { did: 'did:web:example.com:me', name: 'Ada' },
|
|
310
|
+
credentials: [
|
|
311
|
+
{ templateAlias: 'course-completion', name: 'Algebra 101' },
|
|
312
|
+
// Model a credential you issued to someone else:
|
|
313
|
+
{ boostUri: 'lc:boost:team-badge', recipient: 'alice', status: 'pending' },
|
|
314
|
+
],
|
|
315
|
+
counters: { coins: 50 },
|
|
316
|
+
},
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Seeded credentials feed `checkUserHasCredential`, `getTemplateRecipients`,
|
|
321
|
+
`getTemplateIssuanceStatus`, `requestLearnerContext`, and `askCredentialSearch`.
|
|
322
|
+
Seeded counters are applied only when a counter has no persisted value yet, so
|
|
323
|
+
incremented values survive reloads.
|
|
324
|
+
|
|
325
|
+
## Detecting the Embed Context
|
|
326
|
+
|
|
327
|
+
Use `isEmbedded()` to branch your own logic based on whether your app is running
|
|
328
|
+
inside a LearnCard iframe or as a standalone page — no need to write your own
|
|
329
|
+
frame detection.
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
import { isEmbedded, createPartnerConnect } from '@learncard/partner-connect';
|
|
333
|
+
|
|
334
|
+
if (isEmbedded()) {
|
|
335
|
+
// Inside LearnCard — hide your standalone header, enable SDK-backed features.
|
|
336
|
+
} else {
|
|
337
|
+
// Standalone — show an "Open in LearnCard" prompt, or lean on mock mode.
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
It is also available as a static and instance method:
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
PartnerConnect.isEmbedded(); // static
|
|
345
|
+
createPartnerConnect().isEmbedded(); // instance
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
`isEmbedded()` returns `false` during server-side rendering (no `window`) and is
|
|
349
|
+
safe to call anywhere.
|
|
350
|
+
|
|
169
351
|
## API Reference
|
|
170
352
|
|
|
171
353
|
### `requestIdentity()`
|
|
@@ -181,6 +363,7 @@ const identity = await learnCard.requestIdentity();
|
|
|
181
363
|
|
|
182
364
|
- `LC_UNAUTHENTICATED`: User is not logged in to LearnCard
|
|
183
365
|
- `LC_TIMEOUT`: Request timed out
|
|
366
|
+
- `LC_NOT_EMBEDDED`: The app is not embedded in a LearnCard host (standalone, not mocking)
|
|
184
367
|
|
|
185
368
|
---
|
|
186
369
|
|
|
@@ -601,6 +784,7 @@ interface LearnCardError {
|
|
|
601
784
|
**Common Error Codes:**
|
|
602
785
|
|
|
603
786
|
- `LC_TIMEOUT`: Request timed out
|
|
787
|
+
- `LC_NOT_EMBEDDED`: Not embedded in a LearnCard host (standalone, not mocking)
|
|
604
788
|
- `LC_UNAUTHENTICATED`: User not logged in
|
|
605
789
|
- `USER_REJECTED`: User declined the request
|
|
606
790
|
- `CREDENTIAL_NOT_FOUND`: Credential doesn't exist
|
package/dist/index.d.ts
CHANGED
|
@@ -91,6 +91,146 @@ interface PartnerConnectOptions {
|
|
|
91
91
|
* Request timeout in milliseconds (default: 30000)
|
|
92
92
|
*/
|
|
93
93
|
requestTimeout?: number;
|
|
94
|
+
/**
|
|
95
|
+
* Controls automatic **standalone mock mode**.
|
|
96
|
+
*
|
|
97
|
+
* When the SDK runs outside of a LearnCard host (i.e. as a top-level page,
|
|
98
|
+
* not embedded in an iframe), there is no host to answer `postMessage`
|
|
99
|
+
* requests, so every call would hang until it times out. Mock mode makes
|
|
100
|
+
* the SDK simulate the host locally so your app is fully buildable,
|
|
101
|
+
* demo-able, and testable without being embedded — and then behaves
|
|
102
|
+
* identically (real host) once embedded, with no code changes.
|
|
103
|
+
*
|
|
104
|
+
* - `'auto'` **(default)**: mock only when **no LearnCard host is present
|
|
105
|
+
* AND the app is running on a local dev host** (`localhost`,
|
|
106
|
+
* `127.0.0.1`, `[::1]`, `*.localhost`, `*.local`). This covers local
|
|
107
|
+
* dev and local Storybook, but deliberately never fabricates identity
|
|
108
|
+
* or consent on a production or preview origin. Each mocked call
|
|
109
|
+
* surfaces a labeled toast plus a console log so it's clear the host
|
|
110
|
+
* is simulated.
|
|
111
|
+
* - `'standalone'`: mock whenever **no LearnCard host is present**, on
|
|
112
|
+
* any origin — including remote deploy previews (Netlify, Lovable,
|
|
113
|
+
* Vercel, …) — and use the real host when embedded in LearnCard. The
|
|
114
|
+
* one-flag setting for apps that must demo standalone anywhere. Only
|
|
115
|
+
* choose it when a user opening your app's URL directly should see
|
|
116
|
+
* simulated data.
|
|
117
|
+
* - `true`: always mock, **even when embedded in a real LearnCard host**.
|
|
118
|
+
* Use this for CI and tests; for previews that should go real once
|
|
119
|
+
* embedded, prefer `'standalone'`.
|
|
120
|
+
* - `false`: never mock. Standalone calls reject immediately with
|
|
121
|
+
* `LC_NOT_EMBEDDED`. Set this in production builds meant to run only
|
|
122
|
+
* inside LearnCard.
|
|
123
|
+
*
|
|
124
|
+
* @default 'auto'
|
|
125
|
+
*/
|
|
126
|
+
mock?: boolean | 'auto' | 'standalone';
|
|
127
|
+
/**
|
|
128
|
+
* Fine-grained configuration for standalone mock mode. Ignored when mock
|
|
129
|
+
* mode is not active. See {@link MockHostOptions}.
|
|
130
|
+
*/
|
|
131
|
+
mockOptions?: MockHostOptions;
|
|
132
|
+
/**
|
|
133
|
+
* How long (ms) to wait for the host to answer the one-time presence
|
|
134
|
+
* probe used when the SDK is embedded in an iframe whose parent cannot
|
|
135
|
+
* be confirmed as LearnCard (e.g. a same-origin Storybook canvas on
|
|
136
|
+
* localhost). Only used with `mock: 'auto'` on local dev hosts.
|
|
137
|
+
*
|
|
138
|
+
* @default 1500
|
|
139
|
+
*/
|
|
140
|
+
hostProbeTimeout?: number;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Options controlling the behavior of standalone mock mode.
|
|
144
|
+
*
|
|
145
|
+
* All fields are optional; mock mode works out-of-the-box with sensible
|
|
146
|
+
* defaults (visible UI, console logging, and localStorage-backed counters).
|
|
147
|
+
*/
|
|
148
|
+
interface MockHostOptions {
|
|
149
|
+
/**
|
|
150
|
+
* Render lightweight visual feedback in the page: a fake credential-claim
|
|
151
|
+
* modal / toast for `sendCredential`, and a "mock consent" banner for
|
|
152
|
+
* `requestConsent`. Set to `false` for a headless mock (logs only).
|
|
153
|
+
*
|
|
154
|
+
* @default true
|
|
155
|
+
*/
|
|
156
|
+
ui?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Log every simulated host interaction to the console with a clear
|
|
159
|
+
* `[LearnCard SDK · MOCK]` prefix.
|
|
160
|
+
*
|
|
161
|
+
* @default true
|
|
162
|
+
*/
|
|
163
|
+
log?: boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Persist counters (`incrementCounter` / `getCounter` / `getCounters`) to
|
|
166
|
+
* `localStorage` so values survive page reloads, mirroring the real host's
|
|
167
|
+
* durable per-user counters. Falls back to in-memory storage when
|
|
168
|
+
* `localStorage` is unavailable.
|
|
169
|
+
*
|
|
170
|
+
* @default true
|
|
171
|
+
*/
|
|
172
|
+
persist?: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* The fake DID returned by `requestIdentity()` (and used as the mock
|
|
175
|
+
* user's identity) while in mock mode.
|
|
176
|
+
*
|
|
177
|
+
* @default 'did:web:mock.learncard.app:user'
|
|
178
|
+
*/
|
|
179
|
+
did?: string;
|
|
180
|
+
/**
|
|
181
|
+
* Namespace used to scope persisted mock data (counters, claimed
|
|
182
|
+
* credentials) in `localStorage`. Change this if you run multiple mock
|
|
183
|
+
* apps on the same origin and want isolated state.
|
|
184
|
+
*
|
|
185
|
+
* @default 'lc-mock'
|
|
186
|
+
*/
|
|
187
|
+
namespace?: string;
|
|
188
|
+
/**
|
|
189
|
+
* Seed the mock user's identity. Superseded per-field over the legacy
|
|
190
|
+
* `did` option. Extra fields are returned as-is from `requestIdentity()`.
|
|
191
|
+
*/
|
|
192
|
+
identity?: MockIdentitySeed;
|
|
193
|
+
/**
|
|
194
|
+
* Pre-populate the mock with credentials the user already holds (or has
|
|
195
|
+
* issued to others). This lets you demo "happy path" states — e.g. a
|
|
196
|
+
* "you already earned this" banner — without performing an action first.
|
|
197
|
+
* Reads like `checkUserHasCredential`, `getTemplateRecipients`,
|
|
198
|
+
* `requestLearnerContext`, and `askCredentialSearch` reflect these.
|
|
199
|
+
*/
|
|
200
|
+
credentials?: MockCredentialSeed[];
|
|
201
|
+
/**
|
|
202
|
+
* Initial counter values, applied only when a counter has no persisted
|
|
203
|
+
* value yet (so incremented values survive reloads).
|
|
204
|
+
*/
|
|
205
|
+
counters?: Record<string, number>;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Seed shape for the mock user's identity (see {@link MockHostOptions.identity}).
|
|
209
|
+
*/
|
|
210
|
+
interface MockIdentitySeed {
|
|
211
|
+
did?: string;
|
|
212
|
+
name?: string;
|
|
213
|
+
[key: string]: unknown;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Seed shape for a pre-populated mock credential (see
|
|
217
|
+
* {@link MockHostOptions.credentials}).
|
|
218
|
+
*/
|
|
219
|
+
interface MockCredentialSeed {
|
|
220
|
+
/** Template alias this credential was issued from. */
|
|
221
|
+
templateAlias?: string;
|
|
222
|
+
/** Boost URI this credential was issued from. */
|
|
223
|
+
boostUri?: string;
|
|
224
|
+
/** Human-readable credential name (used in toasts and mock VC data). */
|
|
225
|
+
name?: string;
|
|
226
|
+
/**
|
|
227
|
+
* Recipient identifier (profileId or DID). Defaults to the mock user
|
|
228
|
+
* (i.e. a credential the user holds). Set this to model credentials the
|
|
229
|
+
* user has issued to other people.
|
|
230
|
+
*/
|
|
231
|
+
recipient?: string;
|
|
232
|
+
/** Claim status. @default 'claimed' */
|
|
233
|
+
status?: 'pending' | 'claimed' | 'revoked';
|
|
94
234
|
}
|
|
95
235
|
/**
|
|
96
236
|
* Identity information returned from REQUEST_IDENTITY
|
|
@@ -499,7 +639,7 @@ interface GetCountersResponse {
|
|
|
499
639
|
/**
|
|
500
640
|
* Error codes that can be returned by the LearnCard host
|
|
501
641
|
*/
|
|
502
|
-
type ErrorCode = 'LC_TIMEOUT' | 'LC_UNAUTHENTICATED' | 'CREDENTIAL_NOT_FOUND' | 'USER_REJECTED' | 'UNAUTHORIZED' | 'TEMPLATE_NOT_FOUND' | 'BOOST_NOT_FOUND' | 'INSUFFICIENT_PERMISSIONS' | string;
|
|
642
|
+
type ErrorCode = 'LC_TIMEOUT' | 'LC_NOT_EMBEDDED' | 'LC_UNAUTHENTICATED' | 'CREDENTIAL_NOT_FOUND' | 'USER_REJECTED' | 'UNAUTHORIZED' | 'TEMPLATE_NOT_FOUND' | 'BOOST_NOT_FOUND' | 'INSUFFICIENT_PERMISSIONS' | string;
|
|
503
643
|
/**
|
|
504
644
|
* Error object returned when a request fails.
|
|
505
645
|
*
|
|
@@ -598,6 +738,28 @@ interface PendingRequest {
|
|
|
598
738
|
* ```
|
|
599
739
|
*/
|
|
600
740
|
|
|
741
|
+
/**
|
|
742
|
+
* Detect whether the current page is running inside an embedded iframe.
|
|
743
|
+
*
|
|
744
|
+
* Returns `true` when the SDK is embedded (e.g. inside the LearnCard host) and
|
|
745
|
+
* `false` when running as a standalone top-level page. Safe to call in any
|
|
746
|
+
* environment: returns `false` during server-side rendering (no `window`).
|
|
747
|
+
*
|
|
748
|
+
* Partner apps can use this to change behavior without writing their own frame
|
|
749
|
+
* detection — for example, showing a "Open in LearnCard" prompt when standalone.
|
|
750
|
+
*
|
|
751
|
+
* @example
|
|
752
|
+
* ```typescript
|
|
753
|
+
* import { isEmbedded } from '@learncard/partner-connect';
|
|
754
|
+
*
|
|
755
|
+
* if (isEmbedded()) {
|
|
756
|
+
* // Running inside LearnCard — use the SDK against the real host.
|
|
757
|
+
* } else {
|
|
758
|
+
* // Standalone — show a preview banner, or rely on automatic mock mode.
|
|
759
|
+
* }
|
|
760
|
+
* ```
|
|
761
|
+
*/
|
|
762
|
+
declare function isEmbedded(): boolean;
|
|
601
763
|
/**
|
|
602
764
|
* LearnCard Partner Connect SDK class
|
|
603
765
|
*/
|
|
@@ -627,7 +789,47 @@ declare class PartnerConnect {
|
|
|
627
789
|
private isInitialized;
|
|
628
790
|
private syncCompleteCallbacks;
|
|
629
791
|
private syncStatusPollId;
|
|
792
|
+
private mockHost;
|
|
793
|
+
private embedded;
|
|
794
|
+
private warnedNoHost;
|
|
795
|
+
private hostProbeTimeout;
|
|
796
|
+
/** Whether a real LearnCard host is believed to be listening. */
|
|
797
|
+
private hostReachable;
|
|
798
|
+
/** Pending probe decision; requests queue behind it when set. */
|
|
799
|
+
private activation;
|
|
630
800
|
constructor(options?: PartnerConnectOptions);
|
|
801
|
+
/**
|
|
802
|
+
* Decide whether this instance talks to a real host, simulates one, or
|
|
803
|
+
* fails fast — the resolution of the `mock` option against the runtime
|
|
804
|
+
* embed context. See the `mock` option docs for the contract.
|
|
805
|
+
*/
|
|
806
|
+
private configureMockActivation;
|
|
807
|
+
private isLocalDevContext;
|
|
808
|
+
private classifyParent;
|
|
809
|
+
private matchesConfiguredOrigin;
|
|
810
|
+
/**
|
|
811
|
+
* One-time host presence probe for the ambiguous-parent case. Sends a
|
|
812
|
+
* side-effect-free `GET_SYNC_STATUS`; an answer proves a live LearnCard
|
|
813
|
+
* host (responses are origin-checked), a timeout means nobody is
|
|
814
|
+
* listening and the mock takes over. Requests issued while the probe is
|
|
815
|
+
* in flight queue behind the decision instead of racing it.
|
|
816
|
+
*/
|
|
817
|
+
private probeHost;
|
|
818
|
+
/**
|
|
819
|
+
* Whether this SDK instance is running inside an embedded iframe.
|
|
820
|
+
* Instance-level convenience wrapper around the standalone {@link isEmbedded}.
|
|
821
|
+
*/
|
|
822
|
+
isEmbedded(): boolean;
|
|
823
|
+
/**
|
|
824
|
+
* Whether the current page is running inside an embedded iframe.
|
|
825
|
+
* Static convenience wrapper around the standalone {@link isEmbedded}.
|
|
826
|
+
*/
|
|
827
|
+
static isEmbedded(): boolean;
|
|
828
|
+
/**
|
|
829
|
+
* Whether this instance is currently simulating the LearnCard host locally
|
|
830
|
+
* instead of talking to a real host over `postMessage`.
|
|
831
|
+
*/
|
|
832
|
+
isMocked(): boolean;
|
|
631
833
|
/**
|
|
632
834
|
* Configure the active host origin using the following hierarchy:
|
|
633
835
|
* 1. `window.location.ancestorOrigins[0]` (when supported) — the browser's
|
|
@@ -705,9 +907,13 @@ declare class PartnerConnect {
|
|
|
705
907
|
*/
|
|
706
908
|
private generateRequestId;
|
|
707
909
|
/**
|
|
708
|
-
* Send a message to the parent window and return a Promise
|
|
910
|
+
* Send a message to the parent window and return a Promise. While a host
|
|
911
|
+
* presence probe is pending, requests queue behind its decision so they
|
|
912
|
+
* are answered by whichever side (real host or mock) actually exists.
|
|
709
913
|
*/
|
|
710
914
|
private sendMessage;
|
|
915
|
+
private dispatchMessage;
|
|
916
|
+
private postToHost;
|
|
711
917
|
/**
|
|
712
918
|
* Request user identity (Single Sign-On)
|
|
713
919
|
*
|
|
@@ -1037,4 +1243,4 @@ declare class PartnerConnect {
|
|
|
1037
1243
|
*/
|
|
1038
1244
|
declare function createPartnerConnect(options?: PartnerConnectOptions): PartnerConnect;
|
|
1039
1245
|
|
|
1040
|
-
export { AppNotificationInput, AppNotificationResponse, CheckCredentialInput, CheckCredentialResponse, CheckIssuanceStatusInput, ConsentResponse, CredentialSearchResponse, CredentialSpecificResponse, ErrorCode, GetCounterResponse, GetCountersResponse, GetTemplateRecipientsInput, IdentityResponse, IncrementCounterResponse, LearnCardError, LearnerContextCacheStatus, LearnerContextRawData, LearnerContextResponse, LearnerContextTimingBreakdown, PartnerConnect, PartnerConnectError, PartnerConnectOptions, PendingRequest, PostMessageRequest, PostMessageResponse, RequestConsentOptions, RequestConsentPayload, RequestLearnerContextOptions, SendAiSessionCredentialInput, SendAiSessionCredentialResponse, SendCredentialResponse, SummaryCredentialData, SummaryCredentialKeyword, SummaryCredentialNextStep, SummaryCredentialReflection, SummaryCredentialSkill, SyncProgress, SyncStatus, TemplateCredentialInput, TemplateCredentialResponse, TemplateIssuanceStatusResponse, TemplateIssueResponse, TemplateRecipientRecord, TemplateRecipientsResponse, VPRQuery, VerifiablePresentationRequest, createPartnerConnect, createPartnerConnect as default };
|
|
1246
|
+
export { AppNotificationInput, AppNotificationResponse, CheckCredentialInput, CheckCredentialResponse, CheckIssuanceStatusInput, ConsentResponse, CredentialSearchResponse, CredentialSpecificResponse, ErrorCode, GetCounterResponse, GetCountersResponse, GetTemplateRecipientsInput, IdentityResponse, IncrementCounterResponse, LearnCardError, LearnerContextCacheStatus, LearnerContextRawData, LearnerContextResponse, LearnerContextTimingBreakdown, MockCredentialSeed, MockHostOptions, MockIdentitySeed, PartnerConnect, PartnerConnectError, PartnerConnectOptions, PendingRequest, PostMessageRequest, PostMessageResponse, RequestConsentOptions, RequestConsentPayload, RequestLearnerContextOptions, SendAiSessionCredentialInput, SendAiSessionCredentialResponse, SendCredentialResponse, SummaryCredentialData, SummaryCredentialKeyword, SummaryCredentialNextStep, SummaryCredentialReflection, SummaryCredentialSkill, SyncProgress, SyncStatus, TemplateCredentialInput, TemplateCredentialResponse, TemplateIssuanceStatusResponse, TemplateIssueResponse, TemplateRecipientRecord, TemplateRecipientsResponse, VPRQuery, VerifiablePresentationRequest, createPartnerConnect, createPartnerConnect as default, isEmbedded };
|