@eventusgo/sdk 0.1.2 → 0.1.4
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/chunk-TJNC4RSJ.js +394 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.js +10 -255
- package/dist/react.d.ts +16 -0
- package/dist/react.js +182 -0
- package/package.json +19 -2
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import QRCode from "qrcode";
|
|
3
|
+
var EventusBridgeUnavailableError = class extends Error {
|
|
4
|
+
constructor(message = "No Eventus bridge is connected.") {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "EventusBridgeUnavailableError";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
function isBridgeUnavailableError(error) {
|
|
10
|
+
return error instanceof Error && error.name === "EventusBridgeUnavailableError";
|
|
11
|
+
}
|
|
12
|
+
var EventEmitter = class {
|
|
13
|
+
listeners = /* @__PURE__ */ new Map();
|
|
14
|
+
on(event, handler) {
|
|
15
|
+
const nextListeners = this.listeners.get(event) ?? /* @__PURE__ */ new Set();
|
|
16
|
+
nextListeners.add(handler);
|
|
17
|
+
this.listeners.set(event, nextListeners);
|
|
18
|
+
return () => {
|
|
19
|
+
nextListeners.delete(handler);
|
|
20
|
+
if (nextListeners.size === 0) {
|
|
21
|
+
this.listeners.delete(event);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
emit(event, payload) {
|
|
26
|
+
const handlers = this.listeners.get(event);
|
|
27
|
+
if (!handlers) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
for (const handler of handlers) {
|
|
31
|
+
handler(payload);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
function getBrowserLocale() {
|
|
36
|
+
if (typeof navigator !== "undefined" && navigator.language) {
|
|
37
|
+
return navigator.language;
|
|
38
|
+
}
|
|
39
|
+
return "en";
|
|
40
|
+
}
|
|
41
|
+
function createDefaultMockContext() {
|
|
42
|
+
const manifest = readInjectedManifest();
|
|
43
|
+
return {
|
|
44
|
+
locale: getBrowserLocale(),
|
|
45
|
+
theme: "light",
|
|
46
|
+
...manifest?.appId ? { appId: manifest.appId } : {},
|
|
47
|
+
user: {
|
|
48
|
+
id: "dev-user",
|
|
49
|
+
name: "Eventus Developer"
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function readInjectedManifest() {
|
|
54
|
+
const manifest = globalThis.__EVENTUS_MANIFEST__;
|
|
55
|
+
if (typeof manifest === "undefined") {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return manifest ?? null;
|
|
59
|
+
}
|
|
60
|
+
function escapeHtml(value) {
|
|
61
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
62
|
+
}
|
|
63
|
+
function isAbsoluteHttpUrl(value) {
|
|
64
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const parsed = new URL(value);
|
|
69
|
+
return (parsed.protocol === "http:" || parsed.protocol === "https:") && !!parsed.hostname;
|
|
70
|
+
} catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function parseDevPreviewDescriptor(value) {
|
|
75
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const descriptor = value;
|
|
79
|
+
const manifest = descriptor.manifest;
|
|
80
|
+
const urls = descriptor.urls;
|
|
81
|
+
if (descriptor.type !== "eventus-dev-preview" || descriptor.version !== 1 || !manifest || typeof manifest !== "object" || Array.isArray(manifest) || !urls || typeof urls !== "object" || Array.isArray(urls)) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const nextManifest = manifest;
|
|
85
|
+
const nextUrls = urls;
|
|
86
|
+
const permissions = nextManifest.permissions;
|
|
87
|
+
if (typeof nextManifest.name !== "string" || !nextManifest.name.trim() || typeof nextManifest.appId !== "string" || !nextManifest.appId.trim() || typeof nextManifest.version !== "string" || !nextManifest.version.trim() || !isAbsoluteHttpUrl(nextUrls.local) || (nextUrls.network !== null && nextUrls.network !== void 0 ? !isAbsoluteHttpUrl(nextUrls.network) : false) || !isAbsoluteHttpUrl(nextUrls.preview) || permissions !== void 0 && (!Array.isArray(permissions) || permissions.some((permission) => typeof permission !== "string"))) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
type: "eventus-dev-preview",
|
|
92
|
+
version: 1,
|
|
93
|
+
manifest: {
|
|
94
|
+
name: nextManifest.name,
|
|
95
|
+
appId: nextManifest.appId,
|
|
96
|
+
version: nextManifest.version,
|
|
97
|
+
...permissions ? { permissions } : {}
|
|
98
|
+
},
|
|
99
|
+
urls: {
|
|
100
|
+
local: nextUrls.local,
|
|
101
|
+
network: nextUrls.network === void 0 ? null : nextUrls.network,
|
|
102
|
+
preview: nextUrls.preview
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async function fetchDevPreviewDescriptor() {
|
|
107
|
+
if (typeof fetch !== "function") {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const response = await fetch("/__eventus__/preview.json", {
|
|
112
|
+
headers: {
|
|
113
|
+
Accept: "application/json"
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
return parseDevPreviewDescriptor(await response.json());
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function renderPreviewValue(label, value) {
|
|
125
|
+
const escaped = escapeHtml(value);
|
|
126
|
+
return `
|
|
127
|
+
<div>
|
|
128
|
+
<dt>${escapeHtml(label)}</dt>
|
|
129
|
+
<dd><code>${escaped}</code></dd>
|
|
130
|
+
</div>
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
function renderPermissions(permissions) {
|
|
134
|
+
const value = permissions && permissions.length > 0 ? permissions.join(", ") : "None";
|
|
135
|
+
return renderPreviewValue("Permissions", value);
|
|
136
|
+
}
|
|
137
|
+
function createLivePreviewHtml(preview, qrSvg) {
|
|
138
|
+
return `
|
|
139
|
+
<section aria-label="Eventus live preview handoff" style="margin:24px 0;display:grid;gap:20px;">
|
|
140
|
+
<style>
|
|
141
|
+
.eventus-live-preview{display:grid;gap:20px;}
|
|
142
|
+
.eventus-live-preview__copy{color:#102347;}
|
|
143
|
+
.eventus-live-preview__copy h2{margin:0 0 12px;font-size:1.4rem;line-height:1.2;}
|
|
144
|
+
.eventus-live-preview__copy p{margin:0;color:#465d82;line-height:1.6;}
|
|
145
|
+
.eventus-live-preview__grid{display:grid;gap:14px;margin:18px 0 0;}
|
|
146
|
+
.eventus-live-preview__grid > div{padding:14px 16px;border-radius:16px;background:#f8fbff;border:1px solid rgba(16,35,71,0.08);}
|
|
147
|
+
.eventus-live-preview__grid dt{font-size:0.72rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:#6880a6;}
|
|
148
|
+
.eventus-live-preview__grid dd{margin:6px 0 0;color:#102347;word-break:break-word;}
|
|
149
|
+
.eventus-live-preview__grid code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:0.9rem;}
|
|
150
|
+
.eventus-live-preview__hint{margin-top:16px !important;color:#465d82 !important;}
|
|
151
|
+
.eventus-live-preview__qr{display:grid;place-items:center;padding:18px;border-radius:24px;background:linear-gradient(180deg,#fefefe 0%,#f3f7ff 100%);border:1px solid rgba(16,35,71,0.08);box-shadow:0 20px 50px rgba(38,73,134,0.14);}
|
|
152
|
+
.eventus-live-preview__qr svg{display:block;width:min(220px,100%);height:auto;}
|
|
153
|
+
.eventus-live-preview__meta{display:none;}
|
|
154
|
+
@media (min-width: 720px){
|
|
155
|
+
.eventus-live-preview{grid-template-columns:minmax(0,1.7fr) minmax(220px,0.9fr);align-items:center;}
|
|
156
|
+
}
|
|
157
|
+
</style>
|
|
158
|
+
<div class="eventus-live-preview">
|
|
159
|
+
<div class="eventus-live-preview__copy">
|
|
160
|
+
<h2>Live preview from your phone</h2>
|
|
161
|
+
<p>Open Eventus X, go to <strong>Developer</strong>, and scan this QR code to launch the mini app with the real Eventus bridge.</p>
|
|
162
|
+
<dl class="eventus-live-preview__grid">
|
|
163
|
+
${renderPreviewValue("Preview URL", preview.urls.preview)}
|
|
164
|
+
${renderPreviewValue("Local URL", preview.urls.local)}
|
|
165
|
+
${preview.urls.network ? renderPreviewValue("Network URL", preview.urls.network) : ""}
|
|
166
|
+
${renderPermissions(preview.manifest.permissions)}
|
|
167
|
+
</dl>
|
|
168
|
+
<p class="eventus-live-preview__hint">Your phone and computer must be on the same local network.</p>
|
|
169
|
+
</div>
|
|
170
|
+
<div class="eventus-live-preview__qr" aria-label="Eventus live preview QR code">
|
|
171
|
+
${qrSvg}
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</section>`.trim();
|
|
175
|
+
}
|
|
176
|
+
async function getLivePreviewHtml() {
|
|
177
|
+
const preview = await fetchDevPreviewDescriptor();
|
|
178
|
+
if (!preview) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
const qrSvg = await QRCode.toString(JSON.stringify(preview), {
|
|
182
|
+
type: "svg",
|
|
183
|
+
width: 220,
|
|
184
|
+
margin: 1
|
|
185
|
+
});
|
|
186
|
+
return createLivePreviewHtml(preview, qrSvg);
|
|
187
|
+
}
|
|
188
|
+
function readWindowBridge() {
|
|
189
|
+
if (typeof window === "undefined") {
|
|
190
|
+
return void 0;
|
|
191
|
+
}
|
|
192
|
+
return window.Eventus;
|
|
193
|
+
}
|
|
194
|
+
function readStringField(record, key) {
|
|
195
|
+
const value = record?.[key];
|
|
196
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
197
|
+
}
|
|
198
|
+
function mapNativeUser(user) {
|
|
199
|
+
if (!user || typeof user.id !== "string" || !user.id.trim()) {
|
|
200
|
+
return void 0;
|
|
201
|
+
}
|
|
202
|
+
const displayName = typeof user.displayName === "string" ? user.displayName : void 0;
|
|
203
|
+
const name = typeof user.name === "string" ? user.name : displayName;
|
|
204
|
+
const avatarUrl = typeof user.avatarUrl === "string" ? user.avatarUrl : void 0;
|
|
205
|
+
const handle = typeof user.handle === "string" ? user.handle : void 0;
|
|
206
|
+
return {
|
|
207
|
+
id: user.id,
|
|
208
|
+
...name ? { name } : {},
|
|
209
|
+
...displayName ? { displayName } : {},
|
|
210
|
+
...avatarUrl ? { avatarUrl } : {},
|
|
211
|
+
...handle ? { handle } : {}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function mapNativeContext(bridge) {
|
|
215
|
+
const appId = readStringField(bridge.app, "slug") ?? readStringField(bridge.app, "id");
|
|
216
|
+
const locale = readStringField(bridge.device, "locale") ?? getBrowserLocale();
|
|
217
|
+
const themeValue = readStringField(bridge.device, "themeMode");
|
|
218
|
+
const theme = themeValue === "dark" ? "dark" : "light";
|
|
219
|
+
const user = mapNativeUser(bridge.user);
|
|
220
|
+
return {
|
|
221
|
+
locale,
|
|
222
|
+
theme,
|
|
223
|
+
...appId ? { appId } : {},
|
|
224
|
+
...user ? { user } : {}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
var mockState = {
|
|
228
|
+
enabled: false,
|
|
229
|
+
context: createDefaultMockContext(),
|
|
230
|
+
manifestOverride: void 0,
|
|
231
|
+
ready: false
|
|
232
|
+
};
|
|
233
|
+
var EventusClientImpl = class {
|
|
234
|
+
emitter = new EventEmitter();
|
|
235
|
+
lastReadySource;
|
|
236
|
+
hasReadyRequest = false;
|
|
237
|
+
constructor() {
|
|
238
|
+
if (typeof window !== "undefined") {
|
|
239
|
+
window.addEventListener("eventus:ready", this.handleBridgeReady);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async ready() {
|
|
243
|
+
this.hasReadyRequest = true;
|
|
244
|
+
const bridge = await this.waitForNativeBridge();
|
|
245
|
+
if (bridge) {
|
|
246
|
+
this.emitReady(mapNativeContext(bridge), "native");
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (!mockState.enabled) {
|
|
250
|
+
throw new EventusBridgeUnavailableError();
|
|
251
|
+
}
|
|
252
|
+
mockState.ready = true;
|
|
253
|
+
this.emitReady(mockState.context, "mock");
|
|
254
|
+
}
|
|
255
|
+
async getContext() {
|
|
256
|
+
const bridge = readWindowBridge();
|
|
257
|
+
if (bridge) {
|
|
258
|
+
return mapNativeContext(bridge);
|
|
259
|
+
}
|
|
260
|
+
if (!mockState.enabled) {
|
|
261
|
+
throw new EventusBridgeUnavailableError();
|
|
262
|
+
}
|
|
263
|
+
return mockState.context;
|
|
264
|
+
}
|
|
265
|
+
getManifest() {
|
|
266
|
+
const bridge = readWindowBridge();
|
|
267
|
+
if (bridge) {
|
|
268
|
+
return readInjectedManifest();
|
|
269
|
+
}
|
|
270
|
+
return mockState.manifestOverride === void 0 ? readInjectedManifest() : mockState.manifestOverride;
|
|
271
|
+
}
|
|
272
|
+
async request(action, payload) {
|
|
273
|
+
const bridge = readWindowBridge();
|
|
274
|
+
if (bridge) {
|
|
275
|
+
if (typeof bridge.request === "function") {
|
|
276
|
+
return bridge.request(action, payload);
|
|
277
|
+
}
|
|
278
|
+
const bridgeAction = bridge[action];
|
|
279
|
+
if (typeof bridgeAction === "function") {
|
|
280
|
+
return bridgeAction(payload);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (!mockState.enabled) {
|
|
284
|
+
throw new EventusBridgeUnavailableError(
|
|
285
|
+
`Eventus request "${action}" requires a native bridge or explicit mock mode.`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
const mockedResponse = {
|
|
289
|
+
mock: true,
|
|
290
|
+
action,
|
|
291
|
+
payload: payload ?? null,
|
|
292
|
+
message: "Eventus request used the browser mock fallback because no native bridge is connected."
|
|
293
|
+
};
|
|
294
|
+
return mockedResponse;
|
|
295
|
+
}
|
|
296
|
+
on(event, handler) {
|
|
297
|
+
return this.emitter.on(event, handler);
|
|
298
|
+
}
|
|
299
|
+
configureMock(options = {}) {
|
|
300
|
+
const previousTheme = mockState.context.theme;
|
|
301
|
+
const shouldEnableMock = !!options.context || "manifest" in options || typeof options.ready === "boolean";
|
|
302
|
+
if (options.reset) {
|
|
303
|
+
mockState.enabled = false;
|
|
304
|
+
mockState.context = createDefaultMockContext();
|
|
305
|
+
mockState.manifestOverride = void 0;
|
|
306
|
+
mockState.ready = false;
|
|
307
|
+
this.lastReadySource = void 0;
|
|
308
|
+
this.hasReadyRequest = false;
|
|
309
|
+
}
|
|
310
|
+
if (shouldEnableMock) {
|
|
311
|
+
mockState.enabled = true;
|
|
312
|
+
}
|
|
313
|
+
if (options.context) {
|
|
314
|
+
const nextUser = options.context.user ? {
|
|
315
|
+
...mockState.context.user ?? {},
|
|
316
|
+
...options.context.user
|
|
317
|
+
} : mockState.context.user;
|
|
318
|
+
mockState.context = {
|
|
319
|
+
...mockState.context,
|
|
320
|
+
...options.context,
|
|
321
|
+
...nextUser ? { user: nextUser } : {}
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
if ("manifest" in options) {
|
|
325
|
+
mockState.manifestOverride = options.manifest;
|
|
326
|
+
}
|
|
327
|
+
if (typeof options.ready === "boolean") {
|
|
328
|
+
mockState.ready = options.ready;
|
|
329
|
+
if (!options.ready) {
|
|
330
|
+
this.lastReadySource = void 0;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (mockState.context.theme !== previousTheme) {
|
|
334
|
+
this.emitter.emit("themeChange", {
|
|
335
|
+
theme: mockState.context.theme,
|
|
336
|
+
context: mockState.context,
|
|
337
|
+
source: "mock"
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
emitReady(context, source) {
|
|
342
|
+
if (this.lastReadySource === source) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
this.lastReadySource = source;
|
|
346
|
+
this.emitter.emit("ready", {
|
|
347
|
+
context,
|
|
348
|
+
source
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
handleBridgeReady = () => {
|
|
352
|
+
if (!this.hasReadyRequest && this.lastReadySource === void 0) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const bridge = readWindowBridge();
|
|
356
|
+
if (!bridge) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
this.emitReady(mapNativeContext(bridge), "native");
|
|
360
|
+
};
|
|
361
|
+
async waitForNativeBridge() {
|
|
362
|
+
const bridge = readWindowBridge();
|
|
363
|
+
if (bridge || typeof window === "undefined") {
|
|
364
|
+
return bridge;
|
|
365
|
+
}
|
|
366
|
+
return new Promise((resolve) => {
|
|
367
|
+
const timeout = window.setTimeout(() => {
|
|
368
|
+
cleanup();
|
|
369
|
+
resolve(readWindowBridge());
|
|
370
|
+
}, 120);
|
|
371
|
+
const onReady = () => {
|
|
372
|
+
cleanup();
|
|
373
|
+
resolve(readWindowBridge());
|
|
374
|
+
};
|
|
375
|
+
const cleanup = () => {
|
|
376
|
+
window.clearTimeout(timeout);
|
|
377
|
+
window.removeEventListener("eventus:ready", onReady);
|
|
378
|
+
};
|
|
379
|
+
window.addEventListener("eventus:ready", onReady, { once: true });
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
var eventus = new EventusClientImpl();
|
|
384
|
+
function configureMockEventus(options = {}) {
|
|
385
|
+
eventus.configureMock(options);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export {
|
|
389
|
+
EventusBridgeUnavailableError,
|
|
390
|
+
isBridgeUnavailableError,
|
|
391
|
+
getLivePreviewHtml,
|
|
392
|
+
eventus,
|
|
393
|
+
configureMockEventus
|
|
394
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,16 @@ type EventusManifest = {
|
|
|
19
19
|
version: string;
|
|
20
20
|
permissions?: Array<EventusPermission | string>;
|
|
21
21
|
};
|
|
22
|
+
type EventusDevPreviewDescriptor = {
|
|
23
|
+
type: "eventus-dev-preview";
|
|
24
|
+
version: 1;
|
|
25
|
+
manifest: EventusManifest;
|
|
26
|
+
urls: {
|
|
27
|
+
local: string;
|
|
28
|
+
network: string | null;
|
|
29
|
+
preview: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
22
32
|
type EventusRuntimeSource = "native" | "mock";
|
|
23
33
|
type EventusEventMap = {
|
|
24
34
|
ready: {
|
|
@@ -49,6 +59,7 @@ type ConfigureMockEventusOptions = {
|
|
|
49
59
|
declare class EventusBridgeUnavailableError extends Error {
|
|
50
60
|
constructor(message?: string);
|
|
51
61
|
}
|
|
62
|
+
declare function isBridgeUnavailableError(error: unknown): boolean;
|
|
52
63
|
type NativeBridgeUser = Record<string, unknown>;
|
|
53
64
|
type NativeBridgeRecord = Record<string, unknown>;
|
|
54
65
|
type NativeEventusBridge = {
|
|
@@ -64,6 +75,7 @@ declare global {
|
|
|
64
75
|
Eventus?: NativeEventusBridge;
|
|
65
76
|
}
|
|
66
77
|
}
|
|
78
|
+
declare function getLivePreviewHtml(): Promise<string | null>;
|
|
67
79
|
declare class EventusClientImpl implements EventusClient {
|
|
68
80
|
private emitter;
|
|
69
81
|
private lastReadySource;
|
|
@@ -82,4 +94,4 @@ declare class EventusClientImpl implements EventusClient {
|
|
|
82
94
|
declare const eventus: EventusClientImpl;
|
|
83
95
|
declare function configureMockEventus(options?: ConfigureMockEventusOptions): void;
|
|
84
96
|
|
|
85
|
-
export { type ConfigureMockEventusOptions, EventusBridgeUnavailableError, type EventusClient, type EventusContext, type EventusEventHandler, type EventusEventMap, type EventusEventName, type EventusManifest, type EventusPermission, type EventusRuntimeSource, type EventusTheme, type EventusUser, configureMockEventus, eventus };
|
|
97
|
+
export { type ConfigureMockEventusOptions, EventusBridgeUnavailableError, type EventusClient, type EventusContext, type EventusDevPreviewDescriptor, type EventusEventHandler, type EventusEventMap, type EventusEventName, type EventusManifest, type EventusPermission, type EventusRuntimeSource, type EventusTheme, type EventusUser, configureMockEventus, eventus, getLivePreviewHtml, isBridgeUnavailableError };
|
package/dist/index.js
CHANGED
|
@@ -1,259 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
var EventEmitter = class {
|
|
9
|
-
listeners = /* @__PURE__ */ new Map();
|
|
10
|
-
on(event, handler) {
|
|
11
|
-
const nextListeners = this.listeners.get(event) ?? /* @__PURE__ */ new Set();
|
|
12
|
-
nextListeners.add(handler);
|
|
13
|
-
this.listeners.set(event, nextListeners);
|
|
14
|
-
return () => {
|
|
15
|
-
nextListeners.delete(handler);
|
|
16
|
-
if (nextListeners.size === 0) {
|
|
17
|
-
this.listeners.delete(event);
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
emit(event, payload) {
|
|
22
|
-
const handlers = this.listeners.get(event);
|
|
23
|
-
if (!handlers) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
for (const handler of handlers) {
|
|
27
|
-
handler(payload);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
function getBrowserLocale() {
|
|
32
|
-
if (typeof navigator !== "undefined" && navigator.language) {
|
|
33
|
-
return navigator.language;
|
|
34
|
-
}
|
|
35
|
-
return "en";
|
|
36
|
-
}
|
|
37
|
-
function createDefaultMockContext() {
|
|
38
|
-
const manifest = readInjectedManifest();
|
|
39
|
-
return {
|
|
40
|
-
locale: getBrowserLocale(),
|
|
41
|
-
theme: "light",
|
|
42
|
-
...manifest?.appId ? { appId: manifest.appId } : {},
|
|
43
|
-
user: {
|
|
44
|
-
id: "dev-user",
|
|
45
|
-
name: "Eventus Developer"
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
function readInjectedManifest() {
|
|
50
|
-
const manifest = globalThis.__EVENTUS_MANIFEST__;
|
|
51
|
-
if (typeof manifest === "undefined") {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
return manifest ?? null;
|
|
55
|
-
}
|
|
56
|
-
function readWindowBridge() {
|
|
57
|
-
if (typeof window === "undefined") {
|
|
58
|
-
return void 0;
|
|
59
|
-
}
|
|
60
|
-
return window.Eventus;
|
|
61
|
-
}
|
|
62
|
-
function readStringField(record, key) {
|
|
63
|
-
const value = record?.[key];
|
|
64
|
-
return typeof value === "string" && value.trim() ? value : void 0;
|
|
65
|
-
}
|
|
66
|
-
function mapNativeUser(user) {
|
|
67
|
-
if (!user || typeof user.id !== "string" || !user.id.trim()) {
|
|
68
|
-
return void 0;
|
|
69
|
-
}
|
|
70
|
-
const displayName = typeof user.displayName === "string" ? user.displayName : void 0;
|
|
71
|
-
const name = typeof user.name === "string" ? user.name : displayName;
|
|
72
|
-
const avatarUrl = typeof user.avatarUrl === "string" ? user.avatarUrl : void 0;
|
|
73
|
-
const handle = typeof user.handle === "string" ? user.handle : void 0;
|
|
74
|
-
return {
|
|
75
|
-
id: user.id,
|
|
76
|
-
...name ? { name } : {},
|
|
77
|
-
...displayName ? { displayName } : {},
|
|
78
|
-
...avatarUrl ? { avatarUrl } : {},
|
|
79
|
-
...handle ? { handle } : {}
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
function mapNativeContext(bridge) {
|
|
83
|
-
const appId = readStringField(bridge.app, "slug") ?? readStringField(bridge.app, "id");
|
|
84
|
-
const locale = readStringField(bridge.device, "locale") ?? getBrowserLocale();
|
|
85
|
-
const themeValue = readStringField(bridge.device, "themeMode");
|
|
86
|
-
const theme = themeValue === "dark" ? "dark" : "light";
|
|
87
|
-
const user = mapNativeUser(bridge.user);
|
|
88
|
-
return {
|
|
89
|
-
locale,
|
|
90
|
-
theme,
|
|
91
|
-
...appId ? { appId } : {},
|
|
92
|
-
...user ? { user } : {}
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
var mockState = {
|
|
96
|
-
enabled: false,
|
|
97
|
-
context: createDefaultMockContext(),
|
|
98
|
-
manifestOverride: void 0,
|
|
99
|
-
ready: false
|
|
100
|
-
};
|
|
101
|
-
var EventusClientImpl = class {
|
|
102
|
-
emitter = new EventEmitter();
|
|
103
|
-
lastReadySource;
|
|
104
|
-
hasReadyRequest = false;
|
|
105
|
-
constructor() {
|
|
106
|
-
if (typeof window !== "undefined") {
|
|
107
|
-
window.addEventListener("eventus:ready", this.handleBridgeReady);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
async ready() {
|
|
111
|
-
this.hasReadyRequest = true;
|
|
112
|
-
const bridge = await this.waitForNativeBridge();
|
|
113
|
-
if (bridge) {
|
|
114
|
-
this.emitReady(mapNativeContext(bridge), "native");
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
if (!mockState.enabled) {
|
|
118
|
-
throw new EventusBridgeUnavailableError();
|
|
119
|
-
}
|
|
120
|
-
mockState.ready = true;
|
|
121
|
-
this.emitReady(mockState.context, "mock");
|
|
122
|
-
}
|
|
123
|
-
async getContext() {
|
|
124
|
-
const bridge = readWindowBridge();
|
|
125
|
-
if (bridge) {
|
|
126
|
-
return mapNativeContext(bridge);
|
|
127
|
-
}
|
|
128
|
-
if (!mockState.enabled) {
|
|
129
|
-
throw new EventusBridgeUnavailableError();
|
|
130
|
-
}
|
|
131
|
-
return mockState.context;
|
|
132
|
-
}
|
|
133
|
-
getManifest() {
|
|
134
|
-
const bridge = readWindowBridge();
|
|
135
|
-
if (bridge) {
|
|
136
|
-
return readInjectedManifest();
|
|
137
|
-
}
|
|
138
|
-
return mockState.manifestOverride === void 0 ? readInjectedManifest() : mockState.manifestOverride;
|
|
139
|
-
}
|
|
140
|
-
async request(action, payload) {
|
|
141
|
-
const bridge = readWindowBridge();
|
|
142
|
-
if (bridge) {
|
|
143
|
-
if (typeof bridge.request === "function") {
|
|
144
|
-
return bridge.request(action, payload);
|
|
145
|
-
}
|
|
146
|
-
const bridgeAction = bridge[action];
|
|
147
|
-
if (typeof bridgeAction === "function") {
|
|
148
|
-
return bridgeAction(payload);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (!mockState.enabled) {
|
|
152
|
-
throw new EventusBridgeUnavailableError(
|
|
153
|
-
`Eventus request "${action}" requires a native bridge or explicit mock mode.`
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
const mockedResponse = {
|
|
157
|
-
mock: true,
|
|
158
|
-
action,
|
|
159
|
-
payload: payload ?? null,
|
|
160
|
-
message: "Eventus request used the browser mock fallback because no native bridge is connected."
|
|
161
|
-
};
|
|
162
|
-
return mockedResponse;
|
|
163
|
-
}
|
|
164
|
-
on(event, handler) {
|
|
165
|
-
return this.emitter.on(event, handler);
|
|
166
|
-
}
|
|
167
|
-
configureMock(options = {}) {
|
|
168
|
-
const previousTheme = mockState.context.theme;
|
|
169
|
-
const shouldEnableMock = !!options.context || "manifest" in options || typeof options.ready === "boolean";
|
|
170
|
-
if (options.reset) {
|
|
171
|
-
mockState.enabled = false;
|
|
172
|
-
mockState.context = createDefaultMockContext();
|
|
173
|
-
mockState.manifestOverride = void 0;
|
|
174
|
-
mockState.ready = false;
|
|
175
|
-
this.lastReadySource = void 0;
|
|
176
|
-
this.hasReadyRequest = false;
|
|
177
|
-
}
|
|
178
|
-
if (shouldEnableMock) {
|
|
179
|
-
mockState.enabled = true;
|
|
180
|
-
}
|
|
181
|
-
if (options.context) {
|
|
182
|
-
const nextUser = options.context.user ? {
|
|
183
|
-
...mockState.context.user ?? {},
|
|
184
|
-
...options.context.user
|
|
185
|
-
} : mockState.context.user;
|
|
186
|
-
mockState.context = {
|
|
187
|
-
...mockState.context,
|
|
188
|
-
...options.context,
|
|
189
|
-
...nextUser ? { user: nextUser } : {}
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
if ("manifest" in options) {
|
|
193
|
-
mockState.manifestOverride = options.manifest;
|
|
194
|
-
}
|
|
195
|
-
if (typeof options.ready === "boolean") {
|
|
196
|
-
mockState.ready = options.ready;
|
|
197
|
-
if (!options.ready) {
|
|
198
|
-
this.lastReadySource = void 0;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
if (mockState.context.theme !== previousTheme) {
|
|
202
|
-
this.emitter.emit("themeChange", {
|
|
203
|
-
theme: mockState.context.theme,
|
|
204
|
-
context: mockState.context,
|
|
205
|
-
source: "mock"
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
emitReady(context, source) {
|
|
210
|
-
if (this.lastReadySource === source) {
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
this.lastReadySource = source;
|
|
214
|
-
this.emitter.emit("ready", {
|
|
215
|
-
context,
|
|
216
|
-
source
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
handleBridgeReady = () => {
|
|
220
|
-
if (!this.hasReadyRequest && this.lastReadySource === void 0) {
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
const bridge = readWindowBridge();
|
|
224
|
-
if (!bridge) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
this.emitReady(mapNativeContext(bridge), "native");
|
|
228
|
-
};
|
|
229
|
-
async waitForNativeBridge() {
|
|
230
|
-
const bridge = readWindowBridge();
|
|
231
|
-
if (bridge || typeof window === "undefined") {
|
|
232
|
-
return bridge;
|
|
233
|
-
}
|
|
234
|
-
return new Promise((resolve) => {
|
|
235
|
-
const timeout = window.setTimeout(() => {
|
|
236
|
-
cleanup();
|
|
237
|
-
resolve(readWindowBridge());
|
|
238
|
-
}, 120);
|
|
239
|
-
const onReady = () => {
|
|
240
|
-
cleanup();
|
|
241
|
-
resolve(readWindowBridge());
|
|
242
|
-
};
|
|
243
|
-
const cleanup = () => {
|
|
244
|
-
window.clearTimeout(timeout);
|
|
245
|
-
window.removeEventListener("eventus:ready", onReady);
|
|
246
|
-
};
|
|
247
|
-
window.addEventListener("eventus:ready", onReady, { once: true });
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
var eventus = new EventusClientImpl();
|
|
252
|
-
function configureMockEventus(options = {}) {
|
|
253
|
-
eventus.configureMock(options);
|
|
254
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
EventusBridgeUnavailableError,
|
|
3
|
+
configureMockEventus,
|
|
4
|
+
eventus,
|
|
5
|
+
getLivePreviewHtml,
|
|
6
|
+
isBridgeUnavailableError
|
|
7
|
+
} from "./chunk-TJNC4RSJ.js";
|
|
255
8
|
export {
|
|
256
9
|
EventusBridgeUnavailableError,
|
|
257
10
|
configureMockEventus,
|
|
258
|
-
eventus
|
|
11
|
+
eventus,
|
|
12
|
+
getLivePreviewHtml,
|
|
13
|
+
isBridgeUnavailableError
|
|
259
14
|
};
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { EventusContext, EventusRuntimeSource } from './index.js';
|
|
4
|
+
|
|
5
|
+
type EventusReactContextValue = {
|
|
6
|
+
context: EventusContext;
|
|
7
|
+
runtimeSource: EventusRuntimeSource;
|
|
8
|
+
};
|
|
9
|
+
type EventusContextProviderProps = {
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
bridgeUnavailable?: ReactNode;
|
|
12
|
+
};
|
|
13
|
+
declare function EventusContextProvider({ children, bridgeUnavailable, }: EventusContextProviderProps): react_jsx_runtime.JSX.Element;
|
|
14
|
+
declare function useEventusContext(): EventusReactContextValue;
|
|
15
|
+
|
|
16
|
+
export { EventusContextProvider, type EventusContextProviderProps, useEventusContext };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import {
|
|
2
|
+
eventus,
|
|
3
|
+
getLivePreviewHtml,
|
|
4
|
+
isBridgeUnavailableError
|
|
5
|
+
} from "./chunk-TJNC4RSJ.js";
|
|
6
|
+
|
|
7
|
+
// src/react.tsx
|
|
8
|
+
import {
|
|
9
|
+
createContext,
|
|
10
|
+
useContext,
|
|
11
|
+
useEffect,
|
|
12
|
+
useState
|
|
13
|
+
} from "react";
|
|
14
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
var EventusReactContext = createContext(
|
|
16
|
+
null
|
|
17
|
+
);
|
|
18
|
+
function EventusContextProvider({
|
|
19
|
+
children,
|
|
20
|
+
bridgeUnavailable
|
|
21
|
+
}) {
|
|
22
|
+
const [state, setState] = useState({ status: "loading" });
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
let cancelled = false;
|
|
25
|
+
let receivedReadyEvent = false;
|
|
26
|
+
const unsubscribeReady = eventus.on("ready", ({ context, source }) => {
|
|
27
|
+
receivedReadyEvent = true;
|
|
28
|
+
if (!cancelled) {
|
|
29
|
+
setState({
|
|
30
|
+
status: "ready",
|
|
31
|
+
context,
|
|
32
|
+
runtimeSource: source
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const unsubscribeThemeChange = eventus.on(
|
|
37
|
+
"themeChange",
|
|
38
|
+
({ context, source }) => {
|
|
39
|
+
if (!cancelled) {
|
|
40
|
+
setState({
|
|
41
|
+
status: "ready",
|
|
42
|
+
context,
|
|
43
|
+
runtimeSource: source
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
void (async () => {
|
|
49
|
+
try {
|
|
50
|
+
await eventus.ready();
|
|
51
|
+
const context = await eventus.getContext();
|
|
52
|
+
if (!cancelled && !receivedReadyEvent) {
|
|
53
|
+
setState({
|
|
54
|
+
status: "ready",
|
|
55
|
+
context,
|
|
56
|
+
runtimeSource: window.Eventus ? "native" : "mock"
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (receivedReadyEvent || cancelled) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (isBridgeUnavailableError(error)) {
|
|
64
|
+
const previewHtml = await getLivePreviewHtml();
|
|
65
|
+
if (!cancelled && !receivedReadyEvent) {
|
|
66
|
+
setState({
|
|
67
|
+
status: "bridge-unavailable",
|
|
68
|
+
previewHtml
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!cancelled) {
|
|
74
|
+
setState({
|
|
75
|
+
status: "error",
|
|
76
|
+
message: error instanceof Error ? error.message : "Unable to initialize the Eventus client."
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
})();
|
|
81
|
+
return () => {
|
|
82
|
+
cancelled = true;
|
|
83
|
+
unsubscribeReady();
|
|
84
|
+
unsubscribeThemeChange();
|
|
85
|
+
};
|
|
86
|
+
}, []);
|
|
87
|
+
if (state.status === "ready") {
|
|
88
|
+
return /* @__PURE__ */ jsx(
|
|
89
|
+
EventusReactContext.Provider,
|
|
90
|
+
{
|
|
91
|
+
value: {
|
|
92
|
+
context: state.context,
|
|
93
|
+
runtimeSource: state.runtimeSource
|
|
94
|
+
},
|
|
95
|
+
children
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (state.status === "bridge-unavailable") {
|
|
100
|
+
if (bridgeUnavailable) {
|
|
101
|
+
return /* @__PURE__ */ jsx(Fragment, { children: bridgeUnavailable });
|
|
102
|
+
}
|
|
103
|
+
return /* @__PURE__ */ jsx(DefaultBridgeUnavailable, { previewHtml: state.previewHtml });
|
|
104
|
+
}
|
|
105
|
+
if (state.status === "error") {
|
|
106
|
+
return /* @__PURE__ */ jsx(DefaultStatusCard, { title: "Unable to start Eventus", body: state.message });
|
|
107
|
+
}
|
|
108
|
+
return /* @__PURE__ */ jsx(
|
|
109
|
+
DefaultStatusCard,
|
|
110
|
+
{
|
|
111
|
+
title: "Connecting to Eventus",
|
|
112
|
+
body: "Waiting for the Eventus bridge to become available."
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
function useEventusContext() {
|
|
117
|
+
const value = useContext(EventusReactContext);
|
|
118
|
+
if (!value) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
"useEventusContext must be used within an EventusContextProvider."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
function DefaultBridgeUnavailable({
|
|
126
|
+
previewHtml
|
|
127
|
+
}) {
|
|
128
|
+
if (previewHtml) {
|
|
129
|
+
return /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: previewHtml } });
|
|
130
|
+
}
|
|
131
|
+
return /* @__PURE__ */ jsx(
|
|
132
|
+
DefaultStatusCard,
|
|
133
|
+
{
|
|
134
|
+
title: "Open inside Eventus X",
|
|
135
|
+
body: "This mini app needs the Eventus bridge to access the real runtime. Open it from Eventus X to test it with production-like behavior."
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
function DefaultStatusCard({ title, body }) {
|
|
140
|
+
return /* @__PURE__ */ jsx("main", { style: statusShellStyle, children: /* @__PURE__ */ jsxs("section", { style: statusCardStyle, children: [
|
|
141
|
+
/* @__PURE__ */ jsx("p", { style: statusEyebrowStyle, children: "Eventus Mini App Toolkit" }),
|
|
142
|
+
/* @__PURE__ */ jsx("h1", { style: statusTitleStyle, children: title }),
|
|
143
|
+
/* @__PURE__ */ jsx("p", { style: statusBodyStyle, children: body })
|
|
144
|
+
] }) });
|
|
145
|
+
}
|
|
146
|
+
var statusShellStyle = {
|
|
147
|
+
minHeight: "100vh",
|
|
148
|
+
display: "grid",
|
|
149
|
+
placeItems: "center",
|
|
150
|
+
padding: "24px",
|
|
151
|
+
background: "radial-gradient(circle at top, #d8f2ff 0%, #f3f9ff 35%, #eef3ff 100%)"
|
|
152
|
+
};
|
|
153
|
+
var statusCardStyle = {
|
|
154
|
+
width: "min(680px, 100%)",
|
|
155
|
+
padding: "32px",
|
|
156
|
+
borderRadius: "24px",
|
|
157
|
+
background: "rgba(255, 255, 255, 0.88)",
|
|
158
|
+
border: "1px solid rgba(16, 35, 71, 0.08)",
|
|
159
|
+
boxShadow: "0 24px 80px rgba(38, 73, 134, 0.14)",
|
|
160
|
+
color: "#102347"
|
|
161
|
+
};
|
|
162
|
+
var statusEyebrowStyle = {
|
|
163
|
+
margin: "0 0 8px",
|
|
164
|
+
fontSize: "0.85rem",
|
|
165
|
+
letterSpacing: "0.12em",
|
|
166
|
+
textTransform: "uppercase",
|
|
167
|
+
color: "#3f6ea8"
|
|
168
|
+
};
|
|
169
|
+
var statusTitleStyle = {
|
|
170
|
+
margin: "0 0 12px",
|
|
171
|
+
fontSize: "clamp(2rem, 4vw, 3rem)",
|
|
172
|
+
lineHeight: 1.05
|
|
173
|
+
};
|
|
174
|
+
var statusBodyStyle = {
|
|
175
|
+
margin: 0,
|
|
176
|
+
color: "#465d82",
|
|
177
|
+
lineHeight: 1.6
|
|
178
|
+
};
|
|
179
|
+
export {
|
|
180
|
+
EventusContextProvider,
|
|
181
|
+
useEventusContext
|
|
182
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eventusgo/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Eventus mini-app SDK with an explicit browser mock mode.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,14 +13,31 @@
|
|
|
13
13
|
".": {
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./react": {
|
|
18
|
+
"types": "./dist/react.d.ts",
|
|
19
|
+
"import": "./dist/react.js"
|
|
16
20
|
}
|
|
17
21
|
},
|
|
18
22
|
"files": [
|
|
19
23
|
"dist"
|
|
20
24
|
],
|
|
21
25
|
"scripts": {
|
|
22
|
-
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
26
|
+
"build": "tsup src/index.ts src/react.tsx --format esm --dts --clean",
|
|
23
27
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
24
28
|
"test": "vitest run"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"qrcode": "1.5.4"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/qrcode": "1.5.5",
|
|
38
|
+
"@types/react": "18.3.28",
|
|
39
|
+
"@types/react-dom": "18.3.7",
|
|
40
|
+
"react": "18.3.1",
|
|
41
|
+
"react-dom": "18.3.1"
|
|
25
42
|
}
|
|
26
43
|
}
|