@horae.io/passport-core 1.0.0 → 1.0.6
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/dist/index.cjs +112 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +111 -31
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
HoraeSDK: () => HoraeSDK,
|
|
33
34
|
createClient: () => createClient,
|
|
34
35
|
createClientWithAuth: () => createClientWithAuth,
|
|
35
36
|
createCustomStrategy: () => createCustomStrategy,
|
|
@@ -162,6 +163,18 @@ function createPassportApi(api) {
|
|
|
162
163
|
async claimShopifyPassport(data) {
|
|
163
164
|
await api.post("/api/passport/shopify-claim", data);
|
|
164
165
|
},
|
|
166
|
+
/** Scale owner registration (serial/email based, no wallet) */
|
|
167
|
+
async registerScaleOwner(payload) {
|
|
168
|
+
const res = await api.post("/api/passport/scale/register", payload);
|
|
169
|
+
return unwrapData(res);
|
|
170
|
+
},
|
|
171
|
+
/** Scale signed viewer (HMAC signature) */
|
|
172
|
+
async getScaleViewer(tokenId, sig) {
|
|
173
|
+
const res = await api.get(`/api/passport/scale/view/${tokenId}`, {
|
|
174
|
+
params: { sig }
|
|
175
|
+
});
|
|
176
|
+
return unwrapData(res);
|
|
177
|
+
},
|
|
165
178
|
/** Current user profile */
|
|
166
179
|
async getMe() {
|
|
167
180
|
const res = await api.get("/users/me");
|
|
@@ -200,6 +213,15 @@ function prepareContainer(options, apiBase, token) {
|
|
|
200
213
|
if (options.initialTab) {
|
|
201
214
|
containerEl.dataset.initialTab = options.initialTab;
|
|
202
215
|
}
|
|
216
|
+
if (options.mode) {
|
|
217
|
+
containerEl.dataset.horaeMode = options.mode;
|
|
218
|
+
}
|
|
219
|
+
if (options.viewerUrl) {
|
|
220
|
+
containerEl.dataset.horaeViewerUrl = options.viewerUrl;
|
|
221
|
+
}
|
|
222
|
+
if (options.scaleRegistration) {
|
|
223
|
+
containerEl.dataset.horaeScaleRegistration = options.scaleRegistration;
|
|
224
|
+
}
|
|
203
225
|
if (token) {
|
|
204
226
|
containerEl.dataset.horaeToken = token;
|
|
205
227
|
}
|
|
@@ -229,7 +251,12 @@ async function mountApp(options, apiBase, token) {
|
|
|
229
251
|
const host = options.uiHost || "https://app.horae.io";
|
|
230
252
|
await loadUIBundle(host);
|
|
231
253
|
window.dispatchEvent(new CustomEvent("horae:sdk:mount", {
|
|
232
|
-
detail: {
|
|
254
|
+
detail: {
|
|
255
|
+
container: options.container,
|
|
256
|
+
mode: options.mode,
|
|
257
|
+
viewerUrl: options.viewerUrl,
|
|
258
|
+
scaleRegistration: options.scaleRegistration
|
|
259
|
+
}
|
|
233
260
|
}));
|
|
234
261
|
}
|
|
235
262
|
async function renderPassportList(options, apiBase, token) {
|
|
@@ -244,55 +271,109 @@ async function renderPassport(options, apiBase, token) {
|
|
|
244
271
|
const host = options.uiHost || "https://app.horae.io";
|
|
245
272
|
await loadUIBundle(host);
|
|
246
273
|
window.dispatchEvent(new CustomEvent("horae:sdk:mount", {
|
|
247
|
-
detail: {
|
|
274
|
+
detail: {
|
|
275
|
+
container: options.container,
|
|
276
|
+
passportId: options.passportId,
|
|
277
|
+
mode: options.mode,
|
|
278
|
+
viewerUrl: options.viewerUrl,
|
|
279
|
+
scaleRegistration: options.scaleRegistration
|
|
280
|
+
}
|
|
248
281
|
}));
|
|
249
282
|
}
|
|
250
283
|
|
|
251
284
|
// src/index.ts
|
|
252
285
|
function createPassportSDK(config) {
|
|
286
|
+
const mode = config.mode ?? "heritage";
|
|
287
|
+
const authStrategy = config.authStrategy ?? (mode === "scale" ? "custom" : "jwt");
|
|
253
288
|
const events = createEventBus();
|
|
254
289
|
let auth;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
290
|
+
if (mode === "scale") {
|
|
291
|
+
auth = createCustomStrategy(async () => config.token ?? null);
|
|
292
|
+
} else {
|
|
293
|
+
switch (authStrategy) {
|
|
294
|
+
case "jwt": {
|
|
295
|
+
const jwt = createJwtStrategy({
|
|
296
|
+
token: config.token ?? void 0,
|
|
297
|
+
storageKey: config.tokenStorageKey ?? void 0
|
|
298
|
+
});
|
|
299
|
+
auth = jwt;
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case "custom": {
|
|
303
|
+
if (!config.getToken) throw new Error("PassportSDK: getToken required for authStrategy 'custom'");
|
|
304
|
+
auth = createCustomStrategy(config.getToken);
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
case "shopify":
|
|
308
|
+
auth = createJwtStrategy({
|
|
309
|
+
token: config.token ?? void 0,
|
|
310
|
+
storageKey: config.tokenStorageKey ?? "shopify_access_token"
|
|
311
|
+
});
|
|
312
|
+
break;
|
|
313
|
+
case "privy":
|
|
314
|
+
if (!config.getToken) throw new Error("PassportSDK: getToken required for authStrategy 'privy' (pass Privy getAccessToken)");
|
|
315
|
+
auth = createCustomStrategy(config.getToken);
|
|
316
|
+
break;
|
|
317
|
+
default:
|
|
318
|
+
throw new Error(`PassportSDK: unknown authStrategy ${String(authStrategy)}`);
|
|
268
319
|
}
|
|
269
|
-
case "shopify":
|
|
270
|
-
auth = createJwtStrategy({
|
|
271
|
-
token: config.token ?? void 0,
|
|
272
|
-
storageKey: config.tokenStorageKey ?? "shopify_access_token"
|
|
273
|
-
});
|
|
274
|
-
break;
|
|
275
|
-
case "privy":
|
|
276
|
-
if (!config.getToken) throw new Error("PassportSDK: getToken required for authStrategy 'privy' (pass Privy getAccessToken)");
|
|
277
|
-
auth = createCustomStrategy(config.getToken);
|
|
278
|
-
break;
|
|
279
|
-
default:
|
|
280
|
-
throw new Error(`PassportSDK: unknown authStrategy ${String(config.authStrategy)}`);
|
|
281
320
|
}
|
|
282
321
|
const client = createClient({ apiBase: config.apiBase, getToken: () => auth.getToken() });
|
|
283
322
|
const api = createPassportApi(client);
|
|
323
|
+
const fallbackScaleRegistration = config.serial || config.brandId ? {
|
|
324
|
+
serialNumber: config.serial,
|
|
325
|
+
manufacturerId: config.brandId
|
|
326
|
+
} : void 0;
|
|
327
|
+
const scaleRegistrationPayload = config.scaleRegistration ?? fallbackScaleRegistration;
|
|
328
|
+
const scaleRegistration = scaleRegistrationPayload ? JSON.stringify(scaleRegistrationPayload) : void 0;
|
|
284
329
|
return {
|
|
285
330
|
api,
|
|
286
331
|
events,
|
|
287
332
|
auth,
|
|
288
|
-
config: Object.freeze({ ...config }),
|
|
289
|
-
mount: (options) => mountApp(
|
|
290
|
-
|
|
291
|
-
|
|
333
|
+
config: Object.freeze({ ...config, mode }),
|
|
334
|
+
mount: (options) => mountApp(
|
|
335
|
+
{
|
|
336
|
+
...options,
|
|
337
|
+
mode,
|
|
338
|
+
viewerUrl: config.viewerUrl,
|
|
339
|
+
scaleRegistration
|
|
340
|
+
},
|
|
341
|
+
config.apiBase,
|
|
342
|
+
config.token || null
|
|
343
|
+
),
|
|
344
|
+
renderPassportList: (options) => renderPassportList(
|
|
345
|
+
{
|
|
346
|
+
...options,
|
|
347
|
+
mode,
|
|
348
|
+
viewerUrl: config.viewerUrl,
|
|
349
|
+
scaleRegistration
|
|
350
|
+
},
|
|
351
|
+
config.apiBase,
|
|
352
|
+
config.token || null
|
|
353
|
+
),
|
|
354
|
+
renderPassport: (options) => renderPassport(
|
|
355
|
+
{
|
|
356
|
+
...options,
|
|
357
|
+
mode,
|
|
358
|
+
viewerUrl: config.viewerUrl,
|
|
359
|
+
scaleRegistration
|
|
360
|
+
},
|
|
361
|
+
config.apiBase,
|
|
362
|
+
config.token || null
|
|
363
|
+
)
|
|
292
364
|
};
|
|
293
365
|
}
|
|
366
|
+
var HoraeSDK = {
|
|
367
|
+
init(config) {
|
|
368
|
+
return createPassportSDK(config);
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
if (typeof window !== "undefined") {
|
|
372
|
+
window.HoraeSDK = HoraeSDK;
|
|
373
|
+
}
|
|
294
374
|
// Annotate the CommonJS export names for ESM import in node:
|
|
295
375
|
0 && (module.exports = {
|
|
376
|
+
HoraeSDK,
|
|
296
377
|
createClient,
|
|
297
378
|
createClientWithAuth,
|
|
298
379
|
createCustomStrategy,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/events.ts","../src/auth/strategies/jwt.ts","../src/auth/strategies/custom.ts","../src/client.ts","../src/api.ts","../src/ui.ts"],"sourcesContent":["/**\n * @horae/passport-core\n * Reusable Passport SDK — auth strategies, Horae API client, events.\n * Token-based auth only; no cross-domain cookies.\n */\n\nexport type { PassportSDKConfig, AuthStrategy, PassportListItem, PassportDetail, User } from \"./types.js\";\nexport { createEventBus } from \"./events.js\";\nexport type { SDKEvent, EventMap, EventBus } from \"./events.js\";\nexport { createJwtStrategy, createCustomStrategy } from \"./auth/index.js\";\nexport type { AuthStrategyBase } from \"./auth/index.js\";\nexport { createClient, createClientWithAuth } from \"./client.js\";\nexport type { CreateClientOptions } from \"./client.js\";\nexport { createPassportApi } from \"./api.js\";\nexport * from \"./ui.js\";\n\nimport type { PassportSDKConfig } from \"./types.js\";\nimport { createEventBus } from \"./events.js\";\nimport { createJwtStrategy } from \"./auth/strategies/jwt.js\";\nimport { createCustomStrategy } from \"./auth/strategies/custom.js\";\nimport { createClient } from \"./client.js\";\nimport { createPassportApi } from \"./api.js\";\nimport type { AuthStrategyBase } from \"./auth/index.js\";\nimport { mountApp, renderPassportList, renderPassport } from \"./ui.js\";\nimport type { RenderOptions, RenderPassportOptions } from \"./ui.js\";\n\nexport interface PassportSDK {\n /** Horae API client (axios) */\n readonly api: ReturnType<typeof createPassportApi>;\n /** Event bus for auth:ready, auth:error, passport:claimed, etc. */\n readonly events: ReturnType<typeof createEventBus>;\n /** Auth strategy instance (for setToken/clearToken when available) */\n readonly auth: AuthStrategyBase;\n /** Config */\n readonly config: Readonly<PassportSDKConfig>;\n /** Mount the generic SDK App in headless mode */\n mount(options: RenderOptions): Promise<void>;\n /** Render the Passport List view */\n renderPassportList(options: RenderOptions): Promise<void>;\n /** Render a Single Passport Detail view */\n renderPassport(options: RenderPassportOptions): Promise<void>;\n}\n\n/**\n * Create the Passport SDK instance.\n * - authStrategy \"jwt\": pass token in config or call setToken on auth after getting JWT from your backend.\n * - authStrategy \"custom\": pass getToken in config.\n * - authStrategy \"shopify\": use @horae/passport-shopify to get JWT from bridge, then use jwt or custom.\n */\nexport function createPassportSDK(config: PassportSDKConfig): PassportSDK {\n const events = createEventBus();\n let auth: AuthStrategyBase;\n\n switch (config.authStrategy) {\n case \"jwt\": {\n const jwt = createJwtStrategy({\n token: config.token ?? undefined,\n storageKey: config.tokenStorageKey ?? undefined,\n });\n auth = jwt;\n break;\n }\n case \"custom\": {\n if (!config.getToken) throw new Error(\"PassportSDK: getToken required for authStrategy 'custom'\");\n auth = createCustomStrategy(config.getToken);\n break;\n }\n case \"shopify\":\n // Shopify: use JWT strategy; token is set by @horae/passport-shopify bridge\n auth = createJwtStrategy({\n token: config.token ?? undefined,\n storageKey: config.tokenStorageKey ?? \"shopify_access_token\",\n });\n break;\n case \"privy\":\n // Privy: use custom strategy with getToken from host (e.g. getAccessToken from @privy-io/react-auth)\n if (!config.getToken) throw new Error(\"PassportSDK: getToken required for authStrategy 'privy' (pass Privy getAccessToken)\");\n auth = createCustomStrategy(config.getToken);\n break;\n default:\n throw new Error(`PassportSDK: unknown authStrategy ${String((config as { authStrategy?: string }).authStrategy)}`);\n }\n\n const client = createClient({ apiBase: config.apiBase, getToken: () => auth.getToken() });\n const api = createPassportApi(client);\n\n return {\n api,\n events,\n auth,\n config: Object.freeze({ ...config }),\n mount: (options) => mountApp(options, config.apiBase, config.token || null),\n renderPassportList: (options) => renderPassportList(options, config.apiBase, config.token || null),\n renderPassport: (options) => renderPassport(options, config.apiBase, config.token || null),\n };\n}\n","/**\n * @horae/passport-core — event emitter for auth and passport events\n */\n\nexport type SDKEvent =\n | \"auth:ready\"\n | \"auth:error\"\n | \"passport:claimed\"\n | \"passport:loaded\"\n | \"passport:list:loaded\"\n | \"token:expired\";\n\nexport type EventMap = {\n \"auth:ready\": void;\n \"auth:error\": { message: string; code?: string };\n \"passport:claimed\": { tokenId: string };\n \"passport:loaded\": { tokenId: string };\n \"passport:list:loaded\": { count: number };\n \"token:expired\": void;\n};\n\ntype Listener<T> = (payload: T) => void;\n\nexport function createEventBus() {\n const listeners = new Map<SDKEvent, Set<Listener<unknown>>>();\n\n function on<E extends SDKEvent>(event: E, fn: Listener<EventMap[E]>) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(fn as Listener<unknown>);\n return () => listeners.get(event)?.delete(fn as Listener<unknown>);\n }\n\n function emit<E extends SDKEvent>(event: E, payload?: EventMap[E]) {\n listeners.get(event)?.forEach((fn) => (fn as Listener<EventMap[E]>)(payload as EventMap[E]));\n }\n\n return { on, emit };\n}\n\nexport type EventBus = ReturnType<typeof createEventBus>;\n","/**\n * JWT strategy — token from config or setToken; optional localStorage persistence\n */\n\nimport type { AuthStrategyBase } from \"../types.js\";\n\nexport interface JwtStrategyOptions {\n /** Initial token */\n token?: string | null;\n /** localStorage key for persistence (omit for in-memory only) */\n storageKey?: string | null;\n}\n\nexport function createJwtStrategy(options: JwtStrategyOptions = {}): AuthStrategyBase {\n let token: string | null = options.token ?? null;\n const storageKey = options.storageKey ?? null;\n\n const storage = typeof window !== \"undefined\" ? window.localStorage : undefined;\n if (storage && storageKey) {\n try {\n const stored = storage.getItem(storageKey);\n if (stored) token = stored;\n } catch {\n // ignore\n }\n }\n\n return {\n async getToken() {\n return token;\n },\n setToken(next: string | null) {\n token = next;\n if (storage && storageKey) {\n try {\n if (next) storage.setItem(storageKey, next);\n else storage.removeItem(storageKey);\n } catch {\n // ignore\n }\n }\n },\n clearToken() {\n token = null;\n if (storage && storageKey) {\n try {\n storage.removeItem(storageKey);\n } catch {\n // ignore\n }\n }\n },\n };\n}\n","/**\n * Custom strategy — caller supplies getToken (e.g. from backend or Privy)\n */\n\nimport type { AuthStrategyBase } from \"../types.js\";\n\nexport function createCustomStrategy(\n getToken: () => Promise<string | null>,\n): AuthStrategyBase {\n return { getToken };\n}\n","/**\n * Horae API client — axios instance with Bearer token from auth strategy\n */\n\nimport axios, { type AxiosInstance } from \"axios\";\nimport type { AuthStrategyBase } from \"./auth/index.js\";\n\nexport interface CreateClientOptions {\n apiBase: string;\n getToken: () => Promise<string | null>;\n}\n\nexport function createClient(options: CreateClientOptions): AxiosInstance {\n const { apiBase, getToken } = options;\n const client = axios.create({\n baseURL: apiBase.replace(/\\/v1\\/?$/, \"\") + \"/v1\",\n });\n\n client.interceptors.request.use(async (config) => {\n const token = await getToken();\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n config.headers[\"ngrok-skip-browser-warning\"] = \"true\";\n return config;\n });\n\n return client;\n}\n\nexport function createClientWithAuth(auth: AuthStrategyBase, apiBase: string): AxiosInstance {\n return createClient({\n apiBase,\n getToken: () => auth.getToken(),\n });\n}\n","/**\n * Horae Passport API — list, single, claim, user, documents\n * Mirrors passport-web shared/api/api.service.ts (token-based auth)\n */\n\nimport type { AxiosInstance } from \"axios\";\nimport type { PassportListItem, PassportDetail, User } from \"./types.js\";\n\nfunction unwrapItems<T>(response: { data?: unknown }): T[] {\n const data = response.data as { data?: { items?: T[] }; items?: T[] } | T[] | undefined;\n if (Array.isArray(data)) return data;\n const inner = data && typeof data === \"object\" && \"data\" in data ? (data as { data?: { items?: T[] } }).data : data;\n const items = (inner && typeof inner === \"object\" && \"items\" in inner\n ? (inner as { items?: T[] }).items\n : Array.isArray(inner)\n ? inner\n : []) as T[];\n return items ?? [];\n}\n\nfunction unwrapData<T>(response: { data?: unknown }): T {\n const data = response.data as { data?: T } | T;\n return (data && typeof data === \"object\" && \"data\" in data ? (data as { data: T }).data : data) as T;\n}\n\nexport function createPassportApi(api: AxiosInstance) {\n return {\n /** List passports claimed by current user */\n async getMyClaimedPassports(): Promise<PassportListItem[]> {\n const res = await api.get(\"/api/passport/claimed\");\n return unwrapItems<PassportListItem>(res) as PassportListItem[];\n },\n\n /** List passports by owner wallet (e.g. Shopify) */\n async getPassportsByOwner(ownerWallet: string): Promise<PassportListItem[]> {\n const res = await api.get(\"/api/passport/claimed\", { params: { owner: ownerWallet } });\n return unwrapItems<PassportListItem>(res) as PassportListItem[];\n },\n\n /** Single passport (authenticated) */\n async getPassport(tokenId: string, isAuthenticated = true): Promise<PassportDetail> {\n const path = isAuthenticated ? `/api/passport/${tokenId}` : `/api/passport/public/${tokenId}`;\n const res = await api.get(path);\n return unwrapData<PassportDetail>(res);\n },\n\n /** Claim passport */\n async claimPassport(data: { tokenId: string; toAddress: string; claimKey: string }) {\n await api.post(\"/api/passport/claim\", data);\n },\n\n /** Shopify claim (serialNumber + optional email) */\n async claimShopifyPassport(data: { serialNumber: string; email?: string }) {\n await api.post(\"/api/passport/shopify-claim\", data);\n },\n\n /** Current user profile */\n async getMe(): Promise<User> {\n const res = await api.get(\"/users/me\");\n const raw = unwrapData<unknown>(res);\n const doc = raw && typeof raw === \"object\" && \"_doc\" in raw ? (raw as { _doc: User })._doc : raw;\n return doc as User;\n },\n\n /** Documents for a passport (owner gets file URLs) */\n async getDocuments(tokenId: string): Promise<{ url?: string; name?: string; [k: string]: unknown }[]> {\n const res = await api.get(`/api/passport/${tokenId}/documents`);\n const responseData = (res.data as { data?: unknown })?.data ?? res.data;\n if (responseData && typeof responseData === \"object\" && \"data\" in responseData && Array.isArray((responseData as { data: unknown[] }).data))\n return (responseData as { data: unknown[] }).data as { url?: string; name?: string; [k: string]: unknown }[];\n if (Array.isArray(responseData)) return responseData as { url?: string; name?: string; [k: string]: unknown }[];\n return [];\n },\n\n /** Transfer passport to user by email */\n async transferPassportToUser(data: { tokenId: string; recipientEmail: string }) {\n await api.post(\"/api/passport/transfer-to-user\", data);\n },\n\n /** Set stolen status */\n async setStolenStatus(data: { tokenId: string; isStolen: boolean }) {\n await api.post(\"/api/passport/set-stolen\", data);\n },\n };\n}\n","/**\n * UI Renderer for @horae/passport-core\n * Dynamically injects the pre-built React SDK bundle to render the UI on the host page.\n */\n\nexport interface RenderOptions {\n /** CSS selector of the container element (e.g. \"#passport-app\") */\n container: string;\n /** UI Host base URL where the bundle is served (default: https://app.horae.io) */\n uiHost?: string;\n /** Initial tab/view (e.g. \"passports\", \"claim\", \"settings\") */\n initialTab?: string;\n}\n\nexport interface RenderPassportOptions extends RenderOptions {\n /** The ID of the passport to show */\n passportId: string;\n}\n\n/**\n * Configure the container with data attributes so the UI bundle can read them upon mounting.\n */\nfunction prepareContainer(options: RenderOptions, apiBase: string, token: string | null) {\n const containerEl = document.querySelector(options.container);\n if (!containerEl) {\n throw new Error(`PassportSDK: container element '${options.container}' not found.`);\n }\n\n // Set necessary data attributes for the UI bundle (similar to Shopify embed contract)\n if (containerEl instanceof HTMLElement) {\n containerEl.dataset.horaeApiBase = apiBase;\n if (options.initialTab) {\n containerEl.dataset.initialTab = options.initialTab;\n }\n\n // Inject the token (the UI bundle will look for this or use its own mechanism)\n if (token) {\n containerEl.dataset.horaeToken = token;\n }\n\n // Add a signature class/id to ensure the embed root is identifiable\n containerEl.classList.add(\"horae-sdk-root\");\n\n // Allow the bundle to easily find its mount point if it uses querySelector internally\n // (We also pass the container selector directly to the mount event later if needed)\n containerEl.dataset.containerSelector = options.container;\n }\n\n return containerEl;\n}\n\n/**\n * Inject the script tag for the UI bundle if it hasn't been injected yet.\n */\nfunction loadUIBundle(uiHost: string): Promise<void> {\n const SCRIPT_ID = \"horae-passport-sdk-ui\";\n\n return new Promise((resolve, reject) => {\n if (document.getElementById(SCRIPT_ID)) {\n // Script already added\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.id = SCRIPT_ID;\n script.type = \"module\";\n // Target the newly created sdk-embed entrypoint\n script.src = `${uiHost.replace(/\\/$/, '')}/sdk-embed.js`;\n\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`PassportSDK: Failed to load UI bundle from ${script.src}`));\n\n document.head.appendChild(script);\n });\n}\n\n/**\n * Render the generic SDK App\n */\nexport async function mountApp(\n options: RenderOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n prepareContainer(options, apiBase, token);\n\n const host = options.uiHost || \"https://app.horae.io\";\n await loadUIBundle(host);\n\n // Dispatch a custom event in case the bundle is already loaded and listening for dynamic mounts\n window.dispatchEvent(new CustomEvent(\"horae:sdk:mount\", {\n detail: { container: options.container }\n }));\n}\n\n/**\n * Render specifically the Passport List (maps to \"passports\" tab/view)\n */\nexport async function renderPassportList(\n options: RenderOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n return mountApp({ ...options, initialTab: \"passports\" }, apiBase, token);\n}\n\n/**\n * Render specifically a Single Passport (maps to a specific detail view layout)\n */\nexport async function renderPassport(\n options: RenderPassportOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n const containerEl = prepareContainer(options, apiBase, token);\n\n if (containerEl instanceof HTMLElement) {\n containerEl.dataset.passportId = options.passportId;\n // Set initialTab to \"detail\" or a specific flag the UI recognizes\n containerEl.dataset.initialTab = \"detail\";\n }\n\n const host = options.uiHost || \"https://app.horae.io\";\n await loadUIBundle(host);\n\n window.dispatchEvent(new CustomEvent(\"horae:sdk:mount\", {\n detail: { container: options.container, passportId: options.passportId }\n }));\n}\n"],"mappings":"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","names":["axios"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/events.ts","../src/auth/strategies/jwt.ts","../src/auth/strategies/custom.ts","../src/client.ts","../src/api.ts","../src/ui.ts"],"sourcesContent":["/**\n * @horae/passport-core\n * Reusable Passport SDK — auth strategies, Horae API client, events.\n * Token-based auth only; no cross-domain cookies.\n */\n\nexport type {\n PassportSDKConfig,\n AuthStrategy,\n PassportListItem,\n PassportDetail,\n ScaleRegistrationPayload,\n SDKMode,\n User,\n} from \"./types.js\";\nexport { createEventBus } from \"./events.js\";\nexport type { SDKEvent, EventMap, EventBus } from \"./events.js\";\nexport { createJwtStrategy, createCustomStrategy } from \"./auth/index.js\";\nexport type { AuthStrategyBase } from \"./auth/index.js\";\nexport { createClient, createClientWithAuth } from \"./client.js\";\nexport type { CreateClientOptions } from \"./client.js\";\nexport { createPassportApi } from \"./api.js\";\nexport * from \"./ui.js\";\n\nimport type { PassportSDKConfig } from \"./types.js\";\nimport { createEventBus } from \"./events.js\";\nimport { createJwtStrategy } from \"./auth/strategies/jwt.js\";\nimport { createCustomStrategy } from \"./auth/strategies/custom.js\";\nimport { createClient } from \"./client.js\";\nimport { createPassportApi } from \"./api.js\";\nimport type { AuthStrategyBase } from \"./auth/index.js\";\nimport { mountApp, renderPassportList, renderPassport } from \"./ui.js\";\nimport type { RenderOptions, RenderPassportOptions } from \"./ui.js\";\n\nexport interface PassportSDK {\n /** Horae API client (axios) */\n readonly api: ReturnType<typeof createPassportApi>;\n /** Event bus for auth:ready, auth:error, passport:claimed, etc. */\n readonly events: ReturnType<typeof createEventBus>;\n /** Auth strategy instance (for setToken/clearToken when available) */\n readonly auth: AuthStrategyBase;\n /** Config */\n readonly config: Readonly<PassportSDKConfig>;\n /** Mount the generic SDK App in headless mode */\n mount(options: RenderOptions): Promise<void>;\n /** Render the Passport List view */\n renderPassportList(options: RenderOptions): Promise<void>;\n /** Render a Single Passport Detail view */\n renderPassport(options: RenderPassportOptions): Promise<void>;\n}\n\n/**\n * Create the Passport SDK instance.\n * - authStrategy \"jwt\": pass token in config or call setToken on auth after getting JWT from your backend.\n * - authStrategy \"custom\": pass getToken in config.\n * - authStrategy \"shopify\": use @horae/passport-shopify to get JWT from bridge, then use jwt or custom.\n */\nexport function createPassportSDK(config: PassportSDKConfig): PassportSDK {\n const mode = config.mode ?? \"heritage\";\n const authStrategy = config.authStrategy ?? (mode === \"scale\" ? \"custom\" : \"jwt\");\n const events = createEventBus();\n let auth: AuthStrategyBase;\n\n if (mode === \"scale\") {\n // Scale mode does not require wallet/Privy token flow by default.\n auth = createCustomStrategy(async () => config.token ?? null);\n } else {\n switch (authStrategy) {\n case \"jwt\": {\n const jwt = createJwtStrategy({\n token: config.token ?? undefined,\n storageKey: config.tokenStorageKey ?? undefined,\n });\n auth = jwt;\n break;\n }\n case \"custom\": {\n if (!config.getToken) throw new Error(\"PassportSDK: getToken required for authStrategy 'custom'\");\n auth = createCustomStrategy(config.getToken);\n break;\n }\n case \"shopify\":\n // Shopify: use JWT strategy; token is set by @horae/passport-shopify bridge\n auth = createJwtStrategy({\n token: config.token ?? undefined,\n storageKey: config.tokenStorageKey ?? \"shopify_access_token\",\n });\n break;\n case \"privy\":\n // Privy: use custom strategy with getToken from host (e.g. getAccessToken from @privy-io/react-auth)\n if (!config.getToken) throw new Error(\"PassportSDK: getToken required for authStrategy 'privy' (pass Privy getAccessToken)\");\n auth = createCustomStrategy(config.getToken);\n break;\n default:\n throw new Error(`PassportSDK: unknown authStrategy ${String(authStrategy)}`);\n }\n }\n\n const client = createClient({ apiBase: config.apiBase, getToken: () => auth.getToken() });\n const api = createPassportApi(client);\n const fallbackScaleRegistration =\n config.serial || config.brandId\n ? {\n serialNumber: config.serial,\n manufacturerId: config.brandId,\n }\n : undefined;\n const scaleRegistrationPayload = config.scaleRegistration ?? fallbackScaleRegistration;\n const scaleRegistration = scaleRegistrationPayload\n ? JSON.stringify(scaleRegistrationPayload)\n : undefined;\n\n return {\n api,\n events,\n auth,\n config: Object.freeze({ ...config, mode }),\n mount: (options) =>\n mountApp(\n {\n ...options,\n mode,\n viewerUrl: config.viewerUrl,\n scaleRegistration,\n },\n config.apiBase,\n config.token || null,\n ),\n renderPassportList: (options) =>\n renderPassportList(\n {\n ...options,\n mode,\n viewerUrl: config.viewerUrl,\n scaleRegistration,\n },\n config.apiBase,\n config.token || null,\n ),\n renderPassport: (options) =>\n renderPassport(\n {\n ...options,\n mode,\n viewerUrl: config.viewerUrl,\n scaleRegistration,\n },\n config.apiBase,\n config.token || null,\n ),\n };\n}\n\nexport const HoraeSDK = {\n init(config: PassportSDKConfig): PassportSDK {\n return createPassportSDK(config);\n },\n};\n\ndeclare global {\n interface Window {\n HoraeSDK?: typeof HoraeSDK;\n }\n}\n\nif (typeof window !== \"undefined\") {\n window.HoraeSDK = HoraeSDK;\n}\n","/**\n * @horae/passport-core — event emitter for auth and passport events\n */\n\nexport type SDKEvent =\n | \"auth:ready\"\n | \"auth:error\"\n | \"passport:claimed\"\n | \"passport:loaded\"\n | \"passport:list:loaded\"\n | \"token:expired\";\n\nexport type EventMap = {\n \"auth:ready\": void;\n \"auth:error\": { message: string; code?: string };\n \"passport:claimed\": { tokenId: string };\n \"passport:loaded\": { tokenId: string };\n \"passport:list:loaded\": { count: number };\n \"token:expired\": void;\n};\n\ntype Listener<T> = (payload: T) => void;\n\nexport function createEventBus() {\n const listeners = new Map<SDKEvent, Set<Listener<unknown>>>();\n\n function on<E extends SDKEvent>(event: E, fn: Listener<EventMap[E]>) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(fn as Listener<unknown>);\n return () => listeners.get(event)?.delete(fn as Listener<unknown>);\n }\n\n function emit<E extends SDKEvent>(event: E, payload?: EventMap[E]) {\n listeners.get(event)?.forEach((fn) => (fn as Listener<EventMap[E]>)(payload as EventMap[E]));\n }\n\n return { on, emit };\n}\n\nexport type EventBus = ReturnType<typeof createEventBus>;\n","/**\n * JWT strategy — token from config or setToken; optional localStorage persistence\n */\n\nimport type { AuthStrategyBase } from \"../types.js\";\n\nexport interface JwtStrategyOptions {\n /** Initial token */\n token?: string | null;\n /** localStorage key for persistence (omit for in-memory only) */\n storageKey?: string | null;\n}\n\nexport function createJwtStrategy(options: JwtStrategyOptions = {}): AuthStrategyBase {\n let token: string | null = options.token ?? null;\n const storageKey = options.storageKey ?? null;\n\n const storage = typeof window !== \"undefined\" ? window.localStorage : undefined;\n if (storage && storageKey) {\n try {\n const stored = storage.getItem(storageKey);\n if (stored) token = stored;\n } catch {\n // ignore\n }\n }\n\n return {\n async getToken() {\n return token;\n },\n setToken(next: string | null) {\n token = next;\n if (storage && storageKey) {\n try {\n if (next) storage.setItem(storageKey, next);\n else storage.removeItem(storageKey);\n } catch {\n // ignore\n }\n }\n },\n clearToken() {\n token = null;\n if (storage && storageKey) {\n try {\n storage.removeItem(storageKey);\n } catch {\n // ignore\n }\n }\n },\n };\n}\n","/**\n * Custom strategy — caller supplies getToken (e.g. from backend or Privy)\n */\n\nimport type { AuthStrategyBase } from \"../types.js\";\n\nexport function createCustomStrategy(\n getToken: () => Promise<string | null>,\n): AuthStrategyBase {\n return { getToken };\n}\n","/**\n * Horae API client — axios instance with Bearer token from auth strategy\n */\n\nimport axios, { type AxiosInstance } from \"axios\";\nimport type { AuthStrategyBase } from \"./auth/index.js\";\n\nexport interface CreateClientOptions {\n apiBase: string;\n getToken: () => Promise<string | null>;\n}\n\nexport function createClient(options: CreateClientOptions): AxiosInstance {\n const { apiBase, getToken } = options;\n const client = axios.create({\n baseURL: apiBase.replace(/\\/v1\\/?$/, \"\") + \"/v1\",\n });\n\n client.interceptors.request.use(async (config) => {\n const token = await getToken();\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n config.headers[\"ngrok-skip-browser-warning\"] = \"true\";\n return config;\n });\n\n return client;\n}\n\nexport function createClientWithAuth(auth: AuthStrategyBase, apiBase: string): AxiosInstance {\n return createClient({\n apiBase,\n getToken: () => auth.getToken(),\n });\n}\n","/**\n * Horae Passport API — list, single, claim, user, documents\n * Mirrors passport-web shared/api/api.service.ts (token-based auth)\n */\n\nimport type { AxiosInstance } from \"axios\";\nimport type {\n PassportListItem,\n PassportDetail,\n ScaleRegistrationPayload,\n User,\n} from \"./types.js\";\n\nfunction unwrapItems<T>(response: { data?: unknown }): T[] {\n const data = response.data as { data?: { items?: T[] }; items?: T[] } | T[] | undefined;\n if (Array.isArray(data)) return data;\n const inner = data && typeof data === \"object\" && \"data\" in data ? (data as { data?: { items?: T[] } }).data : data;\n const items = (inner && typeof inner === \"object\" && \"items\" in inner\n ? (inner as { items?: T[] }).items\n : Array.isArray(inner)\n ? inner\n : []) as T[];\n return items ?? [];\n}\n\nfunction unwrapData<T>(response: { data?: unknown }): T {\n const data = response.data as { data?: T } | T;\n return (data && typeof data === \"object\" && \"data\" in data ? (data as { data: T }).data : data) as T;\n}\n\nexport function createPassportApi(api: AxiosInstance) {\n return {\n /** List passports claimed by current user */\n async getMyClaimedPassports(): Promise<PassportListItem[]> {\n const res = await api.get(\"/api/passport/claimed\");\n return unwrapItems<PassportListItem>(res) as PassportListItem[];\n },\n\n /** List passports by owner wallet (e.g. Shopify) */\n async getPassportsByOwner(ownerWallet: string): Promise<PassportListItem[]> {\n const res = await api.get(\"/api/passport/claimed\", { params: { owner: ownerWallet } });\n return unwrapItems<PassportListItem>(res) as PassportListItem[];\n },\n\n /** Single passport (authenticated) */\n async getPassport(tokenId: string, isAuthenticated = true): Promise<PassportDetail> {\n const path = isAuthenticated ? `/api/passport/${tokenId}` : `/api/passport/public/${tokenId}`;\n const res = await api.get(path);\n return unwrapData<PassportDetail>(res);\n },\n\n /** Claim passport */\n async claimPassport(data: { tokenId: string; toAddress: string; claimKey: string }) {\n await api.post(\"/api/passport/claim\", data);\n },\n\n /** Shopify claim (serialNumber + optional email) */\n async claimShopifyPassport(data: { serialNumber: string; email?: string }) {\n await api.post(\"/api/passport/shopify-claim\", data);\n },\n\n /** Scale owner registration (serial/email based, no wallet) */\n async registerScaleOwner(payload: ScaleRegistrationPayload): Promise<{\n success: boolean;\n tokenId: string;\n ownerUrl?: string;\n viewerUrl?: string;\n }> {\n const res = await api.post(\"/api/passport/scale/register\", payload);\n return unwrapData<{\n success: boolean;\n tokenId: string;\n ownerUrl?: string;\n viewerUrl?: string;\n }>(res);\n },\n\n /** Scale signed viewer (HMAC signature) */\n async getScaleViewer(tokenId: string, sig: string): Promise<PassportDetail> {\n const res = await api.get(`/api/passport/scale/view/${tokenId}`, {\n params: { sig },\n });\n return unwrapData<PassportDetail>(res);\n },\n\n /** Current user profile */\n async getMe(): Promise<User> {\n const res = await api.get(\"/users/me\");\n const raw = unwrapData<unknown>(res);\n const doc = raw && typeof raw === \"object\" && \"_doc\" in raw ? (raw as { _doc: User })._doc : raw;\n return doc as User;\n },\n\n /** Documents for a passport (owner gets file URLs) */\n async getDocuments(tokenId: string): Promise<{ url?: string; name?: string; [k: string]: unknown }[]> {\n const res = await api.get(`/api/passport/${tokenId}/documents`);\n const responseData = (res.data as { data?: unknown })?.data ?? res.data;\n if (responseData && typeof responseData === \"object\" && \"data\" in responseData && Array.isArray((responseData as { data: unknown[] }).data))\n return (responseData as { data: unknown[] }).data as { url?: string; name?: string; [k: string]: unknown }[];\n if (Array.isArray(responseData)) return responseData as { url?: string; name?: string; [k: string]: unknown }[];\n return [];\n },\n\n /** Transfer passport to user by email */\n async transferPassportToUser(data: { tokenId: string; recipientEmail: string }) {\n await api.post(\"/api/passport/transfer-to-user\", data);\n },\n\n /** Set stolen status */\n async setStolenStatus(data: { tokenId: string; isStolen: boolean }) {\n await api.post(\"/api/passport/set-stolen\", data);\n },\n };\n}\n","/**\n * UI Renderer for @horae/passport-core\n * Dynamically injects the pre-built React SDK bundle to render the UI on the host page.\n */\n\nexport interface RenderOptions {\n /** CSS selector of the container element (e.g. \"#passport-app\") */\n container: string;\n /** UI Host base URL where the bundle is served (default: https://app.horae.io) */\n uiHost?: string;\n /** Initial tab/view (e.g. \"passports\", \"claim\", \"settings\") */\n initialTab?: string;\n /** SDK mode */\n mode?: \"heritage\" | \"scale\";\n /** Scale mode signed viewer URL */\n viewerUrl?: string;\n /** Scale mode registration prefill as JSON string */\n scaleRegistration?: string;\n}\n\nexport interface RenderPassportOptions extends RenderOptions {\n /** The ID of the passport to show */\n passportId: string;\n}\n\n/**\n * Configure the container with data attributes so the UI bundle can read them upon mounting.\n */\nfunction prepareContainer(options: RenderOptions, apiBase: string, token: string | null) {\n const containerEl = document.querySelector(options.container);\n if (!containerEl) {\n throw new Error(`PassportSDK: container element '${options.container}' not found.`);\n }\n\n // Set necessary data attributes for the UI bundle (similar to Shopify embed contract)\n if (containerEl instanceof HTMLElement) {\n containerEl.dataset.horaeApiBase = apiBase;\n if (options.initialTab) {\n containerEl.dataset.initialTab = options.initialTab;\n }\n if (options.mode) {\n containerEl.dataset.horaeMode = options.mode;\n }\n if (options.viewerUrl) {\n containerEl.dataset.horaeViewerUrl = options.viewerUrl;\n }\n if (options.scaleRegistration) {\n containerEl.dataset.horaeScaleRegistration = options.scaleRegistration;\n }\n\n // Inject the token (the UI bundle will look for this or use its own mechanism)\n if (token) {\n containerEl.dataset.horaeToken = token;\n }\n\n // Add a signature class/id to ensure the embed root is identifiable\n containerEl.classList.add(\"horae-sdk-root\");\n\n // Allow the bundle to easily find its mount point if it uses querySelector internally\n // (We also pass the container selector directly to the mount event later if needed)\n containerEl.dataset.containerSelector = options.container;\n }\n\n return containerEl;\n}\n\n/**\n * Inject the script tag for the UI bundle if it hasn't been injected yet.\n */\nfunction loadUIBundle(uiHost: string): Promise<void> {\n const SCRIPT_ID = \"horae-passport-sdk-ui\";\n\n return new Promise((resolve, reject) => {\n if (document.getElementById(SCRIPT_ID)) {\n // Script already added\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.id = SCRIPT_ID;\n script.type = \"module\";\n // Target the newly created sdk-embed entrypoint\n script.src = `${uiHost.replace(/\\/$/, '')}/sdk-embed.js`;\n\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`PassportSDK: Failed to load UI bundle from ${script.src}`));\n\n document.head.appendChild(script);\n });\n}\n\n/**\n * Render the generic SDK App\n */\nexport async function mountApp(\n options: RenderOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n prepareContainer(options, apiBase, token);\n\n const host = options.uiHost || \"https://app.horae.io\";\n await loadUIBundle(host);\n\n // Dispatch a custom event in case the bundle is already loaded and listening for dynamic mounts\n window.dispatchEvent(new CustomEvent(\"horae:sdk:mount\", {\n detail: {\n container: options.container,\n mode: options.mode,\n viewerUrl: options.viewerUrl,\n scaleRegistration: options.scaleRegistration\n }\n }));\n}\n\n/**\n * Render specifically the Passport List (maps to \"passports\" tab/view)\n */\nexport async function renderPassportList(\n options: RenderOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n return mountApp({ ...options, initialTab: \"passports\" }, apiBase, token);\n}\n\n/**\n * Render specifically a Single Passport (maps to a specific detail view layout)\n */\nexport async function renderPassport(\n options: RenderPassportOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n const containerEl = prepareContainer(options, apiBase, token);\n\n if (containerEl instanceof HTMLElement) {\n containerEl.dataset.passportId = options.passportId;\n // Set initialTab to \"detail\" or a specific flag the UI recognizes\n containerEl.dataset.initialTab = \"detail\";\n }\n\n const host = options.uiHost || \"https://app.horae.io\";\n await loadUIBundle(host);\n\n window.dispatchEvent(new CustomEvent(\"horae:sdk:mount\", {\n detail: {\n container: options.container,\n passportId: options.passportId,\n mode: options.mode,\n viewerUrl: options.viewerUrl,\n scaleRegistration: options.scaleRegistration\n }\n }));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACuBO,SAAS,iBAAiB;AAC/B,QAAM,YAAY,oBAAI,IAAsC;AAE5D,WAAS,GAAuB,OAAU,IAA2B;AACnE,QAAI,CAAC,UAAU,IAAI,KAAK,EAAG,WAAU,IAAI,OAAO,oBAAI,IAAI,CAAC;AACzD,cAAU,IAAI,KAAK,EAAG,IAAI,EAAuB;AACjD,WAAO,MAAM,UAAU,IAAI,KAAK,GAAG,OAAO,EAAuB;AAAA,EACnE;AAEA,WAAS,KAAyB,OAAU,SAAuB;AACjE,cAAU,IAAI,KAAK,GAAG,QAAQ,CAAC,OAAQ,GAA6B,OAAsB,CAAC;AAAA,EAC7F;AAEA,SAAO,EAAE,IAAI,KAAK;AACpB;;;ACxBO,SAAS,kBAAkB,UAA8B,CAAC,GAAqB;AACpF,MAAI,QAAuB,QAAQ,SAAS;AAC5C,QAAM,aAAa,QAAQ,cAAc;AAEzC,QAAM,UAAU,OAAO,WAAW,cAAc,OAAO,eAAe;AACtE,MAAI,WAAW,YAAY;AACzB,QAAI;AACF,YAAM,SAAS,QAAQ,QAAQ,UAAU;AACzC,UAAI,OAAQ,SAAQ;AAAA,IACtB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,WAAW;AACf,aAAO;AAAA,IACT;AAAA,IACA,SAAS,MAAqB;AAC5B,cAAQ;AACR,UAAI,WAAW,YAAY;AACzB,YAAI;AACF,cAAI,KAAM,SAAQ,QAAQ,YAAY,IAAI;AAAA,cACrC,SAAQ,WAAW,UAAU;AAAA,QACpC,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,IACA,aAAa;AACX,cAAQ;AACR,UAAI,WAAW,YAAY;AACzB,YAAI;AACF,kBAAQ,WAAW,UAAU;AAAA,QAC/B,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC/CO,SAAS,qBACd,UACkB;AAClB,SAAO,EAAE,SAAS;AACpB;;;ACNA,mBAA0C;AAQnC,SAAS,aAAa,SAA6C;AACxE,QAAM,EAAE,SAAS,SAAS,IAAI;AAC9B,QAAM,SAAS,aAAAA,QAAM,OAAO;AAAA,IAC1B,SAAS,QAAQ,QAAQ,YAAY,EAAE,IAAI;AAAA,EAC7C,CAAC;AAED,SAAO,aAAa,QAAQ,IAAI,OAAO,WAAW;AAChD,UAAM,QAAQ,MAAM,SAAS;AAC7B,QAAI,OAAO;AACT,aAAO,QAAQ,gBAAgB,UAAU,KAAK;AAAA,IAChD;AACA,WAAO,QAAQ,4BAA4B,IAAI;AAC/C,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AACT;AAEO,SAAS,qBAAqB,MAAwB,SAAgC;AAC3F,SAAO,aAAa;AAAA,IAClB;AAAA,IACA,UAAU,MAAM,KAAK,SAAS;AAAA,EAChC,CAAC;AACH;;;ACtBA,SAAS,YAAe,UAAmC;AACzD,QAAM,OAAO,SAAS;AACtB,MAAI,MAAM,QAAQ,IAAI,EAAG,QAAO;AAChC,QAAM,QAAQ,QAAQ,OAAO,SAAS,YAAY,UAAU,OAAQ,KAAoC,OAAO;AAC/G,QAAM,QAAS,SAAS,OAAO,UAAU,YAAY,WAAW,QAC3D,MAA0B,QAC3B,MAAM,QAAQ,KAAK,IACjB,QACA,CAAC;AACP,SAAO,SAAS,CAAC;AACnB;AAEA,SAAS,WAAc,UAAiC;AACtD,QAAM,OAAO,SAAS;AACtB,SAAQ,QAAQ,OAAO,SAAS,YAAY,UAAU,OAAQ,KAAqB,OAAO;AAC5F;AAEO,SAAS,kBAAkB,KAAoB;AACpD,SAAO;AAAA;AAAA,IAEL,MAAM,wBAAqD;AACzD,YAAM,MAAM,MAAM,IAAI,IAAI,uBAAuB;AACjD,aAAO,YAA8B,GAAG;AAAA,IAC1C;AAAA;AAAA,IAGA,MAAM,oBAAoB,aAAkD;AAC1E,YAAM,MAAM,MAAM,IAAI,IAAI,yBAAyB,EAAE,QAAQ,EAAE,OAAO,YAAY,EAAE,CAAC;AACrF,aAAO,YAA8B,GAAG;AAAA,IAC1C;AAAA;AAAA,IAGA,MAAM,YAAY,SAAiB,kBAAkB,MAA+B;AAClF,YAAM,OAAO,kBAAkB,iBAAiB,OAAO,KAAK,wBAAwB,OAAO;AAC3F,YAAM,MAAM,MAAM,IAAI,IAAI,IAAI;AAC9B,aAAO,WAA2B,GAAG;AAAA,IACvC;AAAA;AAAA,IAGA,MAAM,cAAc,MAAgE;AAClF,YAAM,IAAI,KAAK,uBAAuB,IAAI;AAAA,IAC5C;AAAA;AAAA,IAGA,MAAM,qBAAqB,MAAgD;AACzE,YAAM,IAAI,KAAK,+BAA+B,IAAI;AAAA,IACpD;AAAA;AAAA,IAGA,MAAM,mBAAmB,SAKtB;AACD,YAAM,MAAM,MAAM,IAAI,KAAK,gCAAgC,OAAO;AAClE,aAAO,WAKJ,GAAG;AAAA,IACR;AAAA;AAAA,IAGA,MAAM,eAAe,SAAiB,KAAsC;AAC1E,YAAM,MAAM,MAAM,IAAI,IAAI,4BAA4B,OAAO,IAAI;AAAA,QAC/D,QAAQ,EAAE,IAAI;AAAA,MAChB,CAAC;AACD,aAAO,WAA2B,GAAG;AAAA,IACvC;AAAA;AAAA,IAGA,MAAM,QAAuB;AAC3B,YAAM,MAAM,MAAM,IAAI,IAAI,WAAW;AACrC,YAAM,MAAM,WAAoB,GAAG;AACnC,YAAM,MAAM,OAAO,OAAO,QAAQ,YAAY,UAAU,MAAO,IAAuB,OAAO;AAC7F,aAAO;AAAA,IACT;AAAA;AAAA,IAGA,MAAM,aAAa,SAAmF;AACpG,YAAM,MAAM,MAAM,IAAI,IAAI,iBAAiB,OAAO,YAAY;AAC9D,YAAM,eAAgB,IAAI,MAA6B,QAAQ,IAAI;AACnE,UAAI,gBAAgB,OAAO,iBAAiB,YAAY,UAAU,gBAAgB,MAAM,QAAS,aAAqC,IAAI;AACxI,eAAQ,aAAqC;AAC/C,UAAI,MAAM,QAAQ,YAAY,EAAG,QAAO;AACxC,aAAO,CAAC;AAAA,IACV;AAAA;AAAA,IAGA,MAAM,uBAAuB,MAAmD;AAC9E,YAAM,IAAI,KAAK,kCAAkC,IAAI;AAAA,IACvD;AAAA;AAAA,IAGA,MAAM,gBAAgB,MAA8C;AAClE,YAAM,IAAI,KAAK,4BAA4B,IAAI;AAAA,IACjD;AAAA,EACF;AACF;;;ACrFA,SAAS,iBAAiB,SAAwB,SAAiB,OAAsB;AACrF,QAAM,cAAc,SAAS,cAAc,QAAQ,SAAS;AAC5D,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,mCAAmC,QAAQ,SAAS,cAAc;AAAA,EACtF;AAGA,MAAI,uBAAuB,aAAa;AACpC,gBAAY,QAAQ,eAAe;AACnC,QAAI,QAAQ,YAAY;AACpB,kBAAY,QAAQ,aAAa,QAAQ;AAAA,IAC7C;AACA,QAAI,QAAQ,MAAM;AACd,kBAAY,QAAQ,YAAY,QAAQ;AAAA,IAC5C;AACA,QAAI,QAAQ,WAAW;AACnB,kBAAY,QAAQ,iBAAiB,QAAQ;AAAA,IACjD;AACA,QAAI,QAAQ,mBAAmB;AAC3B,kBAAY,QAAQ,yBAAyB,QAAQ;AAAA,IACzD;AAGA,QAAI,OAAO;AACP,kBAAY,QAAQ,aAAa;AAAA,IACrC;AAGA,gBAAY,UAAU,IAAI,gBAAgB;AAI1C,gBAAY,QAAQ,oBAAoB,QAAQ;AAAA,EACpD;AAEA,SAAO;AACX;AAKA,SAAS,aAAa,QAA+B;AACjD,QAAM,YAAY;AAElB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,QAAI,SAAS,eAAe,SAAS,GAAG;AAEpC,cAAQ;AACR;AAAA,IACJ;AAEA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,KAAK;AACZ,WAAO,OAAO;AAEd,WAAO,MAAM,GAAG,OAAO,QAAQ,OAAO,EAAE,CAAC;AAEzC,WAAO,SAAS,MAAM,QAAQ;AAC9B,WAAO,UAAU,MAAM,OAAO,IAAI,MAAM,8CAA8C,OAAO,GAAG,EAAE,CAAC;AAEnG,aAAS,KAAK,YAAY,MAAM;AAAA,EACpC,CAAC;AACL;AAKA,eAAsB,SAClB,SACA,SACA,OACa;AACb,mBAAiB,SAAS,SAAS,KAAK;AAExC,QAAM,OAAO,QAAQ,UAAU;AAC/B,QAAM,aAAa,IAAI;AAGvB,SAAO,cAAc,IAAI,YAAY,mBAAmB;AAAA,IACpD,QAAQ;AAAA,MACJ,WAAW,QAAQ;AAAA,MACnB,MAAM,QAAQ;AAAA,MACd,WAAW,QAAQ;AAAA,MACnB,mBAAmB,QAAQ;AAAA,IAC/B;AAAA,EACJ,CAAC,CAAC;AACN;AAKA,eAAsB,mBAClB,SACA,SACA,OACa;AACb,SAAO,SAAS,EAAE,GAAG,SAAS,YAAY,YAAY,GAAG,SAAS,KAAK;AAC3E;AAKA,eAAsB,eAClB,SACA,SACA,OACa;AACb,QAAM,cAAc,iBAAiB,SAAS,SAAS,KAAK;AAE5D,MAAI,uBAAuB,aAAa;AACpC,gBAAY,QAAQ,aAAa,QAAQ;AAEzC,gBAAY,QAAQ,aAAa;AAAA,EACrC;AAEA,QAAM,OAAO,QAAQ,UAAU;AAC/B,QAAM,aAAa,IAAI;AAEvB,SAAO,cAAc,IAAI,YAAY,mBAAmB;AAAA,IACpD,QAAQ;AAAA,MACJ,WAAW,QAAQ;AAAA,MACnB,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd,WAAW,QAAQ;AAAA,MACnB,mBAAmB,QAAQ;AAAA,IAC/B;AAAA,EACJ,CAAC,CAAC;AACN;;;ANlGO,SAAS,kBAAkB,QAAwC;AACxE,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,eAAe,OAAO,iBAAiB,SAAS,UAAU,WAAW;AAC3E,QAAM,SAAS,eAAe;AAC9B,MAAI;AAEJ,MAAI,SAAS,SAAS;AAEpB,WAAO,qBAAqB,YAAY,OAAO,SAAS,IAAI;AAAA,EAC9D,OAAO;AACL,YAAQ,cAAc;AAAA,MACtB,KAAK,OAAO;AACV,cAAM,MAAM,kBAAkB;AAAA,UAC5B,OAAO,OAAO,SAAS;AAAA,UACvB,YAAY,OAAO,mBAAmB;AAAA,QACxC,CAAC;AACD,eAAO;AACP;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,YAAI,CAAC,OAAO,SAAU,OAAM,IAAI,MAAM,0DAA0D;AAChG,eAAO,qBAAqB,OAAO,QAAQ;AAC3C;AAAA,MACF;AAAA,MACA,KAAK;AAEH,eAAO,kBAAkB;AAAA,UACvB,OAAO,OAAO,SAAS;AAAA,UACvB,YAAY,OAAO,mBAAmB;AAAA,QACxC,CAAC;AACD;AAAA,MACF,KAAK;AAEH,YAAI,CAAC,OAAO,SAAU,OAAM,IAAI,MAAM,qFAAqF;AAC3H,eAAO,qBAAqB,OAAO,QAAQ;AAC3C;AAAA,MACF;AACE,cAAM,IAAI,MAAM,qCAAqC,OAAO,YAAY,CAAC,EAAE;AAAA,IAC7E;AAAA,EACF;AAEA,QAAM,SAAS,aAAa,EAAE,SAAS,OAAO,SAAS,UAAU,MAAM,KAAK,SAAS,EAAE,CAAC;AACxF,QAAM,MAAM,kBAAkB,MAAM;AACpC,QAAM,4BACJ,OAAO,UAAU,OAAO,UACpB;AAAA,IACE,cAAc,OAAO;AAAA,IACrB,gBAAgB,OAAO;AAAA,EACzB,IACA;AACN,QAAM,2BAA2B,OAAO,qBAAqB;AAC7D,QAAM,oBAAoB,2BACtB,KAAK,UAAU,wBAAwB,IACvC;AAEJ,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,OAAO,OAAO,EAAE,GAAG,QAAQ,KAAK,CAAC;AAAA,IACzC,OAAO,CAAC,YACN;AAAA,MACE;AAAA,QACE,GAAG;AAAA,QACH;AAAA,QACA,WAAW,OAAO;AAAA,QAClB;AAAA,MACF;AAAA,MACA,OAAO;AAAA,MACP,OAAO,SAAS;AAAA,IAClB;AAAA,IACF,oBAAoB,CAAC,YACnB;AAAA,MACE;AAAA,QACE,GAAG;AAAA,QACH;AAAA,QACA,WAAW,OAAO;AAAA,QAClB;AAAA,MACF;AAAA,MACA,OAAO;AAAA,MACP,OAAO,SAAS;AAAA,IAClB;AAAA,IACF,gBAAgB,CAAC,YACf;AAAA,MACE;AAAA,QACE,GAAG;AAAA,QACH;AAAA,QACA,WAAW,OAAO;AAAA,QAClB;AAAA,MACF;AAAA,MACA,OAAO;AAAA,MACP,OAAO,SAAS;AAAA,IAClB;AAAA,EACJ;AACF;AAEO,IAAM,WAAW;AAAA,EACtB,KAAK,QAAwC;AAC3C,WAAO,kBAAkB,MAAM;AAAA,EACjC;AACF;AAQA,IAAI,OAAO,WAAW,aAAa;AACjC,SAAO,WAAW;AACpB;","names":["axios"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -4,11 +4,25 @@ import { AxiosInstance } from 'axios';
|
|
|
4
4
|
* @horae/passport-core — shared types
|
|
5
5
|
*/
|
|
6
6
|
type AuthStrategy = "jwt" | "shopify" | "privy" | "custom";
|
|
7
|
+
type SDKMode = "heritage" | "scale";
|
|
8
|
+
interface ScaleRegistrationPayload {
|
|
9
|
+
serialNumber?: string;
|
|
10
|
+
email?: string;
|
|
11
|
+
manufacturerId?: string;
|
|
12
|
+
reference?: string;
|
|
13
|
+
claimCode?: string;
|
|
14
|
+
}
|
|
7
15
|
interface PassportSDKConfig {
|
|
8
16
|
/** Horae API base URL (e.g. https://v2.api.dev.horae.io/v1) */
|
|
9
17
|
apiBase: string;
|
|
18
|
+
/** Optional brand identifier (compatibility for host integrators) */
|
|
19
|
+
brandId?: string;
|
|
20
|
+
/** Optional serial prefill (compatibility for host integrators) */
|
|
21
|
+
serial?: string;
|
|
22
|
+
/** SDK mode: heritage (wallet/privy) or scale (email registration + signed viewer URL) */
|
|
23
|
+
mode?: SDKMode;
|
|
10
24
|
/** Auth strategy */
|
|
11
|
-
authStrategy
|
|
25
|
+
authStrategy?: AuthStrategy;
|
|
12
26
|
/** For custom strategy: async token getter */
|
|
13
27
|
getToken?: () => Promise<string | null>;
|
|
14
28
|
/** For JWT strategy: initial token (optional; can set later via setToken) */
|
|
@@ -17,6 +31,10 @@ interface PassportSDKConfig {
|
|
|
17
31
|
tokenStorageKey?: string | null;
|
|
18
32
|
/** UI Host base URL where the bundle is served (default: https://app.horae.io) */
|
|
19
33
|
uiHost?: string;
|
|
34
|
+
/** Scale mode: optional pre-signed public viewer URL generated server-side by brand */
|
|
35
|
+
viewerUrl?: string;
|
|
36
|
+
/** Scale mode: optional prefill values for registration flow */
|
|
37
|
+
scaleRegistration?: ScaleRegistrationPayload;
|
|
20
38
|
}
|
|
21
39
|
interface PassportListItem {
|
|
22
40
|
id: string;
|
|
@@ -137,6 +155,15 @@ declare function createPassportApi(api: AxiosInstance): {
|
|
|
137
155
|
serialNumber: string;
|
|
138
156
|
email?: string;
|
|
139
157
|
}): Promise<void>;
|
|
158
|
+
/** Scale owner registration (serial/email based, no wallet) */
|
|
159
|
+
registerScaleOwner(payload: ScaleRegistrationPayload): Promise<{
|
|
160
|
+
success: boolean;
|
|
161
|
+
tokenId: string;
|
|
162
|
+
ownerUrl?: string;
|
|
163
|
+
viewerUrl?: string;
|
|
164
|
+
}>;
|
|
165
|
+
/** Scale signed viewer (HMAC signature) */
|
|
166
|
+
getScaleViewer(tokenId: string, sig: string): Promise<PassportDetail>;
|
|
140
167
|
/** Current user profile */
|
|
141
168
|
getMe(): Promise<User>;
|
|
142
169
|
/** Documents for a passport (owner gets file URLs) */
|
|
@@ -168,6 +195,12 @@ interface RenderOptions {
|
|
|
168
195
|
uiHost?: string;
|
|
169
196
|
/** Initial tab/view (e.g. "passports", "claim", "settings") */
|
|
170
197
|
initialTab?: string;
|
|
198
|
+
/** SDK mode */
|
|
199
|
+
mode?: "heritage" | "scale";
|
|
200
|
+
/** Scale mode signed viewer URL */
|
|
201
|
+
viewerUrl?: string;
|
|
202
|
+
/** Scale mode registration prefill as JSON string */
|
|
203
|
+
scaleRegistration?: string;
|
|
171
204
|
}
|
|
172
205
|
interface RenderPassportOptions extends RenderOptions {
|
|
173
206
|
/** The ID of the passport to show */
|
|
@@ -215,5 +248,13 @@ interface PassportSDK {
|
|
|
215
248
|
* - authStrategy "shopify": use @horae/passport-shopify to get JWT from bridge, then use jwt or custom.
|
|
216
249
|
*/
|
|
217
250
|
declare function createPassportSDK(config: PassportSDKConfig): PassportSDK;
|
|
251
|
+
declare const HoraeSDK: {
|
|
252
|
+
init(config: PassportSDKConfig): PassportSDK;
|
|
253
|
+
};
|
|
254
|
+
declare global {
|
|
255
|
+
interface Window {
|
|
256
|
+
HoraeSDK?: typeof HoraeSDK;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
218
259
|
|
|
219
|
-
export { type AuthStrategy, type AuthStrategyBase, type CreateClientOptions, type EventBus, type EventMap, type PassportDetail, type PassportListItem, type PassportSDK, type PassportSDKConfig, type RenderOptions, type RenderPassportOptions, type SDKEvent, type User, createClient, createClientWithAuth, createCustomStrategy, createEventBus, createJwtStrategy, createPassportApi, createPassportSDK, mountApp, renderPassport, renderPassportList };
|
|
260
|
+
export { type AuthStrategy, type AuthStrategyBase, type CreateClientOptions, type EventBus, type EventMap, HoraeSDK, type PassportDetail, type PassportListItem, type PassportSDK, type PassportSDKConfig, type RenderOptions, type RenderPassportOptions, type SDKEvent, type SDKMode, type ScaleRegistrationPayload, type User, createClient, createClientWithAuth, createCustomStrategy, createEventBus, createJwtStrategy, createPassportApi, createPassportSDK, mountApp, renderPassport, renderPassportList };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,11 +4,25 @@ import { AxiosInstance } from 'axios';
|
|
|
4
4
|
* @horae/passport-core — shared types
|
|
5
5
|
*/
|
|
6
6
|
type AuthStrategy = "jwt" | "shopify" | "privy" | "custom";
|
|
7
|
+
type SDKMode = "heritage" | "scale";
|
|
8
|
+
interface ScaleRegistrationPayload {
|
|
9
|
+
serialNumber?: string;
|
|
10
|
+
email?: string;
|
|
11
|
+
manufacturerId?: string;
|
|
12
|
+
reference?: string;
|
|
13
|
+
claimCode?: string;
|
|
14
|
+
}
|
|
7
15
|
interface PassportSDKConfig {
|
|
8
16
|
/** Horae API base URL (e.g. https://v2.api.dev.horae.io/v1) */
|
|
9
17
|
apiBase: string;
|
|
18
|
+
/** Optional brand identifier (compatibility for host integrators) */
|
|
19
|
+
brandId?: string;
|
|
20
|
+
/** Optional serial prefill (compatibility for host integrators) */
|
|
21
|
+
serial?: string;
|
|
22
|
+
/** SDK mode: heritage (wallet/privy) or scale (email registration + signed viewer URL) */
|
|
23
|
+
mode?: SDKMode;
|
|
10
24
|
/** Auth strategy */
|
|
11
|
-
authStrategy
|
|
25
|
+
authStrategy?: AuthStrategy;
|
|
12
26
|
/** For custom strategy: async token getter */
|
|
13
27
|
getToken?: () => Promise<string | null>;
|
|
14
28
|
/** For JWT strategy: initial token (optional; can set later via setToken) */
|
|
@@ -17,6 +31,10 @@ interface PassportSDKConfig {
|
|
|
17
31
|
tokenStorageKey?: string | null;
|
|
18
32
|
/** UI Host base URL where the bundle is served (default: https://app.horae.io) */
|
|
19
33
|
uiHost?: string;
|
|
34
|
+
/** Scale mode: optional pre-signed public viewer URL generated server-side by brand */
|
|
35
|
+
viewerUrl?: string;
|
|
36
|
+
/** Scale mode: optional prefill values for registration flow */
|
|
37
|
+
scaleRegistration?: ScaleRegistrationPayload;
|
|
20
38
|
}
|
|
21
39
|
interface PassportListItem {
|
|
22
40
|
id: string;
|
|
@@ -137,6 +155,15 @@ declare function createPassportApi(api: AxiosInstance): {
|
|
|
137
155
|
serialNumber: string;
|
|
138
156
|
email?: string;
|
|
139
157
|
}): Promise<void>;
|
|
158
|
+
/** Scale owner registration (serial/email based, no wallet) */
|
|
159
|
+
registerScaleOwner(payload: ScaleRegistrationPayload): Promise<{
|
|
160
|
+
success: boolean;
|
|
161
|
+
tokenId: string;
|
|
162
|
+
ownerUrl?: string;
|
|
163
|
+
viewerUrl?: string;
|
|
164
|
+
}>;
|
|
165
|
+
/** Scale signed viewer (HMAC signature) */
|
|
166
|
+
getScaleViewer(tokenId: string, sig: string): Promise<PassportDetail>;
|
|
140
167
|
/** Current user profile */
|
|
141
168
|
getMe(): Promise<User>;
|
|
142
169
|
/** Documents for a passport (owner gets file URLs) */
|
|
@@ -168,6 +195,12 @@ interface RenderOptions {
|
|
|
168
195
|
uiHost?: string;
|
|
169
196
|
/** Initial tab/view (e.g. "passports", "claim", "settings") */
|
|
170
197
|
initialTab?: string;
|
|
198
|
+
/** SDK mode */
|
|
199
|
+
mode?: "heritage" | "scale";
|
|
200
|
+
/** Scale mode signed viewer URL */
|
|
201
|
+
viewerUrl?: string;
|
|
202
|
+
/** Scale mode registration prefill as JSON string */
|
|
203
|
+
scaleRegistration?: string;
|
|
171
204
|
}
|
|
172
205
|
interface RenderPassportOptions extends RenderOptions {
|
|
173
206
|
/** The ID of the passport to show */
|
|
@@ -215,5 +248,13 @@ interface PassportSDK {
|
|
|
215
248
|
* - authStrategy "shopify": use @horae/passport-shopify to get JWT from bridge, then use jwt or custom.
|
|
216
249
|
*/
|
|
217
250
|
declare function createPassportSDK(config: PassportSDKConfig): PassportSDK;
|
|
251
|
+
declare const HoraeSDK: {
|
|
252
|
+
init(config: PassportSDKConfig): PassportSDK;
|
|
253
|
+
};
|
|
254
|
+
declare global {
|
|
255
|
+
interface Window {
|
|
256
|
+
HoraeSDK?: typeof HoraeSDK;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
218
259
|
|
|
219
|
-
export { type AuthStrategy, type AuthStrategyBase, type CreateClientOptions, type EventBus, type EventMap, type PassportDetail, type PassportListItem, type PassportSDK, type PassportSDKConfig, type RenderOptions, type RenderPassportOptions, type SDKEvent, type User, createClient, createClientWithAuth, createCustomStrategy, createEventBus, createJwtStrategy, createPassportApi, createPassportSDK, mountApp, renderPassport, renderPassportList };
|
|
260
|
+
export { type AuthStrategy, type AuthStrategyBase, type CreateClientOptions, type EventBus, type EventMap, HoraeSDK, type PassportDetail, type PassportListItem, type PassportSDK, type PassportSDKConfig, type RenderOptions, type RenderPassportOptions, type SDKEvent, type SDKMode, type ScaleRegistrationPayload, type User, createClient, createClientWithAuth, createCustomStrategy, createEventBus, createJwtStrategy, createPassportApi, createPassportSDK, mountApp, renderPassport, renderPassportList };
|
package/dist/index.js
CHANGED
|
@@ -117,6 +117,18 @@ function createPassportApi(api) {
|
|
|
117
117
|
async claimShopifyPassport(data) {
|
|
118
118
|
await api.post("/api/passport/shopify-claim", data);
|
|
119
119
|
},
|
|
120
|
+
/** Scale owner registration (serial/email based, no wallet) */
|
|
121
|
+
async registerScaleOwner(payload) {
|
|
122
|
+
const res = await api.post("/api/passport/scale/register", payload);
|
|
123
|
+
return unwrapData(res);
|
|
124
|
+
},
|
|
125
|
+
/** Scale signed viewer (HMAC signature) */
|
|
126
|
+
async getScaleViewer(tokenId, sig) {
|
|
127
|
+
const res = await api.get(`/api/passport/scale/view/${tokenId}`, {
|
|
128
|
+
params: { sig }
|
|
129
|
+
});
|
|
130
|
+
return unwrapData(res);
|
|
131
|
+
},
|
|
120
132
|
/** Current user profile */
|
|
121
133
|
async getMe() {
|
|
122
134
|
const res = await api.get("/users/me");
|
|
@@ -155,6 +167,15 @@ function prepareContainer(options, apiBase, token) {
|
|
|
155
167
|
if (options.initialTab) {
|
|
156
168
|
containerEl.dataset.initialTab = options.initialTab;
|
|
157
169
|
}
|
|
170
|
+
if (options.mode) {
|
|
171
|
+
containerEl.dataset.horaeMode = options.mode;
|
|
172
|
+
}
|
|
173
|
+
if (options.viewerUrl) {
|
|
174
|
+
containerEl.dataset.horaeViewerUrl = options.viewerUrl;
|
|
175
|
+
}
|
|
176
|
+
if (options.scaleRegistration) {
|
|
177
|
+
containerEl.dataset.horaeScaleRegistration = options.scaleRegistration;
|
|
178
|
+
}
|
|
158
179
|
if (token) {
|
|
159
180
|
containerEl.dataset.horaeToken = token;
|
|
160
181
|
}
|
|
@@ -184,7 +205,12 @@ async function mountApp(options, apiBase, token) {
|
|
|
184
205
|
const host = options.uiHost || "https://app.horae.io";
|
|
185
206
|
await loadUIBundle(host);
|
|
186
207
|
window.dispatchEvent(new CustomEvent("horae:sdk:mount", {
|
|
187
|
-
detail: {
|
|
208
|
+
detail: {
|
|
209
|
+
container: options.container,
|
|
210
|
+
mode: options.mode,
|
|
211
|
+
viewerUrl: options.viewerUrl,
|
|
212
|
+
scaleRegistration: options.scaleRegistration
|
|
213
|
+
}
|
|
188
214
|
}));
|
|
189
215
|
}
|
|
190
216
|
async function renderPassportList(options, apiBase, token) {
|
|
@@ -199,54 +225,108 @@ async function renderPassport(options, apiBase, token) {
|
|
|
199
225
|
const host = options.uiHost || "https://app.horae.io";
|
|
200
226
|
await loadUIBundle(host);
|
|
201
227
|
window.dispatchEvent(new CustomEvent("horae:sdk:mount", {
|
|
202
|
-
detail: {
|
|
228
|
+
detail: {
|
|
229
|
+
container: options.container,
|
|
230
|
+
passportId: options.passportId,
|
|
231
|
+
mode: options.mode,
|
|
232
|
+
viewerUrl: options.viewerUrl,
|
|
233
|
+
scaleRegistration: options.scaleRegistration
|
|
234
|
+
}
|
|
203
235
|
}));
|
|
204
236
|
}
|
|
205
237
|
|
|
206
238
|
// src/index.ts
|
|
207
239
|
function createPassportSDK(config) {
|
|
240
|
+
const mode = config.mode ?? "heritage";
|
|
241
|
+
const authStrategy = config.authStrategy ?? (mode === "scale" ? "custom" : "jwt");
|
|
208
242
|
const events = createEventBus();
|
|
209
243
|
let auth;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
244
|
+
if (mode === "scale") {
|
|
245
|
+
auth = createCustomStrategy(async () => config.token ?? null);
|
|
246
|
+
} else {
|
|
247
|
+
switch (authStrategy) {
|
|
248
|
+
case "jwt": {
|
|
249
|
+
const jwt = createJwtStrategy({
|
|
250
|
+
token: config.token ?? void 0,
|
|
251
|
+
storageKey: config.tokenStorageKey ?? void 0
|
|
252
|
+
});
|
|
253
|
+
auth = jwt;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
case "custom": {
|
|
257
|
+
if (!config.getToken) throw new Error("PassportSDK: getToken required for authStrategy 'custom'");
|
|
258
|
+
auth = createCustomStrategy(config.getToken);
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
case "shopify":
|
|
262
|
+
auth = createJwtStrategy({
|
|
263
|
+
token: config.token ?? void 0,
|
|
264
|
+
storageKey: config.tokenStorageKey ?? "shopify_access_token"
|
|
265
|
+
});
|
|
266
|
+
break;
|
|
267
|
+
case "privy":
|
|
268
|
+
if (!config.getToken) throw new Error("PassportSDK: getToken required for authStrategy 'privy' (pass Privy getAccessToken)");
|
|
269
|
+
auth = createCustomStrategy(config.getToken);
|
|
270
|
+
break;
|
|
271
|
+
default:
|
|
272
|
+
throw new Error(`PassportSDK: unknown authStrategy ${String(authStrategy)}`);
|
|
223
273
|
}
|
|
224
|
-
case "shopify":
|
|
225
|
-
auth = createJwtStrategy({
|
|
226
|
-
token: config.token ?? void 0,
|
|
227
|
-
storageKey: config.tokenStorageKey ?? "shopify_access_token"
|
|
228
|
-
});
|
|
229
|
-
break;
|
|
230
|
-
case "privy":
|
|
231
|
-
if (!config.getToken) throw new Error("PassportSDK: getToken required for authStrategy 'privy' (pass Privy getAccessToken)");
|
|
232
|
-
auth = createCustomStrategy(config.getToken);
|
|
233
|
-
break;
|
|
234
|
-
default:
|
|
235
|
-
throw new Error(`PassportSDK: unknown authStrategy ${String(config.authStrategy)}`);
|
|
236
274
|
}
|
|
237
275
|
const client = createClient({ apiBase: config.apiBase, getToken: () => auth.getToken() });
|
|
238
276
|
const api = createPassportApi(client);
|
|
277
|
+
const fallbackScaleRegistration = config.serial || config.brandId ? {
|
|
278
|
+
serialNumber: config.serial,
|
|
279
|
+
manufacturerId: config.brandId
|
|
280
|
+
} : void 0;
|
|
281
|
+
const scaleRegistrationPayload = config.scaleRegistration ?? fallbackScaleRegistration;
|
|
282
|
+
const scaleRegistration = scaleRegistrationPayload ? JSON.stringify(scaleRegistrationPayload) : void 0;
|
|
239
283
|
return {
|
|
240
284
|
api,
|
|
241
285
|
events,
|
|
242
286
|
auth,
|
|
243
|
-
config: Object.freeze({ ...config }),
|
|
244
|
-
mount: (options) => mountApp(
|
|
245
|
-
|
|
246
|
-
|
|
287
|
+
config: Object.freeze({ ...config, mode }),
|
|
288
|
+
mount: (options) => mountApp(
|
|
289
|
+
{
|
|
290
|
+
...options,
|
|
291
|
+
mode,
|
|
292
|
+
viewerUrl: config.viewerUrl,
|
|
293
|
+
scaleRegistration
|
|
294
|
+
},
|
|
295
|
+
config.apiBase,
|
|
296
|
+
config.token || null
|
|
297
|
+
),
|
|
298
|
+
renderPassportList: (options) => renderPassportList(
|
|
299
|
+
{
|
|
300
|
+
...options,
|
|
301
|
+
mode,
|
|
302
|
+
viewerUrl: config.viewerUrl,
|
|
303
|
+
scaleRegistration
|
|
304
|
+
},
|
|
305
|
+
config.apiBase,
|
|
306
|
+
config.token || null
|
|
307
|
+
),
|
|
308
|
+
renderPassport: (options) => renderPassport(
|
|
309
|
+
{
|
|
310
|
+
...options,
|
|
311
|
+
mode,
|
|
312
|
+
viewerUrl: config.viewerUrl,
|
|
313
|
+
scaleRegistration
|
|
314
|
+
},
|
|
315
|
+
config.apiBase,
|
|
316
|
+
config.token || null
|
|
317
|
+
)
|
|
247
318
|
};
|
|
248
319
|
}
|
|
320
|
+
var HoraeSDK = {
|
|
321
|
+
init(config) {
|
|
322
|
+
return createPassportSDK(config);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
if (typeof window !== "undefined") {
|
|
326
|
+
window.HoraeSDK = HoraeSDK;
|
|
327
|
+
}
|
|
249
328
|
export {
|
|
329
|
+
HoraeSDK,
|
|
250
330
|
createClient,
|
|
251
331
|
createClientWithAuth,
|
|
252
332
|
createCustomStrategy,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/events.ts","../src/auth/strategies/jwt.ts","../src/auth/strategies/custom.ts","../src/client.ts","../src/api.ts","../src/ui.ts","../src/index.ts"],"sourcesContent":["/**\n * @horae/passport-core — event emitter for auth and passport events\n */\n\nexport type SDKEvent =\n | \"auth:ready\"\n | \"auth:error\"\n | \"passport:claimed\"\n | \"passport:loaded\"\n | \"passport:list:loaded\"\n | \"token:expired\";\n\nexport type EventMap = {\n \"auth:ready\": void;\n \"auth:error\": { message: string; code?: string };\n \"passport:claimed\": { tokenId: string };\n \"passport:loaded\": { tokenId: string };\n \"passport:list:loaded\": { count: number };\n \"token:expired\": void;\n};\n\ntype Listener<T> = (payload: T) => void;\n\nexport function createEventBus() {\n const listeners = new Map<SDKEvent, Set<Listener<unknown>>>();\n\n function on<E extends SDKEvent>(event: E, fn: Listener<EventMap[E]>) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(fn as Listener<unknown>);\n return () => listeners.get(event)?.delete(fn as Listener<unknown>);\n }\n\n function emit<E extends SDKEvent>(event: E, payload?: EventMap[E]) {\n listeners.get(event)?.forEach((fn) => (fn as Listener<EventMap[E]>)(payload as EventMap[E]));\n }\n\n return { on, emit };\n}\n\nexport type EventBus = ReturnType<typeof createEventBus>;\n","/**\n * JWT strategy — token from config or setToken; optional localStorage persistence\n */\n\nimport type { AuthStrategyBase } from \"../types.js\";\n\nexport interface JwtStrategyOptions {\n /** Initial token */\n token?: string | null;\n /** localStorage key for persistence (omit for in-memory only) */\n storageKey?: string | null;\n}\n\nexport function createJwtStrategy(options: JwtStrategyOptions = {}): AuthStrategyBase {\n let token: string | null = options.token ?? null;\n const storageKey = options.storageKey ?? null;\n\n const storage = typeof window !== \"undefined\" ? window.localStorage : undefined;\n if (storage && storageKey) {\n try {\n const stored = storage.getItem(storageKey);\n if (stored) token = stored;\n } catch {\n // ignore\n }\n }\n\n return {\n async getToken() {\n return token;\n },\n setToken(next: string | null) {\n token = next;\n if (storage && storageKey) {\n try {\n if (next) storage.setItem(storageKey, next);\n else storage.removeItem(storageKey);\n } catch {\n // ignore\n }\n }\n },\n clearToken() {\n token = null;\n if (storage && storageKey) {\n try {\n storage.removeItem(storageKey);\n } catch {\n // ignore\n }\n }\n },\n };\n}\n","/**\n * Custom strategy — caller supplies getToken (e.g. from backend or Privy)\n */\n\nimport type { AuthStrategyBase } from \"../types.js\";\n\nexport function createCustomStrategy(\n getToken: () => Promise<string | null>,\n): AuthStrategyBase {\n return { getToken };\n}\n","/**\n * Horae API client — axios instance with Bearer token from auth strategy\n */\n\nimport axios, { type AxiosInstance } from \"axios\";\nimport type { AuthStrategyBase } from \"./auth/index.js\";\n\nexport interface CreateClientOptions {\n apiBase: string;\n getToken: () => Promise<string | null>;\n}\n\nexport function createClient(options: CreateClientOptions): AxiosInstance {\n const { apiBase, getToken } = options;\n const client = axios.create({\n baseURL: apiBase.replace(/\\/v1\\/?$/, \"\") + \"/v1\",\n });\n\n client.interceptors.request.use(async (config) => {\n const token = await getToken();\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n config.headers[\"ngrok-skip-browser-warning\"] = \"true\";\n return config;\n });\n\n return client;\n}\n\nexport function createClientWithAuth(auth: AuthStrategyBase, apiBase: string): AxiosInstance {\n return createClient({\n apiBase,\n getToken: () => auth.getToken(),\n });\n}\n","/**\n * Horae Passport API — list, single, claim, user, documents\n * Mirrors passport-web shared/api/api.service.ts (token-based auth)\n */\n\nimport type { AxiosInstance } from \"axios\";\nimport type { PassportListItem, PassportDetail, User } from \"./types.js\";\n\nfunction unwrapItems<T>(response: { data?: unknown }): T[] {\n const data = response.data as { data?: { items?: T[] }; items?: T[] } | T[] | undefined;\n if (Array.isArray(data)) return data;\n const inner = data && typeof data === \"object\" && \"data\" in data ? (data as { data?: { items?: T[] } }).data : data;\n const items = (inner && typeof inner === \"object\" && \"items\" in inner\n ? (inner as { items?: T[] }).items\n : Array.isArray(inner)\n ? inner\n : []) as T[];\n return items ?? [];\n}\n\nfunction unwrapData<T>(response: { data?: unknown }): T {\n const data = response.data as { data?: T } | T;\n return (data && typeof data === \"object\" && \"data\" in data ? (data as { data: T }).data : data) as T;\n}\n\nexport function createPassportApi(api: AxiosInstance) {\n return {\n /** List passports claimed by current user */\n async getMyClaimedPassports(): Promise<PassportListItem[]> {\n const res = await api.get(\"/api/passport/claimed\");\n return unwrapItems<PassportListItem>(res) as PassportListItem[];\n },\n\n /** List passports by owner wallet (e.g. Shopify) */\n async getPassportsByOwner(ownerWallet: string): Promise<PassportListItem[]> {\n const res = await api.get(\"/api/passport/claimed\", { params: { owner: ownerWallet } });\n return unwrapItems<PassportListItem>(res) as PassportListItem[];\n },\n\n /** Single passport (authenticated) */\n async getPassport(tokenId: string, isAuthenticated = true): Promise<PassportDetail> {\n const path = isAuthenticated ? `/api/passport/${tokenId}` : `/api/passport/public/${tokenId}`;\n const res = await api.get(path);\n return unwrapData<PassportDetail>(res);\n },\n\n /** Claim passport */\n async claimPassport(data: { tokenId: string; toAddress: string; claimKey: string }) {\n await api.post(\"/api/passport/claim\", data);\n },\n\n /** Shopify claim (serialNumber + optional email) */\n async claimShopifyPassport(data: { serialNumber: string; email?: string }) {\n await api.post(\"/api/passport/shopify-claim\", data);\n },\n\n /** Current user profile */\n async getMe(): Promise<User> {\n const res = await api.get(\"/users/me\");\n const raw = unwrapData<unknown>(res);\n const doc = raw && typeof raw === \"object\" && \"_doc\" in raw ? (raw as { _doc: User })._doc : raw;\n return doc as User;\n },\n\n /** Documents for a passport (owner gets file URLs) */\n async getDocuments(tokenId: string): Promise<{ url?: string; name?: string; [k: string]: unknown }[]> {\n const res = await api.get(`/api/passport/${tokenId}/documents`);\n const responseData = (res.data as { data?: unknown })?.data ?? res.data;\n if (responseData && typeof responseData === \"object\" && \"data\" in responseData && Array.isArray((responseData as { data: unknown[] }).data))\n return (responseData as { data: unknown[] }).data as { url?: string; name?: string; [k: string]: unknown }[];\n if (Array.isArray(responseData)) return responseData as { url?: string; name?: string; [k: string]: unknown }[];\n return [];\n },\n\n /** Transfer passport to user by email */\n async transferPassportToUser(data: { tokenId: string; recipientEmail: string }) {\n await api.post(\"/api/passport/transfer-to-user\", data);\n },\n\n /** Set stolen status */\n async setStolenStatus(data: { tokenId: string; isStolen: boolean }) {\n await api.post(\"/api/passport/set-stolen\", data);\n },\n };\n}\n","/**\n * UI Renderer for @horae/passport-core\n * Dynamically injects the pre-built React SDK bundle to render the UI on the host page.\n */\n\nexport interface RenderOptions {\n /** CSS selector of the container element (e.g. \"#passport-app\") */\n container: string;\n /** UI Host base URL where the bundle is served (default: https://app.horae.io) */\n uiHost?: string;\n /** Initial tab/view (e.g. \"passports\", \"claim\", \"settings\") */\n initialTab?: string;\n}\n\nexport interface RenderPassportOptions extends RenderOptions {\n /** The ID of the passport to show */\n passportId: string;\n}\n\n/**\n * Configure the container with data attributes so the UI bundle can read them upon mounting.\n */\nfunction prepareContainer(options: RenderOptions, apiBase: string, token: string | null) {\n const containerEl = document.querySelector(options.container);\n if (!containerEl) {\n throw new Error(`PassportSDK: container element '${options.container}' not found.`);\n }\n\n // Set necessary data attributes for the UI bundle (similar to Shopify embed contract)\n if (containerEl instanceof HTMLElement) {\n containerEl.dataset.horaeApiBase = apiBase;\n if (options.initialTab) {\n containerEl.dataset.initialTab = options.initialTab;\n }\n\n // Inject the token (the UI bundle will look for this or use its own mechanism)\n if (token) {\n containerEl.dataset.horaeToken = token;\n }\n\n // Add a signature class/id to ensure the embed root is identifiable\n containerEl.classList.add(\"horae-sdk-root\");\n\n // Allow the bundle to easily find its mount point if it uses querySelector internally\n // (We also pass the container selector directly to the mount event later if needed)\n containerEl.dataset.containerSelector = options.container;\n }\n\n return containerEl;\n}\n\n/**\n * Inject the script tag for the UI bundle if it hasn't been injected yet.\n */\nfunction loadUIBundle(uiHost: string): Promise<void> {\n const SCRIPT_ID = \"horae-passport-sdk-ui\";\n\n return new Promise((resolve, reject) => {\n if (document.getElementById(SCRIPT_ID)) {\n // Script already added\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.id = SCRIPT_ID;\n script.type = \"module\";\n // Target the newly created sdk-embed entrypoint\n script.src = `${uiHost.replace(/\\/$/, '')}/sdk-embed.js`;\n\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`PassportSDK: Failed to load UI bundle from ${script.src}`));\n\n document.head.appendChild(script);\n });\n}\n\n/**\n * Render the generic SDK App\n */\nexport async function mountApp(\n options: RenderOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n prepareContainer(options, apiBase, token);\n\n const host = options.uiHost || \"https://app.horae.io\";\n await loadUIBundle(host);\n\n // Dispatch a custom event in case the bundle is already loaded and listening for dynamic mounts\n window.dispatchEvent(new CustomEvent(\"horae:sdk:mount\", {\n detail: { container: options.container }\n }));\n}\n\n/**\n * Render specifically the Passport List (maps to \"passports\" tab/view)\n */\nexport async function renderPassportList(\n options: RenderOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n return mountApp({ ...options, initialTab: \"passports\" }, apiBase, token);\n}\n\n/**\n * Render specifically a Single Passport (maps to a specific detail view layout)\n */\nexport async function renderPassport(\n options: RenderPassportOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n const containerEl = prepareContainer(options, apiBase, token);\n\n if (containerEl instanceof HTMLElement) {\n containerEl.dataset.passportId = options.passportId;\n // Set initialTab to \"detail\" or a specific flag the UI recognizes\n containerEl.dataset.initialTab = \"detail\";\n }\n\n const host = options.uiHost || \"https://app.horae.io\";\n await loadUIBundle(host);\n\n window.dispatchEvent(new CustomEvent(\"horae:sdk:mount\", {\n detail: { container: options.container, passportId: options.passportId }\n }));\n}\n","/**\n * @horae/passport-core\n * Reusable Passport SDK — auth strategies, Horae API client, events.\n * Token-based auth only; no cross-domain cookies.\n */\n\nexport type { PassportSDKConfig, AuthStrategy, PassportListItem, PassportDetail, User } from \"./types.js\";\nexport { createEventBus } from \"./events.js\";\nexport type { SDKEvent, EventMap, EventBus } from \"./events.js\";\nexport { createJwtStrategy, createCustomStrategy } from \"./auth/index.js\";\nexport type { AuthStrategyBase } from \"./auth/index.js\";\nexport { createClient, createClientWithAuth } from \"./client.js\";\nexport type { CreateClientOptions } from \"./client.js\";\nexport { createPassportApi } from \"./api.js\";\nexport * from \"./ui.js\";\n\nimport type { PassportSDKConfig } from \"./types.js\";\nimport { createEventBus } from \"./events.js\";\nimport { createJwtStrategy } from \"./auth/strategies/jwt.js\";\nimport { createCustomStrategy } from \"./auth/strategies/custom.js\";\nimport { createClient } from \"./client.js\";\nimport { createPassportApi } from \"./api.js\";\nimport type { AuthStrategyBase } from \"./auth/index.js\";\nimport { mountApp, renderPassportList, renderPassport } from \"./ui.js\";\nimport type { RenderOptions, RenderPassportOptions } from \"./ui.js\";\n\nexport interface PassportSDK {\n /** Horae API client (axios) */\n readonly api: ReturnType<typeof createPassportApi>;\n /** Event bus for auth:ready, auth:error, passport:claimed, etc. */\n readonly events: ReturnType<typeof createEventBus>;\n /** Auth strategy instance (for setToken/clearToken when available) */\n readonly auth: AuthStrategyBase;\n /** Config */\n readonly config: Readonly<PassportSDKConfig>;\n /** Mount the generic SDK App in headless mode */\n mount(options: RenderOptions): Promise<void>;\n /** Render the Passport List view */\n renderPassportList(options: RenderOptions): Promise<void>;\n /** Render a Single Passport Detail view */\n renderPassport(options: RenderPassportOptions): Promise<void>;\n}\n\n/**\n * Create the Passport SDK instance.\n * - authStrategy \"jwt\": pass token in config or call setToken on auth after getting JWT from your backend.\n * - authStrategy \"custom\": pass getToken in config.\n * - authStrategy \"shopify\": use @horae/passport-shopify to get JWT from bridge, then use jwt or custom.\n */\nexport function createPassportSDK(config: PassportSDKConfig): PassportSDK {\n const events = createEventBus();\n let auth: AuthStrategyBase;\n\n switch (config.authStrategy) {\n case \"jwt\": {\n const jwt = createJwtStrategy({\n token: config.token ?? undefined,\n storageKey: config.tokenStorageKey ?? undefined,\n });\n auth = jwt;\n break;\n }\n case \"custom\": {\n if (!config.getToken) throw new Error(\"PassportSDK: getToken required for authStrategy 'custom'\");\n auth = createCustomStrategy(config.getToken);\n break;\n }\n case \"shopify\":\n // Shopify: use JWT strategy; token is set by @horae/passport-shopify bridge\n auth = createJwtStrategy({\n token: config.token ?? undefined,\n storageKey: config.tokenStorageKey ?? \"shopify_access_token\",\n });\n break;\n case \"privy\":\n // Privy: use custom strategy with getToken from host (e.g. getAccessToken from @privy-io/react-auth)\n if (!config.getToken) throw new Error(\"PassportSDK: getToken required for authStrategy 'privy' (pass Privy getAccessToken)\");\n auth = createCustomStrategy(config.getToken);\n break;\n default:\n throw new Error(`PassportSDK: unknown authStrategy ${String((config as { authStrategy?: string }).authStrategy)}`);\n }\n\n const client = createClient({ apiBase: config.apiBase, getToken: () => auth.getToken() });\n const api = createPassportApi(client);\n\n return {\n api,\n events,\n auth,\n config: Object.freeze({ ...config }),\n mount: (options) => mountApp(options, config.apiBase, config.token || null),\n renderPassportList: (options) => renderPassportList(options, config.apiBase, config.token || null),\n renderPassport: (options) => renderPassport(options, config.apiBase, config.token || null),\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/events.ts","../src/auth/strategies/jwt.ts","../src/auth/strategies/custom.ts","../src/client.ts","../src/api.ts","../src/ui.ts","../src/index.ts"],"sourcesContent":["/**\n * @horae/passport-core — event emitter for auth and passport events\n */\n\nexport type SDKEvent =\n | \"auth:ready\"\n | \"auth:error\"\n | \"passport:claimed\"\n | \"passport:loaded\"\n | \"passport:list:loaded\"\n | \"token:expired\";\n\nexport type EventMap = {\n \"auth:ready\": void;\n \"auth:error\": { message: string; code?: string };\n \"passport:claimed\": { tokenId: string };\n \"passport:loaded\": { tokenId: string };\n \"passport:list:loaded\": { count: number };\n \"token:expired\": void;\n};\n\ntype Listener<T> = (payload: T) => void;\n\nexport function createEventBus() {\n const listeners = new Map<SDKEvent, Set<Listener<unknown>>>();\n\n function on<E extends SDKEvent>(event: E, fn: Listener<EventMap[E]>) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(fn as Listener<unknown>);\n return () => listeners.get(event)?.delete(fn as Listener<unknown>);\n }\n\n function emit<E extends SDKEvent>(event: E, payload?: EventMap[E]) {\n listeners.get(event)?.forEach((fn) => (fn as Listener<EventMap[E]>)(payload as EventMap[E]));\n }\n\n return { on, emit };\n}\n\nexport type EventBus = ReturnType<typeof createEventBus>;\n","/**\n * JWT strategy — token from config or setToken; optional localStorage persistence\n */\n\nimport type { AuthStrategyBase } from \"../types.js\";\n\nexport interface JwtStrategyOptions {\n /** Initial token */\n token?: string | null;\n /** localStorage key for persistence (omit for in-memory only) */\n storageKey?: string | null;\n}\n\nexport function createJwtStrategy(options: JwtStrategyOptions = {}): AuthStrategyBase {\n let token: string | null = options.token ?? null;\n const storageKey = options.storageKey ?? null;\n\n const storage = typeof window !== \"undefined\" ? window.localStorage : undefined;\n if (storage && storageKey) {\n try {\n const stored = storage.getItem(storageKey);\n if (stored) token = stored;\n } catch {\n // ignore\n }\n }\n\n return {\n async getToken() {\n return token;\n },\n setToken(next: string | null) {\n token = next;\n if (storage && storageKey) {\n try {\n if (next) storage.setItem(storageKey, next);\n else storage.removeItem(storageKey);\n } catch {\n // ignore\n }\n }\n },\n clearToken() {\n token = null;\n if (storage && storageKey) {\n try {\n storage.removeItem(storageKey);\n } catch {\n // ignore\n }\n }\n },\n };\n}\n","/**\n * Custom strategy — caller supplies getToken (e.g. from backend or Privy)\n */\n\nimport type { AuthStrategyBase } from \"../types.js\";\n\nexport function createCustomStrategy(\n getToken: () => Promise<string | null>,\n): AuthStrategyBase {\n return { getToken };\n}\n","/**\n * Horae API client — axios instance with Bearer token from auth strategy\n */\n\nimport axios, { type AxiosInstance } from \"axios\";\nimport type { AuthStrategyBase } from \"./auth/index.js\";\n\nexport interface CreateClientOptions {\n apiBase: string;\n getToken: () => Promise<string | null>;\n}\n\nexport function createClient(options: CreateClientOptions): AxiosInstance {\n const { apiBase, getToken } = options;\n const client = axios.create({\n baseURL: apiBase.replace(/\\/v1\\/?$/, \"\") + \"/v1\",\n });\n\n client.interceptors.request.use(async (config) => {\n const token = await getToken();\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n config.headers[\"ngrok-skip-browser-warning\"] = \"true\";\n return config;\n });\n\n return client;\n}\n\nexport function createClientWithAuth(auth: AuthStrategyBase, apiBase: string): AxiosInstance {\n return createClient({\n apiBase,\n getToken: () => auth.getToken(),\n });\n}\n","/**\n * Horae Passport API — list, single, claim, user, documents\n * Mirrors passport-web shared/api/api.service.ts (token-based auth)\n */\n\nimport type { AxiosInstance } from \"axios\";\nimport type {\n PassportListItem,\n PassportDetail,\n ScaleRegistrationPayload,\n User,\n} from \"./types.js\";\n\nfunction unwrapItems<T>(response: { data?: unknown }): T[] {\n const data = response.data as { data?: { items?: T[] }; items?: T[] } | T[] | undefined;\n if (Array.isArray(data)) return data;\n const inner = data && typeof data === \"object\" && \"data\" in data ? (data as { data?: { items?: T[] } }).data : data;\n const items = (inner && typeof inner === \"object\" && \"items\" in inner\n ? (inner as { items?: T[] }).items\n : Array.isArray(inner)\n ? inner\n : []) as T[];\n return items ?? [];\n}\n\nfunction unwrapData<T>(response: { data?: unknown }): T {\n const data = response.data as { data?: T } | T;\n return (data && typeof data === \"object\" && \"data\" in data ? (data as { data: T }).data : data) as T;\n}\n\nexport function createPassportApi(api: AxiosInstance) {\n return {\n /** List passports claimed by current user */\n async getMyClaimedPassports(): Promise<PassportListItem[]> {\n const res = await api.get(\"/api/passport/claimed\");\n return unwrapItems<PassportListItem>(res) as PassportListItem[];\n },\n\n /** List passports by owner wallet (e.g. Shopify) */\n async getPassportsByOwner(ownerWallet: string): Promise<PassportListItem[]> {\n const res = await api.get(\"/api/passport/claimed\", { params: { owner: ownerWallet } });\n return unwrapItems<PassportListItem>(res) as PassportListItem[];\n },\n\n /** Single passport (authenticated) */\n async getPassport(tokenId: string, isAuthenticated = true): Promise<PassportDetail> {\n const path = isAuthenticated ? `/api/passport/${tokenId}` : `/api/passport/public/${tokenId}`;\n const res = await api.get(path);\n return unwrapData<PassportDetail>(res);\n },\n\n /** Claim passport */\n async claimPassport(data: { tokenId: string; toAddress: string; claimKey: string }) {\n await api.post(\"/api/passport/claim\", data);\n },\n\n /** Shopify claim (serialNumber + optional email) */\n async claimShopifyPassport(data: { serialNumber: string; email?: string }) {\n await api.post(\"/api/passport/shopify-claim\", data);\n },\n\n /** Scale owner registration (serial/email based, no wallet) */\n async registerScaleOwner(payload: ScaleRegistrationPayload): Promise<{\n success: boolean;\n tokenId: string;\n ownerUrl?: string;\n viewerUrl?: string;\n }> {\n const res = await api.post(\"/api/passport/scale/register\", payload);\n return unwrapData<{\n success: boolean;\n tokenId: string;\n ownerUrl?: string;\n viewerUrl?: string;\n }>(res);\n },\n\n /** Scale signed viewer (HMAC signature) */\n async getScaleViewer(tokenId: string, sig: string): Promise<PassportDetail> {\n const res = await api.get(`/api/passport/scale/view/${tokenId}`, {\n params: { sig },\n });\n return unwrapData<PassportDetail>(res);\n },\n\n /** Current user profile */\n async getMe(): Promise<User> {\n const res = await api.get(\"/users/me\");\n const raw = unwrapData<unknown>(res);\n const doc = raw && typeof raw === \"object\" && \"_doc\" in raw ? (raw as { _doc: User })._doc : raw;\n return doc as User;\n },\n\n /** Documents for a passport (owner gets file URLs) */\n async getDocuments(tokenId: string): Promise<{ url?: string; name?: string; [k: string]: unknown }[]> {\n const res = await api.get(`/api/passport/${tokenId}/documents`);\n const responseData = (res.data as { data?: unknown })?.data ?? res.data;\n if (responseData && typeof responseData === \"object\" && \"data\" in responseData && Array.isArray((responseData as { data: unknown[] }).data))\n return (responseData as { data: unknown[] }).data as { url?: string; name?: string; [k: string]: unknown }[];\n if (Array.isArray(responseData)) return responseData as { url?: string; name?: string; [k: string]: unknown }[];\n return [];\n },\n\n /** Transfer passport to user by email */\n async transferPassportToUser(data: { tokenId: string; recipientEmail: string }) {\n await api.post(\"/api/passport/transfer-to-user\", data);\n },\n\n /** Set stolen status */\n async setStolenStatus(data: { tokenId: string; isStolen: boolean }) {\n await api.post(\"/api/passport/set-stolen\", data);\n },\n };\n}\n","/**\n * UI Renderer for @horae/passport-core\n * Dynamically injects the pre-built React SDK bundle to render the UI on the host page.\n */\n\nexport interface RenderOptions {\n /** CSS selector of the container element (e.g. \"#passport-app\") */\n container: string;\n /** UI Host base URL where the bundle is served (default: https://app.horae.io) */\n uiHost?: string;\n /** Initial tab/view (e.g. \"passports\", \"claim\", \"settings\") */\n initialTab?: string;\n /** SDK mode */\n mode?: \"heritage\" | \"scale\";\n /** Scale mode signed viewer URL */\n viewerUrl?: string;\n /** Scale mode registration prefill as JSON string */\n scaleRegistration?: string;\n}\n\nexport interface RenderPassportOptions extends RenderOptions {\n /** The ID of the passport to show */\n passportId: string;\n}\n\n/**\n * Configure the container with data attributes so the UI bundle can read them upon mounting.\n */\nfunction prepareContainer(options: RenderOptions, apiBase: string, token: string | null) {\n const containerEl = document.querySelector(options.container);\n if (!containerEl) {\n throw new Error(`PassportSDK: container element '${options.container}' not found.`);\n }\n\n // Set necessary data attributes for the UI bundle (similar to Shopify embed contract)\n if (containerEl instanceof HTMLElement) {\n containerEl.dataset.horaeApiBase = apiBase;\n if (options.initialTab) {\n containerEl.dataset.initialTab = options.initialTab;\n }\n if (options.mode) {\n containerEl.dataset.horaeMode = options.mode;\n }\n if (options.viewerUrl) {\n containerEl.dataset.horaeViewerUrl = options.viewerUrl;\n }\n if (options.scaleRegistration) {\n containerEl.dataset.horaeScaleRegistration = options.scaleRegistration;\n }\n\n // Inject the token (the UI bundle will look for this or use its own mechanism)\n if (token) {\n containerEl.dataset.horaeToken = token;\n }\n\n // Add a signature class/id to ensure the embed root is identifiable\n containerEl.classList.add(\"horae-sdk-root\");\n\n // Allow the bundle to easily find its mount point if it uses querySelector internally\n // (We also pass the container selector directly to the mount event later if needed)\n containerEl.dataset.containerSelector = options.container;\n }\n\n return containerEl;\n}\n\n/**\n * Inject the script tag for the UI bundle if it hasn't been injected yet.\n */\nfunction loadUIBundle(uiHost: string): Promise<void> {\n const SCRIPT_ID = \"horae-passport-sdk-ui\";\n\n return new Promise((resolve, reject) => {\n if (document.getElementById(SCRIPT_ID)) {\n // Script already added\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.id = SCRIPT_ID;\n script.type = \"module\";\n // Target the newly created sdk-embed entrypoint\n script.src = `${uiHost.replace(/\\/$/, '')}/sdk-embed.js`;\n\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`PassportSDK: Failed to load UI bundle from ${script.src}`));\n\n document.head.appendChild(script);\n });\n}\n\n/**\n * Render the generic SDK App\n */\nexport async function mountApp(\n options: RenderOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n prepareContainer(options, apiBase, token);\n\n const host = options.uiHost || \"https://app.horae.io\";\n await loadUIBundle(host);\n\n // Dispatch a custom event in case the bundle is already loaded and listening for dynamic mounts\n window.dispatchEvent(new CustomEvent(\"horae:sdk:mount\", {\n detail: {\n container: options.container,\n mode: options.mode,\n viewerUrl: options.viewerUrl,\n scaleRegistration: options.scaleRegistration\n }\n }));\n}\n\n/**\n * Render specifically the Passport List (maps to \"passports\" tab/view)\n */\nexport async function renderPassportList(\n options: RenderOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n return mountApp({ ...options, initialTab: \"passports\" }, apiBase, token);\n}\n\n/**\n * Render specifically a Single Passport (maps to a specific detail view layout)\n */\nexport async function renderPassport(\n options: RenderPassportOptions,\n apiBase: string,\n token: string | null\n): Promise<void> {\n const containerEl = prepareContainer(options, apiBase, token);\n\n if (containerEl instanceof HTMLElement) {\n containerEl.dataset.passportId = options.passportId;\n // Set initialTab to \"detail\" or a specific flag the UI recognizes\n containerEl.dataset.initialTab = \"detail\";\n }\n\n const host = options.uiHost || \"https://app.horae.io\";\n await loadUIBundle(host);\n\n window.dispatchEvent(new CustomEvent(\"horae:sdk:mount\", {\n detail: {\n container: options.container,\n passportId: options.passportId,\n mode: options.mode,\n viewerUrl: options.viewerUrl,\n scaleRegistration: options.scaleRegistration\n }\n }));\n}\n","/**\n * @horae/passport-core\n * Reusable Passport SDK — auth strategies, Horae API client, events.\n * Token-based auth only; no cross-domain cookies.\n */\n\nexport type {\n PassportSDKConfig,\n AuthStrategy,\n PassportListItem,\n PassportDetail,\n ScaleRegistrationPayload,\n SDKMode,\n User,\n} from \"./types.js\";\nexport { createEventBus } from \"./events.js\";\nexport type { SDKEvent, EventMap, EventBus } from \"./events.js\";\nexport { createJwtStrategy, createCustomStrategy } from \"./auth/index.js\";\nexport type { AuthStrategyBase } from \"./auth/index.js\";\nexport { createClient, createClientWithAuth } from \"./client.js\";\nexport type { CreateClientOptions } from \"./client.js\";\nexport { createPassportApi } from \"./api.js\";\nexport * from \"./ui.js\";\n\nimport type { PassportSDKConfig } from \"./types.js\";\nimport { createEventBus } from \"./events.js\";\nimport { createJwtStrategy } from \"./auth/strategies/jwt.js\";\nimport { createCustomStrategy } from \"./auth/strategies/custom.js\";\nimport { createClient } from \"./client.js\";\nimport { createPassportApi } from \"./api.js\";\nimport type { AuthStrategyBase } from \"./auth/index.js\";\nimport { mountApp, renderPassportList, renderPassport } from \"./ui.js\";\nimport type { RenderOptions, RenderPassportOptions } from \"./ui.js\";\n\nexport interface PassportSDK {\n /** Horae API client (axios) */\n readonly api: ReturnType<typeof createPassportApi>;\n /** Event bus for auth:ready, auth:error, passport:claimed, etc. */\n readonly events: ReturnType<typeof createEventBus>;\n /** Auth strategy instance (for setToken/clearToken when available) */\n readonly auth: AuthStrategyBase;\n /** Config */\n readonly config: Readonly<PassportSDKConfig>;\n /** Mount the generic SDK App in headless mode */\n mount(options: RenderOptions): Promise<void>;\n /** Render the Passport List view */\n renderPassportList(options: RenderOptions): Promise<void>;\n /** Render a Single Passport Detail view */\n renderPassport(options: RenderPassportOptions): Promise<void>;\n}\n\n/**\n * Create the Passport SDK instance.\n * - authStrategy \"jwt\": pass token in config or call setToken on auth after getting JWT from your backend.\n * - authStrategy \"custom\": pass getToken in config.\n * - authStrategy \"shopify\": use @horae/passport-shopify to get JWT from bridge, then use jwt or custom.\n */\nexport function createPassportSDK(config: PassportSDKConfig): PassportSDK {\n const mode = config.mode ?? \"heritage\";\n const authStrategy = config.authStrategy ?? (mode === \"scale\" ? \"custom\" : \"jwt\");\n const events = createEventBus();\n let auth: AuthStrategyBase;\n\n if (mode === \"scale\") {\n // Scale mode does not require wallet/Privy token flow by default.\n auth = createCustomStrategy(async () => config.token ?? null);\n } else {\n switch (authStrategy) {\n case \"jwt\": {\n const jwt = createJwtStrategy({\n token: config.token ?? undefined,\n storageKey: config.tokenStorageKey ?? undefined,\n });\n auth = jwt;\n break;\n }\n case \"custom\": {\n if (!config.getToken) throw new Error(\"PassportSDK: getToken required for authStrategy 'custom'\");\n auth = createCustomStrategy(config.getToken);\n break;\n }\n case \"shopify\":\n // Shopify: use JWT strategy; token is set by @horae/passport-shopify bridge\n auth = createJwtStrategy({\n token: config.token ?? undefined,\n storageKey: config.tokenStorageKey ?? \"shopify_access_token\",\n });\n break;\n case \"privy\":\n // Privy: use custom strategy with getToken from host (e.g. getAccessToken from @privy-io/react-auth)\n if (!config.getToken) throw new Error(\"PassportSDK: getToken required for authStrategy 'privy' (pass Privy getAccessToken)\");\n auth = createCustomStrategy(config.getToken);\n break;\n default:\n throw new Error(`PassportSDK: unknown authStrategy ${String(authStrategy)}`);\n }\n }\n\n const client = createClient({ apiBase: config.apiBase, getToken: () => auth.getToken() });\n const api = createPassportApi(client);\n const fallbackScaleRegistration =\n config.serial || config.brandId\n ? {\n serialNumber: config.serial,\n manufacturerId: config.brandId,\n }\n : undefined;\n const scaleRegistrationPayload = config.scaleRegistration ?? fallbackScaleRegistration;\n const scaleRegistration = scaleRegistrationPayload\n ? JSON.stringify(scaleRegistrationPayload)\n : undefined;\n\n return {\n api,\n events,\n auth,\n config: Object.freeze({ ...config, mode }),\n mount: (options) =>\n mountApp(\n {\n ...options,\n mode,\n viewerUrl: config.viewerUrl,\n scaleRegistration,\n },\n config.apiBase,\n config.token || null,\n ),\n renderPassportList: (options) =>\n renderPassportList(\n {\n ...options,\n mode,\n viewerUrl: config.viewerUrl,\n scaleRegistration,\n },\n config.apiBase,\n config.token || null,\n ),\n renderPassport: (options) =>\n renderPassport(\n {\n ...options,\n mode,\n viewerUrl: config.viewerUrl,\n scaleRegistration,\n },\n config.apiBase,\n config.token || null,\n ),\n };\n}\n\nexport const HoraeSDK = {\n init(config: PassportSDKConfig): PassportSDK {\n return createPassportSDK(config);\n },\n};\n\ndeclare global {\n interface Window {\n HoraeSDK?: typeof HoraeSDK;\n }\n}\n\nif (typeof window !== \"undefined\") {\n window.HoraeSDK = HoraeSDK;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@horae.io/passport-core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Horae Passport SDK — core client, auth strategies, Horae API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -21,12 +21,16 @@
|
|
|
21
21
|
"dev": "tsup --watch"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"axios": "^1.
|
|
24
|
+
"axios": "^1.15.0",
|
|
25
25
|
"zod": "^3.24.2"
|
|
26
26
|
},
|
|
27
|
+
"overrides": {
|
|
28
|
+
"axios": "^1.15.0"
|
|
29
|
+
},
|
|
27
30
|
"devDependencies": {
|
|
28
31
|
"tsup": "^8.3.5",
|
|
29
32
|
"typescript": "~5.7.2"
|
|
30
33
|
},
|
|
31
|
-
"peerDependencies": {}
|
|
32
|
-
|
|
34
|
+
"peerDependencies": {},
|
|
35
|
+
"packageManager": "bun@1.3.10"
|
|
36
|
+
}
|