@basictech/react 0.8.0-beta.1 → 0.8.0-beta.2

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.js CHANGED
@@ -238,9 +238,812 @@ var init_syncProtocol = __esm({
238
238
  }
239
239
  });
240
240
 
241
+ // package.json
242
+ var version;
243
+ var init_package = __esm({
244
+ "package.json"() {
245
+ version = "0.8.0-beta.2";
246
+ }
247
+ });
248
+
249
+ // src/utils/network.ts
250
+ function isDevelopment(debug) {
251
+ if (debug === true) return true;
252
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "development") return true;
253
+ if (typeof window === "undefined" || !window.location) return false;
254
+ const host = window.location.hostname;
255
+ return host === "localhost" || host === "127.0.0.1" || host.includes("localhost") || host.includes("127.0.0.1") || host.includes(".local");
256
+ }
257
+ function normalizeVersion(v) {
258
+ if (v == null) return null;
259
+ const t = String(v).trim();
260
+ return t.length ? t : null;
261
+ }
262
+ function versionsMatch(a, b) {
263
+ const na = a.trim();
264
+ const nb = b.trim();
265
+ if (na === nb) return true;
266
+ const va = import_semver.default.valid(na);
267
+ const vb = import_semver.default.valid(nb);
268
+ if (va && vb) return import_semver.default.eq(va, vb);
269
+ return false;
270
+ }
271
+ function usesBetaDistTag(version2) {
272
+ const pre = import_semver.default.prerelease(version2);
273
+ const id = pre?.[0];
274
+ return typeof id === "string" && id.toLowerCase() === "beta";
275
+ }
276
+ async function checkForNewVersion() {
277
+ try {
278
+ const currentVersion = normalizeVersion(version);
279
+ if (!currentVersion) {
280
+ return { hasNewVersion: false, latestVersion: null, currentVersion: null };
281
+ }
282
+ const response = await fetch("https://registry.npmjs.org/@basictech/react", {
283
+ headers: { Accept: "application/vnd.npm.install-v1+json" }
284
+ });
285
+ if (!response.ok) {
286
+ throw new Error("Failed to fetch version from npm");
287
+ }
288
+ const data = await response.json();
289
+ const distTags = data["dist-tags"] ?? {};
290
+ const rawRegistry = usesBetaDistTag(currentVersion) ? distTags.beta ?? distTags.latest : distTags.latest;
291
+ const latestVersion = normalizeVersion(rawRegistry ?? null);
292
+ if (!latestVersion) {
293
+ throw new Error("Missing dist-tags from npm registry");
294
+ }
295
+ const same = versionsMatch(currentVersion, latestVersion);
296
+ if (!same && isDevelopment()) {
297
+ log("[basic] version check mismatch:", {
298
+ currentVersion,
299
+ registryVersion: latestVersion,
300
+ channel: usesBetaDistTag(currentVersion) ? "beta" : "latest"
301
+ });
302
+ }
303
+ if (!same) {
304
+ console.warn("[basic] New version available:", latestVersion, `
305
+ run "npm install @basictech/react@${latestVersion}" to update`);
306
+ }
307
+ if (usesBetaDistTag(currentVersion)) {
308
+ log("thank you for being on basictech/react beta :)");
309
+ }
310
+ return {
311
+ hasNewVersion: !same,
312
+ latestVersion,
313
+ currentVersion
314
+ };
315
+ } catch (error) {
316
+ log("Error checking for new version:", error);
317
+ return {
318
+ hasNewVersion: false,
319
+ latestVersion: null,
320
+ currentVersion: null
321
+ };
322
+ }
323
+ }
324
+ function cleanOAuthParamsFromUrl() {
325
+ if (window.location.search.includes("code") || window.location.search.includes("state")) {
326
+ const url = new URL(window.location.href);
327
+ url.searchParams.delete("code");
328
+ url.searchParams.delete("state");
329
+ window.history.pushState({}, document.title, url.pathname + url.search);
330
+ log("Cleaned OAuth parameters from URL");
331
+ }
332
+ }
333
+ function getSyncStatus(statusCode) {
334
+ switch (statusCode) {
335
+ case -1:
336
+ return "ERROR";
337
+ case 0:
338
+ return "OFFLINE";
339
+ case 1:
340
+ return "CONNECTING";
341
+ case 2:
342
+ return "ONLINE";
343
+ case 3:
344
+ return "SYNCING";
345
+ case 4:
346
+ return "ERROR_WILL_RETRY";
347
+ default:
348
+ return "UNKNOWN";
349
+ }
350
+ }
351
+ var import_semver;
352
+ var init_network = __esm({
353
+ "src/utils/network.ts"() {
354
+ "use strict";
355
+ import_semver = __toESM(require("semver"));
356
+ init_config();
357
+ init_package();
358
+ }
359
+ });
360
+
361
+ // src/context.tsx
362
+ function useBasic() {
363
+ return (0, import_react.useContext)(BasicContext);
364
+ }
365
+ var import_react, DBStatus, noDb, BasicContext;
366
+ var init_context = __esm({
367
+ "src/context.tsx"() {
368
+ "use strict";
369
+ import_react = require("react");
370
+ DBStatus = /* @__PURE__ */ ((DBStatus2) => {
371
+ DBStatus2["LOADING"] = "LOADING";
372
+ DBStatus2["OFFLINE"] = "OFFLINE";
373
+ DBStatus2["CONNECTING"] = "CONNECTING";
374
+ DBStatus2["ONLINE"] = "ONLINE";
375
+ DBStatus2["SYNCING"] = "SYNCING";
376
+ DBStatus2["ERROR"] = "ERROR";
377
+ DBStatus2["ERROR_WILL_RETRY"] = "ERROR_WILL_RETRY";
378
+ DBStatus2["ERROR_TOKEN_EXPIRED"] = "ERROR_TOKEN_EXPIRED";
379
+ return DBStatus2;
380
+ })(DBStatus || {});
381
+ noDb = {
382
+ collection: () => {
383
+ throw new Error("no basicdb found - initialization failed. double check your schema.");
384
+ }
385
+ };
386
+ BasicContext = (0, import_react.createContext)({
387
+ isReady: false,
388
+ isSignedIn: false,
389
+ user: null,
390
+ did: null,
391
+ scope: null,
392
+ hasScope: () => false,
393
+ missingScopes: () => [],
394
+ signIn: () => Promise.resolve(),
395
+ signInWithHandle: () => Promise.resolve(),
396
+ signOut: () => Promise.resolve(),
397
+ signInWithCode: () => Promise.resolve({ success: false }),
398
+ getToken: (_options) => Promise.reject(new Error("no token")),
399
+ getSignInUrl: () => Promise.resolve(""),
400
+ db: noDb,
401
+ dbStatus: "LOADING" /* LOADING */,
402
+ dbMode: "sync",
403
+ devInfo: null,
404
+ refreshSchemaStatus: async () => {
405
+ },
406
+ isAuthReady: false,
407
+ signin: () => Promise.resolve(),
408
+ signout: () => Promise.resolve(),
409
+ signinWithCode: () => Promise.resolve({ success: false }),
410
+ getSignInLink: () => Promise.resolve("")
411
+ });
412
+ }
413
+ });
414
+
415
+ // src/dev/BasicDevToolbar.tsx
416
+ var BasicDevToolbar_exports = {};
417
+ __export(BasicDevToolbar_exports, {
418
+ BasicDevToolbar: () => BasicDevToolbar
419
+ });
420
+ function toneForAuth(isReady, isSignedIn) {
421
+ if (!isReady) return "muted";
422
+ if (isSignedIn) return "ok";
423
+ return "warn";
424
+ }
425
+ function toneForDb(dbMode, dbStatus) {
426
+ if (dbMode === "remote") return dbStatus === "ONLINE" /* ONLINE */ ? "ok" : "warn";
427
+ if (dbStatus === "ONLINE" /* ONLINE */ || dbStatus === "SYNCING" /* SYNCING */) return "ok";
428
+ if (dbStatus === "CONNECTING" /* CONNECTING */ || dbStatus === "LOADING" /* LOADING */) return "warn";
429
+ if (dbStatus === "OFFLINE" /* OFFLINE */) return "muted";
430
+ return "bad";
431
+ }
432
+ function toneForSchema(info) {
433
+ if (!info) return "muted";
434
+ if (info.valid && info.status === "current") return "ok";
435
+ if (info.status === "unpublished") return "warn";
436
+ if (info.status === "no_schema") return "muted";
437
+ return "bad";
438
+ }
439
+ function dbStatusLabel(status) {
440
+ switch (status) {
441
+ case "LOADING" /* LOADING */:
442
+ return "Initializing";
443
+ case "OFFLINE" /* OFFLINE */:
444
+ return "Offline";
445
+ case "CONNECTING" /* CONNECTING */:
446
+ return "Connecting";
447
+ case "ONLINE" /* ONLINE */:
448
+ return "Connected";
449
+ case "SYNCING" /* SYNCING */:
450
+ return "Syncing";
451
+ case "ERROR" /* ERROR */:
452
+ return "Error";
453
+ case "ERROR_WILL_RETRY" /* ERROR_WILL_RETRY */:
454
+ return "Retrying";
455
+ case "ERROR_TOKEN_EXPIRED" /* ERROR_TOKEN_EXPIRED */:
456
+ return "Token refresh";
457
+ default:
458
+ return String(status);
459
+ }
460
+ }
461
+ function chipColor(tone) {
462
+ switch (tone) {
463
+ case "ok":
464
+ return "#22c55e";
465
+ case "warn":
466
+ return "#eab308";
467
+ case "bad":
468
+ return "#ef4444";
469
+ default:
470
+ return "#71717a";
471
+ }
472
+ }
473
+ function displayDid(did) {
474
+ return did || "\u2014";
475
+ }
476
+ function displayUserLine(user) {
477
+ const parts = [];
478
+ if (user.sub) parts.push(`sub: ${user.sub}`);
479
+ if (user.email) parts.push(`email: ${user.email}`);
480
+ if (user.name) parts.push(`name: ${user.name}`);
481
+ return parts.length ? parts.join(" \xB7 ") : "\u2014";
482
+ }
483
+ function ClipboardIcon() {
484
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
485
+ "svg",
486
+ {
487
+ width: "14",
488
+ height: "14",
489
+ viewBox: "0 0 24 24",
490
+ fill: "none",
491
+ stroke: "currentColor",
492
+ strokeWidth: "2",
493
+ strokeLinecap: "round",
494
+ strokeLinejoin: "round",
495
+ "aria-hidden": true,
496
+ children: [
497
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
498
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
499
+ ]
500
+ }
501
+ );
502
+ }
503
+ function SectionHeader({ children }) {
504
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
505
+ "div",
506
+ {
507
+ style: {
508
+ fontSize: 10,
509
+ fontWeight: 700,
510
+ color: "#e4e4e7",
511
+ letterSpacing: "0.07em",
512
+ textTransform: "uppercase",
513
+ marginBottom: 8
514
+ },
515
+ children
516
+ }
517
+ );
518
+ }
519
+ function SectionRule() {
520
+ const bleed = PANEL_PAD_X;
521
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
522
+ "div",
523
+ {
524
+ role: "separator",
525
+ style: {
526
+ height: 1,
527
+ background: "rgba(255, 255, 255, 0.055)",
528
+ marginLeft: -bleed,
529
+ marginRight: -bleed,
530
+ marginTop: 14,
531
+ marginBottom: 10,
532
+ width: `calc(100% + ${bleed * 2}px)`
533
+ }
534
+ }
535
+ );
536
+ }
537
+ function CopyableRow({
538
+ rowKey,
539
+ label,
540
+ copyText,
541
+ copiedKey,
542
+ onCopied,
543
+ children
544
+ }) {
545
+ const [hover, setHover] = (0, import_react2.useState)(false);
546
+ const canCopy = copyText.length > 0;
547
+ const handleClick = (0, import_react2.useCallback)(
548
+ (e) => {
549
+ e.stopPropagation();
550
+ if (!canCopy) return;
551
+ void navigator.clipboard.writeText(copyText).then(() => onCopied(rowKey));
552
+ },
553
+ [canCopy, copyText, onCopied, rowKey]
554
+ );
555
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
556
+ "div",
557
+ {
558
+ role: canCopy ? "button" : void 0,
559
+ tabIndex: canCopy ? 0 : void 0,
560
+ onClick: canCopy ? handleClick : void 0,
561
+ onKeyDown: canCopy ? (e) => {
562
+ if (e.key === "Enter" || e.key === " ") {
563
+ e.preventDefault();
564
+ handleClick(e);
565
+ }
566
+ } : void 0,
567
+ onMouseEnter: () => setHover(true),
568
+ onMouseLeave: () => setHover(false),
569
+ style: {
570
+ display: "flex",
571
+ gap: 8,
572
+ marginBottom: 6,
573
+ alignItems: "flex-start",
574
+ borderRadius: 6,
575
+ padding: "4px 6px",
576
+ marginLeft: -6,
577
+ marginRight: -6,
578
+ cursor: canCopy ? "pointer" : "default",
579
+ background: hover && canCopy ? "rgba(255,255,255,0.06)" : "transparent",
580
+ transition: "background 0.12s ease"
581
+ },
582
+ children: [
583
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#a1a1aa", minWidth: 88, flexShrink: 0, paddingTop: 2 }, children: label }),
584
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
585
+ "span",
586
+ {
587
+ style: {
588
+ flex: 1,
589
+ minWidth: 0,
590
+ wordBreak: "break-all",
591
+ paddingTop: 2,
592
+ lineHeight: 1.35
593
+ },
594
+ children
595
+ }
596
+ ),
597
+ canCopy && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
598
+ "span",
599
+ {
600
+ style: {
601
+ flexShrink: 0,
602
+ color: copiedKey === rowKey ? "#22c55e" : "#71717a",
603
+ opacity: hover || copiedKey === rowKey ? 1 : 0,
604
+ transition: "opacity 0.12s ease, color 0.12s ease",
605
+ paddingTop: 2,
606
+ display: "flex",
607
+ alignItems: "flex-start"
608
+ },
609
+ title: "Copy value",
610
+ children: copiedKey === rowKey ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 10 }, children: "\u2713" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ClipboardIcon, {})
611
+ }
612
+ )
613
+ ]
614
+ }
615
+ );
616
+ }
617
+ function BasicDevToolbar({ enabled = true, debug }) {
618
+ const {
619
+ isReady,
620
+ isSignedIn,
621
+ user,
622
+ did,
623
+ scope,
624
+ missingScopes,
625
+ dbMode,
626
+ dbStatus,
627
+ devInfo,
628
+ refreshSchemaStatus
629
+ } = useBasic();
630
+ const [open, setOpen] = (0, import_react2.useState)(false);
631
+ const [refreshing, setRefreshing] = (0, import_react2.useState)(false);
632
+ const [copied, setCopied] = (0, import_react2.useState)(false);
633
+ const [rowCopied, setRowCopied] = (0, import_react2.useState)(null);
634
+ const show = enabled && typeof window !== "undefined" && isDevelopment(debug);
635
+ const authTone = toneForAuth(isReady, isSignedIn);
636
+ const dbTone = toneForDb(dbMode, dbStatus);
637
+ const schemaTone = toneForSchema(devInfo);
638
+ const syncTone = dbMode === "remote" ? "muted" : dbTone === "ok" || dbStatus === "SYNCING" /* SYNCING */ ? "ok" : dbTone === "warn" ? "warn" : dbTone === "bad" ? "bad" : "muted";
639
+ const handleRefreshSchema = (0, import_react2.useCallback)(async () => {
640
+ setRefreshing(true);
641
+ try {
642
+ await refreshSchemaStatus();
643
+ } finally {
644
+ setRefreshing(false);
645
+ }
646
+ }, [refreshSchemaStatus]);
647
+ const missingList = missingScopes();
648
+ const debugPayload = (0, import_react2.useMemo)(() => {
649
+ return {
650
+ sdkVersion: version,
651
+ isReady,
652
+ isSignedIn,
653
+ did: did ?? null,
654
+ user: user ? {
655
+ sub: user.sub,
656
+ email: user.email,
657
+ name: user.name,
658
+ picture: user.picture
659
+ } : null,
660
+ scope,
661
+ missingScopes: missingList,
662
+ dbMode,
663
+ dbStatus,
664
+ indexedDbName: dbMode === "sync" ? INDEXED_DB_NAME : null,
665
+ schema: devInfo
666
+ };
667
+ }, [isReady, isSignedIn, did, user, scope, dbMode, dbStatus, devInfo, missingList]);
668
+ const handleCopy = (0, import_react2.useCallback)(async () => {
669
+ try {
670
+ await navigator.clipboard.writeText(JSON.stringify(debugPayload, null, 2));
671
+ setCopied(true);
672
+ setTimeout(() => setCopied(false), 2e3);
673
+ } catch {
674
+ }
675
+ }, [debugPayload]);
676
+ const onRowCopied = (0, import_react2.useCallback)((key) => {
677
+ setRowCopied(key);
678
+ setTimeout(() => setRowCopied((k) => k === key ? null : k), 1500);
679
+ }, []);
680
+ if (!show) return null;
681
+ const shell = {
682
+ position: "fixed",
683
+ bottom: 12,
684
+ left: "50%",
685
+ transform: "translateX(-50%)",
686
+ zIndex: 99999,
687
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
688
+ fontSize: 11,
689
+ color: "#e4e4e7",
690
+ pointerEvents: "auto"
691
+ };
692
+ const bar = {
693
+ display: "flex",
694
+ alignItems: "center",
695
+ gap: 8,
696
+ padding: "8px 12px",
697
+ borderRadius: 999,
698
+ background: "rgba(24, 24, 27, 0.92)",
699
+ border: "1px solid rgba(63, 63, 70, 0.9)",
700
+ boxShadow: "0 8px 32px rgba(0,0,0,0.35)",
701
+ cursor: "pointer",
702
+ userSelect: "none"
703
+ };
704
+ const dot = (tone) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
705
+ "span",
706
+ {
707
+ style: {
708
+ display: "block",
709
+ boxSizing: "border-box",
710
+ width: 6,
711
+ height: 6,
712
+ minWidth: 6,
713
+ minHeight: 6,
714
+ maxWidth: 6,
715
+ maxHeight: 6,
716
+ borderRadius: "50%",
717
+ background: chipColor(tone),
718
+ flexShrink: 0
719
+ }
720
+ }
721
+ );
722
+ const dotSlot = (title, tone) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
723
+ "span",
724
+ {
725
+ title,
726
+ style: {
727
+ display: "inline-flex",
728
+ alignItems: "center",
729
+ justifyContent: "center",
730
+ width: 6,
731
+ height: 6,
732
+ flexShrink: 0,
733
+ lineHeight: 0
734
+ },
735
+ children: dot(tone)
736
+ }
737
+ );
738
+ const panel = {
739
+ marginBottom: 8,
740
+ maxHeight: "50vh",
741
+ overflow: "auto",
742
+ padding: PANEL_PAD_X,
743
+ borderRadius: 10,
744
+ background: "rgba(24, 24, 27, 0.96)",
745
+ border: "1px solid rgba(63, 63, 70, 0.9)",
746
+ boxShadow: "0 8px 32px rgba(0,0,0,0.35)",
747
+ minWidth: 300,
748
+ maxWidth: "min(560px, calc(100vw - 24px))"
749
+ };
750
+ const syncStatusText = dbStatusLabel(dbStatus);
751
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: shell, children: [
752
+ open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: panel, children: [
753
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: 12 }, children: [
754
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 600, fontSize: 12 }, children: "Basic SDK" }),
755
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { color: "#71717a", fontSize: 10, marginTop: 2 }, children: [
756
+ "v",
757
+ version
758
+ ] })
759
+ ] }),
760
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionHeader, { children: "Auth" }),
761
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
762
+ CopyableRow,
763
+ {
764
+ rowKey: "ready",
765
+ label: "Ready",
766
+ copyText: String(isReady),
767
+ copiedKey: rowCopied,
768
+ onCopied: onRowCopied,
769
+ children: String(isReady)
770
+ }
771
+ ),
772
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
773
+ CopyableRow,
774
+ {
775
+ rowKey: "signedIn",
776
+ label: "Signed in",
777
+ copyText: String(isSignedIn),
778
+ copiedKey: rowCopied,
779
+ onCopied: onRowCopied,
780
+ children: String(isSignedIn)
781
+ }
782
+ ),
783
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
784
+ CopyableRow,
785
+ {
786
+ rowKey: "did",
787
+ label: "DID",
788
+ copyText: did || "",
789
+ copiedKey: rowCopied,
790
+ onCopied: onRowCopied,
791
+ children: displayDid(did)
792
+ }
793
+ ),
794
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
795
+ CopyableRow,
796
+ {
797
+ rowKey: "user",
798
+ label: "User",
799
+ copyText: user ? displayUserLine(user) : "",
800
+ copiedKey: rowCopied,
801
+ onCopied: onRowCopied,
802
+ children: user ? displayUserLine(user) : "\u2014"
803
+ }
804
+ ),
805
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
806
+ CopyableRow,
807
+ {
808
+ rowKey: "scopes",
809
+ label: "Scopes",
810
+ copyText: scope || "",
811
+ copiedKey: rowCopied,
812
+ onCopied: onRowCopied,
813
+ children: scope || "\u2014"
814
+ }
815
+ ),
816
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
817
+ CopyableRow,
818
+ {
819
+ rowKey: "missingScopes",
820
+ label: "Missing scopes",
821
+ copyText: missingList.length ? missingList.join(", ") : "",
822
+ copiedKey: rowCopied,
823
+ onCopied: onRowCopied,
824
+ children: missingList.length ? missingList.join(", ") : "\u2014"
825
+ }
826
+ ),
827
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionRule, {}),
828
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionHeader, { children: "Database" }),
829
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
830
+ CopyableRow,
831
+ {
832
+ rowKey: "dbMode",
833
+ label: "Mode",
834
+ copyText: dbMode,
835
+ copiedKey: rowCopied,
836
+ onCopied: onRowCopied,
837
+ children: dbMode
838
+ }
839
+ ),
840
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
841
+ CopyableRow,
842
+ {
843
+ rowKey: "indexedDb",
844
+ label: "IndexedDB",
845
+ copyText: dbMode === "sync" ? INDEXED_DB_NAME : "",
846
+ copiedKey: rowCopied,
847
+ onCopied: onRowCopied,
848
+ children: dbMode === "sync" ? INDEXED_DB_NAME : "\u2014"
849
+ }
850
+ ),
851
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
852
+ CopyableRow,
853
+ {
854
+ rowKey: "syncStatus",
855
+ label: "Sync / status",
856
+ copyText: syncStatusText,
857
+ copiedKey: rowCopied,
858
+ onCopied: onRowCopied,
859
+ children: syncStatusText
860
+ }
861
+ ),
862
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionRule, {}),
863
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionHeader, { children: "Schema" }),
864
+ devInfo ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
865
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
866
+ CopyableRow,
867
+ {
868
+ rowKey: "schemaProject",
869
+ label: "Project",
870
+ copyText: devInfo.projectId ?? "",
871
+ copiedKey: rowCopied,
872
+ onCopied: onRowCopied,
873
+ children: devInfo.projectId ?? "\u2014"
874
+ }
875
+ ),
876
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
877
+ CopyableRow,
878
+ {
879
+ rowKey: "schemaLocalVer",
880
+ label: "Local version",
881
+ copyText: devInfo.localVersion !== void 0 && devInfo.localVersion !== null ? String(devInfo.localVersion) : "",
882
+ copiedKey: rowCopied,
883
+ onCopied: onRowCopied,
884
+ children: devInfo.localVersion ?? "\u2014"
885
+ }
886
+ ),
887
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
888
+ CopyableRow,
889
+ {
890
+ rowKey: "schemaRemote",
891
+ label: "Remote check",
892
+ copyText: devInfo.status,
893
+ copiedKey: rowCopied,
894
+ onCopied: onRowCopied,
895
+ children: devInfo.status
896
+ }
897
+ ),
898
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
899
+ CopyableRow,
900
+ {
901
+ rowKey: "schemaValid",
902
+ label: "Valid",
903
+ copyText: String(devInfo.valid),
904
+ copiedKey: rowCopied,
905
+ onCopied: onRowCopied,
906
+ children: String(devInfo.valid)
907
+ }
908
+ ),
909
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
910
+ CopyableRow,
911
+ {
912
+ rowKey: "schemaChecked",
913
+ label: "Checked",
914
+ copyText: devInfo.lastCheckedAt ? new Date(devInfo.lastCheckedAt).toISOString() : "",
915
+ copiedKey: rowCopied,
916
+ onCopied: onRowCopied,
917
+ children: devInfo.lastCheckedAt ? new Date(devInfo.lastCheckedAt).toLocaleString() : "\u2014"
918
+ }
919
+ ),
920
+ devInfo.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
921
+ CopyableRow,
922
+ {
923
+ rowKey: "schemaError",
924
+ label: "Error",
925
+ copyText: devInfo.error,
926
+ copiedKey: rowCopied,
927
+ onCopied: onRowCopied,
928
+ children: devInfo.error
929
+ }
930
+ ) : null
931
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
932
+ CopyableRow,
933
+ {
934
+ rowKey: "schemaStatus",
935
+ label: "Status",
936
+ copyText: "No schema on provider",
937
+ copiedKey: rowCopied,
938
+ onCopied: onRowCopied,
939
+ children: "No schema on provider"
940
+ }
941
+ ),
942
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8, marginTop: 12, flexWrap: "wrap" }, children: [
943
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
944
+ "button",
945
+ {
946
+ type: "button",
947
+ onClick: (e) => {
948
+ e.stopPropagation();
949
+ void handleRefreshSchema();
950
+ },
951
+ disabled: refreshing,
952
+ style: {
953
+ padding: "6px 10px",
954
+ borderRadius: 6,
955
+ border: "1px solid #3f3f46",
956
+ background: "#27272a",
957
+ color: "#e4e4e7",
958
+ cursor: refreshing ? "wait" : "pointer",
959
+ fontSize: 11,
960
+ fontFamily: "inherit"
961
+ },
962
+ children: refreshing ? "Refreshing\u2026" : "Refresh schema"
963
+ }
964
+ ),
965
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
966
+ "button",
967
+ {
968
+ type: "button",
969
+ onClick: (e) => {
970
+ e.stopPropagation();
971
+ void handleCopy();
972
+ },
973
+ style: {
974
+ padding: "6px 10px",
975
+ borderRadius: 6,
976
+ border: "1px solid #3f3f46",
977
+ background: "#27272a",
978
+ color: "#e4e4e7",
979
+ cursor: "pointer",
980
+ fontSize: 11,
981
+ fontFamily: "inherit"
982
+ },
983
+ children: copied ? "Copied" : "Copy debug info"
984
+ }
985
+ )
986
+ ] })
987
+ ] }),
988
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
989
+ "button",
990
+ {
991
+ type: "button",
992
+ "aria-expanded": open,
993
+ onClick: () => setOpen((o) => !o),
994
+ style: {
995
+ ...bar,
996
+ border: "none",
997
+ width: "100%",
998
+ cursor: "pointer"
999
+ },
1000
+ children: [
1001
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontWeight: 600, letterSpacing: 0.02 }, children: "Basic" }),
1002
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1003
+ "span",
1004
+ {
1005
+ style: {
1006
+ display: "inline-flex",
1007
+ alignItems: "center",
1008
+ gap: 6,
1009
+ marginLeft: 8,
1010
+ height: 6,
1011
+ flexShrink: 0,
1012
+ lineHeight: 0
1013
+ },
1014
+ children: [
1015
+ dotSlot("Auth", authTone),
1016
+ dotSlot("DB", dbTone),
1017
+ dotSlot("Sync", syncTone),
1018
+ dotSlot("Schema", schemaTone)
1019
+ ]
1020
+ }
1021
+ ),
1022
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#71717a", marginLeft: 4 }, children: open ? "\u25BE" : "\u25B4" })
1023
+ ]
1024
+ }
1025
+ )
1026
+ ] });
1027
+ }
1028
+ var import_react2, import_jsx_runtime, INDEXED_DB_NAME, PANEL_PAD_X;
1029
+ var init_BasicDevToolbar = __esm({
1030
+ "src/dev/BasicDevToolbar.tsx"() {
1031
+ "use strict";
1032
+ "use client";
1033
+ import_react2 = require("react");
1034
+ init_context();
1035
+ init_package();
1036
+ init_network();
1037
+ import_jsx_runtime = require("react/jsx-runtime");
1038
+ INDEXED_DB_NAME = "basicdb";
1039
+ PANEL_PAD_X = 12;
1040
+ }
1041
+ });
1042
+
241
1043
  // src/index.ts
242
1044
  var index_exports = {};
243
1045
  __export(index_exports, {
1046
+ BasicDevToolbar: () => BasicDevToolbar,
244
1047
  BasicProvider: () => BasicProvider,
245
1048
  DBStatus: () => DBStatus,
246
1049
  NotAuthenticatedError: () => NotAuthenticatedError,
@@ -257,7 +1060,7 @@ __export(index_exports, {
257
1060
  module.exports = __toCommonJS(index_exports);
258
1061
 
259
1062
  // src/AuthContext.tsx
260
- var import_react = require("react");
1063
+ var import_react3 = require("react");
261
1064
 
262
1065
  // src/sync/index.ts
263
1066
  var import_uuid = require("uuid");
@@ -848,75 +1651,8 @@ async function resolveHandle(handle) {
848
1651
  return resolved;
849
1652
  }
850
1653
 
851
- // src/utils/network.ts
852
- init_config();
853
-
854
- // package.json
855
- var version = "0.8.0-beta.1";
856
-
857
- // src/utils/network.ts
858
- function isDevelopment(debug) {
859
- return window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" || window.location.hostname.includes("localhost") || window.location.hostname.includes("127.0.0.1") || window.location.hostname.includes(".local") || process.env.NODE_ENV === "development" || debug === true;
860
- }
861
- async function checkForNewVersion() {
862
- try {
863
- const isBeta = version.includes("beta");
864
- const response = await fetch(`https://registry.npmjs.org/@basictech/react/${isBeta ? "beta" : "latest"}`);
865
- if (!response.ok) {
866
- throw new Error("Failed to fetch version from npm");
867
- }
868
- const data = await response.json();
869
- const latestVersion = data.version;
870
- if (latestVersion !== version) {
871
- console.warn("[basic] New version available:", latestVersion, `
872
- run "npm install @basictech/react@${latestVersion}" to update`);
873
- }
874
- if (isBeta) {
875
- log("thank you for being on basictech/react beta :)");
876
- }
877
- return {
878
- hasNewVersion: version !== latestVersion,
879
- latestVersion,
880
- currentVersion: version
881
- };
882
- } catch (error) {
883
- log("Error checking for new version:", error);
884
- return {
885
- hasNewVersion: false,
886
- latestVersion: null,
887
- currentVersion: null
888
- };
889
- }
890
- }
891
- function cleanOAuthParamsFromUrl() {
892
- if (window.location.search.includes("code") || window.location.search.includes("state")) {
893
- const url = new URL(window.location.href);
894
- url.searchParams.delete("code");
895
- url.searchParams.delete("state");
896
- window.history.pushState({}, document.title, url.pathname + url.search);
897
- log("Cleaned OAuth parameters from URL");
898
- }
899
- }
900
- function getSyncStatus(statusCode) {
901
- switch (statusCode) {
902
- case -1:
903
- return "ERROR";
904
- case 0:
905
- return "OFFLINE";
906
- case 1:
907
- return "CONNECTING";
908
- case 2:
909
- return "ONLINE";
910
- case 3:
911
- return "SYNCING";
912
- case 4:
913
- return "ERROR_WILL_RETRY";
914
- default:
915
- return "UNKNOWN";
916
- }
917
- }
918
-
919
1654
  // src/core/auth/AuthManager.ts
1655
+ init_network();
920
1656
  init_config();
921
1657
  function generateCodeVerifier() {
922
1658
  const array = new Uint8Array(32);
@@ -1617,6 +2353,7 @@ var AuthManager = class {
1617
2353
 
1618
2354
  // src/AuthContext.tsx
1619
2355
  init_config();
2356
+ init_package();
1620
2357
 
1621
2358
  // src/updater/versionUpdater.ts
1622
2359
  init_config();
@@ -1741,6 +2478,9 @@ function getMigrations() {
1741
2478
  ];
1742
2479
  }
1743
2480
 
2481
+ // src/AuthContext.tsx
2482
+ init_network();
2483
+
1744
2484
  // src/utils/schema.ts
1745
2485
  var import_schema3 = require("@basictech/schema");
1746
2486
  init_config();
@@ -1840,57 +2580,18 @@ async function validateAndCheckSchema(schema) {
1840
2580
  }
1841
2581
 
1842
2582
  // src/AuthContext.tsx
1843
- var import_jsx_runtime = require("react/jsx-runtime");
2583
+ init_context();
2584
+ init_context();
2585
+ var import_jsx_runtime2 = require("react/jsx-runtime");
2586
+ var BasicDevToolbar2 = (0, import_react3.lazy)(
2587
+ () => Promise.resolve().then(() => (init_BasicDevToolbar(), BasicDevToolbar_exports)).then((m) => ({ default: m.BasicDevToolbar }))
2588
+ );
1844
2589
  var DEFAULT_AUTH_CONFIG = {
1845
2590
  scopes: "profile,email,app:admin",
1846
2591
  pds_url: "https://pds.basic.id",
1847
2592
  admin_url: "https://api.basic.tech",
1848
2593
  ws_url: "wss://pds.basic.id/ws"
1849
2594
  };
1850
- var DBStatus = /* @__PURE__ */ ((DBStatus2) => {
1851
- DBStatus2["LOADING"] = "LOADING";
1852
- DBStatus2["OFFLINE"] = "OFFLINE";
1853
- DBStatus2["CONNECTING"] = "CONNECTING";
1854
- DBStatus2["ONLINE"] = "ONLINE";
1855
- DBStatus2["SYNCING"] = "SYNCING";
1856
- DBStatus2["ERROR"] = "ERROR";
1857
- DBStatus2["ERROR_WILL_RETRY"] = "ERROR_WILL_RETRY";
1858
- DBStatus2["ERROR_TOKEN_EXPIRED"] = "ERROR_TOKEN_EXPIRED";
1859
- return DBStatus2;
1860
- })(DBStatus || {});
1861
- var noDb = {
1862
- collection: () => {
1863
- throw new Error("no basicdb found - initialization failed. double check your schema.");
1864
- }
1865
- };
1866
- var BasicContext = (0, import_react.createContext)({
1867
- // Auth state
1868
- isReady: false,
1869
- isSignedIn: false,
1870
- user: null,
1871
- did: null,
1872
- scope: null,
1873
- hasScope: () => false,
1874
- missingScopes: () => [],
1875
- // Auth actions
1876
- signIn: () => Promise.resolve(),
1877
- signInWithHandle: () => Promise.resolve(),
1878
- signOut: () => Promise.resolve(),
1879
- signInWithCode: () => Promise.resolve({ success: false }),
1880
- // Token management
1881
- getToken: (_options) => Promise.reject(new Error("no token")),
1882
- getSignInUrl: () => Promise.resolve(""),
1883
- // DB access
1884
- db: noDb,
1885
- dbStatus: "LOADING" /* LOADING */,
1886
- dbMode: "sync",
1887
- // Legacy aliases
1888
- isAuthReady: false,
1889
- signin: () => Promise.resolve(),
1890
- signout: () => Promise.resolve(),
1891
- signinWithCode: () => Promise.resolve({ success: false }),
1892
- getSignInLink: () => Promise.resolve("")
1893
- });
1894
2595
  function snapshotAuth(mgr) {
1895
2596
  return {
1896
2597
  isSignedIn: mgr.isSignedIn,
@@ -1908,7 +2609,8 @@ function BasicProvider({
1908
2609
  debug = false,
1909
2610
  storage,
1910
2611
  auth,
1911
- dbMode = "sync"
2612
+ dbMode = "sync",
2613
+ devToolbar = false
1912
2614
  }) {
1913
2615
  const project_id = schema?.project_id || project_id_prop;
1914
2616
  if (auth?.server_url && !auth?.pds_url) {
@@ -1921,9 +2623,11 @@ function BasicProvider({
1921
2623
  ws_url: auth?.ws_url || DEFAULT_AUTH_CONFIG.ws_url
1922
2624
  };
1923
2625
  const scopesString = Array.isArray(authConfig.scopes) ? authConfig.scopes.join(" ") : authConfig.scopes;
1924
- const storageRef = (0, import_react.useRef)(storage || new LocalStorageAdapter());
2626
+ const storageRef = (0, import_react3.useRef)(storage || new LocalStorageAdapter());
1925
2627
  const storageAdapter = storageRef.current;
1926
- const [authState, setAuthState] = (0, import_react.useState)({
2628
+ const schemaRef = (0, import_react3.useRef)(schema);
2629
+ schemaRef.current = schema;
2630
+ const [authState, setAuthState] = (0, import_react3.useState)({
1927
2631
  isSignedIn: false,
1928
2632
  hasToken: false,
1929
2633
  isAuthReady: false,
@@ -1931,7 +2635,7 @@ function BasicProvider({
1931
2635
  did: null,
1932
2636
  tokenScope: null
1933
2637
  });
1934
- const authRef = (0, import_react.useRef)(null);
2638
+ const authRef = (0, import_react3.useRef)(null);
1935
2639
  if (!authRef.current) {
1936
2640
  authRef.current = new AuthManager(
1937
2641
  {
@@ -1945,14 +2649,50 @@ function BasicProvider({
1945
2649
  () => setAuthState(snapshotAuth(authRef.current))
1946
2650
  );
1947
2651
  }
1948
- const syncRef = (0, import_react.useRef)(null);
1949
- const remoteDbRef = (0, import_react.useRef)(null);
1950
- const [shouldConnect, setShouldConnect] = (0, import_react.useState)(false);
1951
- const [dbStatus, setDbStatus] = (0, import_react.useState)("OFFLINE" /* OFFLINE */);
1952
- const [isReady, setIsReady] = (0, import_react.useState)(false);
1953
- const [error, setError] = (0, import_react.useState)(null);
2652
+ const syncRef = (0, import_react3.useRef)(null);
2653
+ const remoteDbRef = (0, import_react3.useRef)(null);
2654
+ const [shouldConnect, setShouldConnect] = (0, import_react3.useState)(false);
2655
+ const [dbStatus, setDbStatus] = (0, import_react3.useState)("OFFLINE" /* OFFLINE */);
2656
+ const [isReady, setIsReady] = (0, import_react3.useState)(false);
2657
+ const [error, setError] = (0, import_react3.useState)(null);
2658
+ const [schemaDevInfo, setSchemaDevInfo] = (0, import_react3.useState)(null);
1954
2659
  const isDevMode = () => isDevelopment(debug);
1955
- (0, import_react.useEffect)(() => {
2660
+ const refreshSchemaStatus = (0, import_react3.useCallback)(async () => {
2661
+ const s = schemaRef.current;
2662
+ if (!s) {
2663
+ setSchemaDevInfo(
2664
+ project_id ? {
2665
+ projectId: project_id,
2666
+ localVersion: void 0,
2667
+ status: "no_schema",
2668
+ valid: false,
2669
+ lastCheckedAt: Date.now()
2670
+ } : null
2671
+ );
2672
+ return;
2673
+ }
2674
+ const result = await validateAndCheckSchema(s);
2675
+ if (!result.isValid) {
2676
+ const errText = result.errors?.map((e) => e.message || "").join("; ") || "invalid";
2677
+ setSchemaDevInfo({
2678
+ projectId: s.project_id ?? null,
2679
+ localVersion: s.version,
2680
+ status: "invalid",
2681
+ valid: false,
2682
+ lastCheckedAt: Date.now(),
2683
+ error: errText
2684
+ });
2685
+ return;
2686
+ }
2687
+ setSchemaDevInfo({
2688
+ projectId: s.project_id ?? null,
2689
+ localVersion: s.version,
2690
+ status: result.schemaStatus.status ?? "unknown",
2691
+ valid: result.schemaStatus.valid,
2692
+ lastCheckedAt: Date.now()
2693
+ });
2694
+ }, [project_id]);
2695
+ (0, import_react3.useEffect)(() => {
1956
2696
  const runVersionUpdater = async () => {
1957
2697
  try {
1958
2698
  const versionUpdater = createVersionUpdater(storageAdapter, version, getMigrations());
@@ -1970,7 +2710,7 @@ function BasicProvider({
1970
2710
  authRef.current.initialize();
1971
2711
  return authRef.current.setupNetworkListeners();
1972
2712
  }, []);
1973
- (0, import_react.useEffect)(() => {
2713
+ (0, import_react3.useEffect)(() => {
1974
2714
  async function initSyncDb(options) {
1975
2715
  if (!syncRef.current) {
1976
2716
  log("Initializing Basic Sync DB");
@@ -2025,11 +2765,19 @@ function BasicProvider({
2025
2765
  if (!result.isValid) {
2026
2766
  let errorMessage = "";
2027
2767
  if (result.errors) {
2028
- result.errors.forEach((error2, index) => {
2029
- errorMessage += `${index + 1}: ${error2.message} - at ${error2.instancePath}
2768
+ result.errors.forEach((err, index) => {
2769
+ errorMessage += `${index + 1}: ${err.message} - at ${err.instancePath}
2030
2770
  `;
2031
2771
  });
2032
2772
  }
2773
+ setSchemaDevInfo({
2774
+ projectId: schema?.project_id ?? null,
2775
+ localVersion: schema?.version,
2776
+ status: "invalid",
2777
+ valid: false,
2778
+ lastCheckedAt: Date.now(),
2779
+ error: errorMessage.trim() || void 0
2780
+ });
2033
2781
  setError({
2034
2782
  code: "schema_invalid",
2035
2783
  title: "Basic Schema is invalid!",
@@ -2038,6 +2786,13 @@ function BasicProvider({
2038
2786
  setIsReady(true);
2039
2787
  return null;
2040
2788
  }
2789
+ setSchemaDevInfo({
2790
+ projectId: schema?.project_id ?? null,
2791
+ localVersion: schema?.version,
2792
+ status: result.schemaStatus.status ?? "unknown",
2793
+ valid: result.schemaStatus.valid,
2794
+ lastCheckedAt: Date.now()
2795
+ });
2041
2796
  if (dbMode === "remote") {
2042
2797
  initRemoteDb();
2043
2798
  } else {
@@ -2057,6 +2812,15 @@ function BasicProvider({
2057
2812
  if (schema) {
2058
2813
  checkSchema();
2059
2814
  } else {
2815
+ setSchemaDevInfo(
2816
+ project_id ? {
2817
+ projectId: project_id,
2818
+ localVersion: void 0,
2819
+ status: "no_schema",
2820
+ valid: false,
2821
+ lastCheckedAt: Date.now()
2822
+ } : null
2823
+ );
2060
2824
  if (dbMode === "remote" && project_id) {
2061
2825
  initRemoteDb();
2062
2826
  } else {
@@ -2064,7 +2828,7 @@ function BasicProvider({
2064
2828
  }
2065
2829
  }
2066
2830
  }, []);
2067
- (0, import_react.useEffect)(() => {
2831
+ (0, import_react3.useEffect)(() => {
2068
2832
  if (authState.hasToken && syncRef.current && authState.isSignedIn && shouldConnect) {
2069
2833
  log("connecting to db...");
2070
2834
  syncRef.current?.connect({
@@ -2123,69 +2887,72 @@ function BasicProvider({
2123
2887
  return syncRef.current || noDb;
2124
2888
  };
2125
2889
  const contextValue = {
2126
- // Auth state
2127
2890
  isReady: authState.isAuthReady,
2128
2891
  isSignedIn: authState.isSignedIn,
2129
2892
  user: authState.user,
2130
2893
  did: authState.did,
2131
2894
  scope: authState.tokenScope,
2132
- hasScope: (scope) => authRef.current.hasScope(scope),
2895
+ hasScope: (s) => authRef.current.hasScope(s),
2133
2896
  missingScopes: () => authRef.current.missingScopes(),
2134
- // Auth actions
2135
2897
  signIn: handleSignIn,
2136
2898
  signInWithHandle: handleSignInWithHandle,
2137
2899
  signOut: handleSignOut,
2138
2900
  signInWithCode: (code, state) => authRef.current.signInWithCode(code, state),
2139
- // Token management
2140
2901
  getToken: (opts) => authRef.current.getToken(opts),
2141
2902
  getSignInUrl: (redirectUri) => authRef.current.getSignInUrl(redirectUri),
2142
- // DB access
2143
2903
  db: getCurrentDb(),
2144
2904
  dbStatus,
2145
2905
  dbMode,
2146
- // Legacy aliases (deprecated)
2906
+ devInfo: schemaDevInfo,
2907
+ refreshSchemaStatus,
2147
2908
  isAuthReady: authState.isAuthReady,
2148
2909
  signin: handleSignIn,
2149
2910
  signout: handleSignOut,
2150
2911
  signinWithCode: (code, state) => authRef.current.signInWithCode(code, state),
2151
2912
  getSignInLink: (redirectUri) => authRef.current.getSignInUrl(redirectUri)
2152
2913
  };
2153
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(BasicContext.Provider, { value: contextValue, children: [
2154
- error && isDevMode() && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorDisplay, { error }),
2914
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(BasicContext.Provider, { value: contextValue, children: [
2915
+ error && isDevMode() && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ErrorDisplay, { error }),
2916
+ devToolbar && isDevMode() && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react3.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BasicDevToolbar2, { debug }) }),
2155
2917
  isReady && children
2156
2918
  ] });
2157
2919
  }
2158
2920
  function ErrorDisplay({ error }) {
2159
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
2160
- position: "absolute",
2161
- top: 20,
2162
- left: 20,
2163
- color: "black",
2164
- backgroundColor: "#f8d7da",
2165
- border: "1px solid #f5c6cb",
2166
- borderRadius: "4px",
2167
- padding: "20px",
2168
- maxWidth: "400px",
2169
- margin: "20px auto",
2170
- boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)",
2171
- fontFamily: "monospace"
2172
- }, children: [
2173
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", { style: { fontSize: "0.8rem", opacity: 0.8 }, children: [
2174
- "code: ",
2175
- error.code
2176
- ] }),
2177
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { style: { fontSize: "1.2rem", lineHeight: "1.5" }, children: error.title }),
2178
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: error.message })
2179
- ] });
2180
- }
2181
- function useBasic() {
2182
- return (0, import_react.useContext)(BasicContext);
2921
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2922
+ "div",
2923
+ {
2924
+ style: {
2925
+ position: "absolute",
2926
+ top: 20,
2927
+ left: 20,
2928
+ color: "black",
2929
+ backgroundColor: "#f8d7da",
2930
+ border: "1px solid #f5c6cb",
2931
+ borderRadius: "4px",
2932
+ padding: "20px",
2933
+ maxWidth: "400px",
2934
+ margin: "20px auto",
2935
+ boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)",
2936
+ fontFamily: "monospace"
2937
+ },
2938
+ children: [
2939
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h3", { style: { fontSize: "0.8rem", opacity: 0.8 }, children: [
2940
+ "code: ",
2941
+ error.code
2942
+ ] }),
2943
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { style: { fontSize: "1.2rem", lineHeight: 1.5 }, children: error.title }),
2944
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: error.message })
2945
+ ]
2946
+ }
2947
+ );
2183
2948
  }
2184
2949
 
2185
2950
  // src/index.ts
2186
2951
  var import_dexie_react_hooks = require("dexie-react-hooks");
2952
+ init_BasicDevToolbar();
2187
2953
  // Annotate the CommonJS export names for ESM import in node:
2188
2954
  0 && (module.exports = {
2955
+ BasicDevToolbar,
2189
2956
  BasicProvider,
2190
2957
  DBStatus,
2191
2958
  NotAuthenticatedError,