@sybil-studio-devs/sdk 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +433 -146
- package/dist/atlas/index.d.mts +28 -0
- package/dist/atlas/index.d.ts +28 -0
- package/dist/atlas/index.js +418 -0
- package/dist/atlas/index.mjs +8 -0
- package/dist/chunk-B6RXZKRY.mjs +391 -0
- package/dist/chunk-MM27YV6Z.mjs +668 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1059 -0
- package/dist/index.mjs +12 -0
- package/dist/nexus/index.d.mts +34 -0
- package/dist/nexus/index.d.ts +34 -0
- package/dist/nexus/index.js +695 -0
- package/dist/nexus/index.mjs +8 -0
- package/dist/react/index.d.mts +192 -1
- package/dist/react/index.d.ts +192 -1
- package/dist/react/index.js +1826 -14
- package/dist/react/index.mjs +771 -10
- package/dist/types-BjxgQxBW.d.mts +182 -0
- package/dist/types-BjxgQxBW.d.ts +182 -0
- package/dist/types-DVY5_vpY.d.mts +258 -0
- package/dist/types-DVY5_vpY.d.ts +258 -0
- package/package.json +20 -5
package/dist/react/index.js
CHANGED
|
@@ -20,7 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/react/index.ts
|
|
21
21
|
var react_exports = {};
|
|
22
22
|
__export(react_exports, {
|
|
23
|
+
SybilAtlas: () => SybilAtlas,
|
|
24
|
+
SybilNexus: () => SybilNexus,
|
|
23
25
|
SybilPages: () => SybilPages,
|
|
26
|
+
useAtlas: () => useAtlas,
|
|
27
|
+
useNexus: () => useNexus,
|
|
24
28
|
useSybilPages: () => useSybilPages
|
|
25
29
|
});
|
|
26
30
|
module.exports = __toCommonJS(react_exports);
|
|
@@ -437,23 +441,1454 @@ var SybilPages = (0, import_react.forwardRef)(function SybilPages2({
|
|
|
437
441
|
);
|
|
438
442
|
});
|
|
439
443
|
|
|
444
|
+
// src/react/SybilAtlas.tsx
|
|
445
|
+
var import_react2 = require("react");
|
|
446
|
+
|
|
447
|
+
// src/atlas/client.ts
|
|
448
|
+
var DEFAULT_BASE_URL2 = "https://app.sybil.studio";
|
|
449
|
+
var AtlasLogger = class {
|
|
450
|
+
constructor(config) {
|
|
451
|
+
this.logs = [];
|
|
452
|
+
this.config = config;
|
|
453
|
+
}
|
|
454
|
+
log(level, category, message, data, duration) {
|
|
455
|
+
if (!this.config?.enabled) return;
|
|
456
|
+
const levels = ["debug", "info", "warn", "error"];
|
|
457
|
+
const configLevel = this.config.level || "info";
|
|
458
|
+
if (levels.indexOf(level) < levels.indexOf(configLevel)) return;
|
|
459
|
+
const entry = {
|
|
460
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
461
|
+
level,
|
|
462
|
+
category,
|
|
463
|
+
message,
|
|
464
|
+
data,
|
|
465
|
+
duration
|
|
466
|
+
};
|
|
467
|
+
this.logs.push(entry);
|
|
468
|
+
this.config.onLog?.(entry);
|
|
469
|
+
if (typeof console !== "undefined") {
|
|
470
|
+
const prefix = `[Atlas SDK] [${category}]`;
|
|
471
|
+
switch (level) {
|
|
472
|
+
case "debug":
|
|
473
|
+
console.debug(prefix, message, data || "");
|
|
474
|
+
break;
|
|
475
|
+
case "info":
|
|
476
|
+
console.info(prefix, message, data || "");
|
|
477
|
+
break;
|
|
478
|
+
case "warn":
|
|
479
|
+
console.warn(prefix, message, data || "");
|
|
480
|
+
break;
|
|
481
|
+
case "error":
|
|
482
|
+
console.error(prefix, message, data || "");
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
getLogs() {
|
|
488
|
+
return [...this.logs];
|
|
489
|
+
}
|
|
490
|
+
clearLogs() {
|
|
491
|
+
this.logs = [];
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
function embedAtlas(config) {
|
|
495
|
+
const {
|
|
496
|
+
apiKey,
|
|
497
|
+
workspaceId,
|
|
498
|
+
container,
|
|
499
|
+
baseUrl = DEFAULT_BASE_URL2,
|
|
500
|
+
theme = "dark",
|
|
501
|
+
showSidebar = true,
|
|
502
|
+
sidebarWidth = 260,
|
|
503
|
+
sidebarCollapsible = true,
|
|
504
|
+
readOnly = false,
|
|
505
|
+
defaultPageId,
|
|
506
|
+
allowCreate = true,
|
|
507
|
+
allowDelete = true,
|
|
508
|
+
allowExport = true,
|
|
509
|
+
features = {},
|
|
510
|
+
logging,
|
|
511
|
+
onReady,
|
|
512
|
+
onPageChange,
|
|
513
|
+
onPageCreate,
|
|
514
|
+
onPageDelete,
|
|
515
|
+
onPageUpdate,
|
|
516
|
+
onError,
|
|
517
|
+
onNavigate
|
|
518
|
+
} = config;
|
|
519
|
+
const logger = new AtlasLogger(logging);
|
|
520
|
+
const startTime = Date.now();
|
|
521
|
+
logger.log("info", "render", "Initializing Atlas embed", {
|
|
522
|
+
workspaceId,
|
|
523
|
+
showSidebar,
|
|
524
|
+
readOnly,
|
|
525
|
+
features
|
|
526
|
+
});
|
|
527
|
+
const containerEl = typeof container === "string" ? document.querySelector(container) : container;
|
|
528
|
+
if (!containerEl) {
|
|
529
|
+
const error = {
|
|
530
|
+
code: "CONTAINER_NOT_FOUND",
|
|
531
|
+
message: "Container element not found",
|
|
532
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
533
|
+
};
|
|
534
|
+
onError?.(error);
|
|
535
|
+
throw new Error(error.message);
|
|
536
|
+
}
|
|
537
|
+
const params = new URLSearchParams({
|
|
538
|
+
apiKey,
|
|
539
|
+
workspaceId,
|
|
540
|
+
readOnly: readOnly.toString(),
|
|
541
|
+
showSidebar: showSidebar.toString(),
|
|
542
|
+
sidebarWidth: sidebarWidth.toString(),
|
|
543
|
+
sidebarCollapsible: sidebarCollapsible.toString(),
|
|
544
|
+
allowCreate: allowCreate.toString(),
|
|
545
|
+
allowDelete: allowDelete.toString(),
|
|
546
|
+
allowExport: allowExport.toString()
|
|
547
|
+
});
|
|
548
|
+
if (defaultPageId) params.set("defaultPageId", defaultPageId);
|
|
549
|
+
if (typeof theme === "string") {
|
|
550
|
+
params.set("theme", theme);
|
|
551
|
+
} else {
|
|
552
|
+
Object.entries(theme).forEach(([key, value]) => {
|
|
553
|
+
if (value) params.set(`theme_${key}`, value);
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
Object.entries(features).forEach(([key, value]) => {
|
|
557
|
+
if (typeof value === "boolean") {
|
|
558
|
+
params.set(`feature_${key}`, value.toString());
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
const iframe = document.createElement("iframe");
|
|
562
|
+
iframe.src = `${baseUrl}/embed/atlas?${params.toString()}`;
|
|
563
|
+
iframe.style.width = "100%";
|
|
564
|
+
iframe.style.height = "100%";
|
|
565
|
+
iframe.style.border = "none";
|
|
566
|
+
iframe.style.borderRadius = "8px";
|
|
567
|
+
iframe.allow = "clipboard-write";
|
|
568
|
+
let currentPage = null;
|
|
569
|
+
let isReady = false;
|
|
570
|
+
const createError = (code, message, status) => ({
|
|
571
|
+
code,
|
|
572
|
+
message,
|
|
573
|
+
status,
|
|
574
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
575
|
+
requestId: `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
576
|
+
});
|
|
577
|
+
const apiRequest = async (endpoint, options = {}) => {
|
|
578
|
+
const requestStart = Date.now();
|
|
579
|
+
const url = `${baseUrl}/api/sdk/v1${endpoint}`;
|
|
580
|
+
logger.log("debug", "api", `Request: ${options.method || "GET"} ${endpoint}`, {
|
|
581
|
+
url,
|
|
582
|
+
method: options.method || "GET"
|
|
583
|
+
});
|
|
584
|
+
try {
|
|
585
|
+
const response = await fetch(url, {
|
|
586
|
+
...options,
|
|
587
|
+
headers: {
|
|
588
|
+
"x-api-key": apiKey,
|
|
589
|
+
"Content-Type": "application/json",
|
|
590
|
+
...options.headers
|
|
591
|
+
}
|
|
592
|
+
});
|
|
593
|
+
const duration = Date.now() - requestStart;
|
|
594
|
+
if (!response.ok) {
|
|
595
|
+
const errorData = await response.json().catch(() => ({}));
|
|
596
|
+
const error = createError(
|
|
597
|
+
errorData.error?.code || "API_ERROR",
|
|
598
|
+
errorData.error?.message || `Request failed with status ${response.status}`,
|
|
599
|
+
response.status
|
|
600
|
+
);
|
|
601
|
+
logger.log("error", "api", `Request failed: ${endpoint}`, {
|
|
602
|
+
status: response.status,
|
|
603
|
+
error: errorData
|
|
604
|
+
}, duration);
|
|
605
|
+
onError?.(error);
|
|
606
|
+
throw error;
|
|
607
|
+
}
|
|
608
|
+
const data = await response.json();
|
|
609
|
+
logger.log("debug", "api", `Response: ${endpoint}`, { status: response.status }, duration);
|
|
610
|
+
return data;
|
|
611
|
+
} catch (err) {
|
|
612
|
+
if (err.code) throw err;
|
|
613
|
+
const error = createError("NETWORK_ERROR", err.message);
|
|
614
|
+
logger.log("error", "api", "Network error", { error: err.message });
|
|
615
|
+
onError?.(error);
|
|
616
|
+
throw error;
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
const postMessage = (type, payload) => {
|
|
620
|
+
iframe.contentWindow?.postMessage({ type, ...payload }, baseUrl);
|
|
621
|
+
};
|
|
622
|
+
const handleMessage = (event) => {
|
|
623
|
+
if (event.origin !== new URL(baseUrl).origin) return;
|
|
624
|
+
const { type, ...data } = event.data || {};
|
|
625
|
+
logger.log("debug", "render", `Message received: ${type}`, data);
|
|
626
|
+
switch (type) {
|
|
627
|
+
case "sybil:atlas:ready":
|
|
628
|
+
isReady = true;
|
|
629
|
+
logger.log("info", "render", "Atlas embed ready", {}, Date.now() - startTime);
|
|
630
|
+
onReady?.(instance);
|
|
631
|
+
break;
|
|
632
|
+
case "sybil:atlas:page:changed":
|
|
633
|
+
currentPage = data.page;
|
|
634
|
+
logger.log("info", "navigation", "Page changed", { pageId: data.page?.id });
|
|
635
|
+
onPageChange?.(data.page);
|
|
636
|
+
break;
|
|
637
|
+
case "sybil:atlas:page:created":
|
|
638
|
+
logger.log("info", "editor", "Page created", { pageId: data.page?.id });
|
|
639
|
+
onPageCreate?.(data.page);
|
|
640
|
+
break;
|
|
641
|
+
case "sybil:atlas:page:deleted":
|
|
642
|
+
logger.log("info", "editor", "Page deleted", { pageId: data.pageId });
|
|
643
|
+
onPageDelete?.(data.pageId);
|
|
644
|
+
break;
|
|
645
|
+
case "sybil:atlas:page:updated":
|
|
646
|
+
currentPage = data.page;
|
|
647
|
+
logger.log("debug", "sync", "Page updated", { pageId: data.page?.id });
|
|
648
|
+
onPageUpdate?.(data.page);
|
|
649
|
+
break;
|
|
650
|
+
case "sybil:atlas:navigate":
|
|
651
|
+
logger.log("info", "navigation", "Navigation requested", { pageId: data.pageId });
|
|
652
|
+
onNavigate?.(data.pageId);
|
|
653
|
+
break;
|
|
654
|
+
case "sybil:atlas:error":
|
|
655
|
+
const error = createError(data.code || "EMBED_ERROR", data.message);
|
|
656
|
+
logger.log("error", "render", "Embed error", data);
|
|
657
|
+
onError?.(error);
|
|
658
|
+
break;
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
window.addEventListener("message", handleMessage);
|
|
662
|
+
containerEl.appendChild(iframe);
|
|
663
|
+
const instance = {
|
|
664
|
+
getPages: async () => {
|
|
665
|
+
logger.log("info", "api", "Fetching pages");
|
|
666
|
+
const response = await apiRequest(
|
|
667
|
+
`/atlas/workspaces/${workspaceId}/sidebar`
|
|
668
|
+
);
|
|
669
|
+
return response.sidebar;
|
|
670
|
+
},
|
|
671
|
+
getPage: async (pageId) => {
|
|
672
|
+
logger.log("info", "api", "Fetching page", { pageId });
|
|
673
|
+
const response = await apiRequest(
|
|
674
|
+
`/atlas/pages/${pageId}`
|
|
675
|
+
);
|
|
676
|
+
return response.page;
|
|
677
|
+
},
|
|
678
|
+
createPage: async (params2) => {
|
|
679
|
+
logger.log("info", "api", "Creating page", params2);
|
|
680
|
+
const response = await apiRequest(
|
|
681
|
+
`/atlas/workspaces/${workspaceId}/pages`,
|
|
682
|
+
{
|
|
683
|
+
method: "POST",
|
|
684
|
+
body: JSON.stringify(params2)
|
|
685
|
+
}
|
|
686
|
+
);
|
|
687
|
+
postMessage("sybil:atlas:refresh");
|
|
688
|
+
return response.page;
|
|
689
|
+
},
|
|
690
|
+
updatePage: async (pageId, params2) => {
|
|
691
|
+
logger.log("info", "api", "Updating page", { pageId, ...params2 });
|
|
692
|
+
const response = await apiRequest(
|
|
693
|
+
`/atlas/pages/${pageId}`,
|
|
694
|
+
{
|
|
695
|
+
method: "PUT",
|
|
696
|
+
body: JSON.stringify(params2)
|
|
697
|
+
}
|
|
698
|
+
);
|
|
699
|
+
postMessage("sybil:atlas:refresh");
|
|
700
|
+
return response.page;
|
|
701
|
+
},
|
|
702
|
+
deletePage: async (pageId) => {
|
|
703
|
+
logger.log("info", "api", "Deleting page", { pageId });
|
|
704
|
+
await apiRequest(`/atlas/pages/${pageId}`, { method: "DELETE" });
|
|
705
|
+
postMessage("sybil:atlas:refresh");
|
|
706
|
+
},
|
|
707
|
+
navigateTo: (pageId) => {
|
|
708
|
+
logger.log("info", "navigation", "Navigating to page", { pageId });
|
|
709
|
+
postMessage("sybil:atlas:navigate", { pageId });
|
|
710
|
+
},
|
|
711
|
+
getCurrentPage: () => currentPage,
|
|
712
|
+
exportPage: async (pageId, format) => {
|
|
713
|
+
logger.log("info", "api", "Exporting page", { pageId, format });
|
|
714
|
+
const response = await fetch(
|
|
715
|
+
`${baseUrl}/api/sdk/v1/atlas/pages/${pageId}/export?format=${format}`,
|
|
716
|
+
{
|
|
717
|
+
headers: { "x-api-key": apiKey }
|
|
718
|
+
}
|
|
719
|
+
);
|
|
720
|
+
if (!response.ok) {
|
|
721
|
+
const error = createError("EXPORT_FAILED", "Failed to export page");
|
|
722
|
+
onError?.(error);
|
|
723
|
+
throw error;
|
|
724
|
+
}
|
|
725
|
+
return response.blob();
|
|
726
|
+
},
|
|
727
|
+
toggleSidebar: () => {
|
|
728
|
+
logger.log("debug", "render", "Toggling sidebar");
|
|
729
|
+
postMessage("sybil:atlas:toggleSidebar");
|
|
730
|
+
},
|
|
731
|
+
setSidebarWidth: (width) => {
|
|
732
|
+
logger.log("debug", "render", "Setting sidebar width", { width });
|
|
733
|
+
postMessage("sybil:atlas:setSidebarWidth", { width });
|
|
734
|
+
},
|
|
735
|
+
setTheme: (newTheme) => {
|
|
736
|
+
logger.log("debug", "render", "Setting theme", { theme: newTheme });
|
|
737
|
+
postMessage("sybil:atlas:setTheme", { theme: newTheme });
|
|
738
|
+
},
|
|
739
|
+
refresh: async () => {
|
|
740
|
+
logger.log("info", "sync", "Refreshing");
|
|
741
|
+
postMessage("sybil:atlas:refresh");
|
|
742
|
+
},
|
|
743
|
+
destroy: () => {
|
|
744
|
+
logger.log("info", "render", "Destroying Atlas embed");
|
|
745
|
+
window.removeEventListener("message", handleMessage);
|
|
746
|
+
iframe.remove();
|
|
747
|
+
},
|
|
748
|
+
getLogs: () => logger.getLogs(),
|
|
749
|
+
clearLogs: () => logger.clearLogs()
|
|
750
|
+
};
|
|
751
|
+
return instance;
|
|
752
|
+
}
|
|
753
|
+
var AtlasClient = class {
|
|
754
|
+
constructor(config) {
|
|
755
|
+
this.apiKey = config.apiKey;
|
|
756
|
+
this.workspaceId = config.workspaceId;
|
|
757
|
+
this.baseUrl = config.baseUrl || DEFAULT_BASE_URL2;
|
|
758
|
+
this.logger = new AtlasLogger(config.logging);
|
|
759
|
+
}
|
|
760
|
+
async request(endpoint, options = {}) {
|
|
761
|
+
const url = `${this.baseUrl}/api/sdk/v1${endpoint}`;
|
|
762
|
+
const startTime = Date.now();
|
|
763
|
+
this.logger.log("debug", "api", `Request: ${options.method || "GET"} ${endpoint}`);
|
|
764
|
+
const response = await fetch(url, {
|
|
765
|
+
...options,
|
|
766
|
+
headers: {
|
|
767
|
+
"x-api-key": this.apiKey,
|
|
768
|
+
"Content-Type": "application/json",
|
|
769
|
+
...options.headers
|
|
770
|
+
}
|
|
771
|
+
});
|
|
772
|
+
const duration = Date.now() - startTime;
|
|
773
|
+
if (!response.ok) {
|
|
774
|
+
const errorData = await response.json().catch(() => ({}));
|
|
775
|
+
this.logger.log("error", "api", `Request failed: ${endpoint}`, {
|
|
776
|
+
status: response.status,
|
|
777
|
+
error: errorData
|
|
778
|
+
}, duration);
|
|
779
|
+
throw new Error(errorData.error?.message || `Request failed with status ${response.status}`);
|
|
780
|
+
}
|
|
781
|
+
this.logger.log("debug", "api", `Response: ${endpoint}`, { status: response.status }, duration);
|
|
782
|
+
return response.json();
|
|
783
|
+
}
|
|
784
|
+
async getSidebar() {
|
|
785
|
+
const response = await this.request(
|
|
786
|
+
`/atlas/workspaces/${this.workspaceId}/sidebar`
|
|
787
|
+
);
|
|
788
|
+
return response.sidebar;
|
|
789
|
+
}
|
|
790
|
+
async getPage(pageId) {
|
|
791
|
+
const response = await this.request(`/atlas/pages/${pageId}`);
|
|
792
|
+
return response.page;
|
|
793
|
+
}
|
|
794
|
+
async createPage(params = {}) {
|
|
795
|
+
const response = await this.request(
|
|
796
|
+
`/atlas/workspaces/${this.workspaceId}/pages`,
|
|
797
|
+
{ method: "POST", body: JSON.stringify(params) }
|
|
798
|
+
);
|
|
799
|
+
return response.page;
|
|
800
|
+
}
|
|
801
|
+
async updatePage(pageId, params) {
|
|
802
|
+
const response = await this.request(
|
|
803
|
+
`/atlas/pages/${pageId}`,
|
|
804
|
+
{ method: "PUT", body: JSON.stringify(params) }
|
|
805
|
+
);
|
|
806
|
+
return response.page;
|
|
807
|
+
}
|
|
808
|
+
async deletePage(pageId) {
|
|
809
|
+
await this.request(`/atlas/pages/${pageId}`, { method: "DELETE" });
|
|
810
|
+
}
|
|
811
|
+
async exportPage(pageId, format) {
|
|
812
|
+
const response = await fetch(
|
|
813
|
+
`${this.baseUrl}/api/sdk/v1/atlas/pages/${pageId}/export?format=${format}`,
|
|
814
|
+
{ headers: { "x-api-key": this.apiKey } }
|
|
815
|
+
);
|
|
816
|
+
if (!response.ok) throw new Error("Failed to export page");
|
|
817
|
+
return response.blob();
|
|
818
|
+
}
|
|
819
|
+
async toggleFavorite(pageId) {
|
|
820
|
+
const response = await this.request(
|
|
821
|
+
`/atlas/pages/${pageId}/favorite`,
|
|
822
|
+
{ method: "POST" }
|
|
823
|
+
);
|
|
824
|
+
return response.page;
|
|
825
|
+
}
|
|
826
|
+
getLogs() {
|
|
827
|
+
return this.logger.getLogs();
|
|
828
|
+
}
|
|
829
|
+
clearLogs() {
|
|
830
|
+
this.logger.clearLogs();
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
// src/react/SybilAtlas.tsx
|
|
835
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
836
|
+
var SybilAtlas = (0, import_react2.forwardRef)(function SybilAtlas2({
|
|
837
|
+
apiKey,
|
|
838
|
+
workspaceId,
|
|
839
|
+
baseUrl,
|
|
840
|
+
theme = "dark",
|
|
841
|
+
showSidebar = true,
|
|
842
|
+
sidebarWidth = 260,
|
|
843
|
+
sidebarCollapsible = true,
|
|
844
|
+
readOnly = false,
|
|
845
|
+
defaultPageId,
|
|
846
|
+
allowCreate = true,
|
|
847
|
+
allowDelete = true,
|
|
848
|
+
allowExport = true,
|
|
849
|
+
features,
|
|
850
|
+
logging,
|
|
851
|
+
className,
|
|
852
|
+
style,
|
|
853
|
+
onReady,
|
|
854
|
+
onPageChange,
|
|
855
|
+
onPageCreate,
|
|
856
|
+
onPageDelete,
|
|
857
|
+
onPageUpdate,
|
|
858
|
+
onError,
|
|
859
|
+
onNavigate
|
|
860
|
+
}, ref) {
|
|
861
|
+
const containerRef = (0, import_react2.useRef)(null);
|
|
862
|
+
const instanceRef = (0, import_react2.useRef)(null);
|
|
863
|
+
(0, import_react2.useImperativeHandle)(ref, () => ({
|
|
864
|
+
getPages: async () => {
|
|
865
|
+
if (!instanceRef.current) throw new Error("Atlas not initialized");
|
|
866
|
+
return instanceRef.current.getPages();
|
|
867
|
+
},
|
|
868
|
+
getPage: async (pageId) => {
|
|
869
|
+
if (!instanceRef.current) throw new Error("Atlas not initialized");
|
|
870
|
+
return instanceRef.current.getPage(pageId);
|
|
871
|
+
},
|
|
872
|
+
createPage: async (params) => {
|
|
873
|
+
if (!instanceRef.current) throw new Error("Atlas not initialized");
|
|
874
|
+
return instanceRef.current.createPage(params || {});
|
|
875
|
+
},
|
|
876
|
+
updatePage: async (pageId, params) => {
|
|
877
|
+
if (!instanceRef.current) throw new Error("Atlas not initialized");
|
|
878
|
+
return instanceRef.current.updatePage(pageId, params);
|
|
879
|
+
},
|
|
880
|
+
deletePage: async (pageId) => {
|
|
881
|
+
if (!instanceRef.current) throw new Error("Atlas not initialized");
|
|
882
|
+
return instanceRef.current.deletePage(pageId);
|
|
883
|
+
},
|
|
884
|
+
navigateTo: (pageId) => {
|
|
885
|
+
instanceRef.current?.navigateTo(pageId);
|
|
886
|
+
},
|
|
887
|
+
getCurrentPage: () => {
|
|
888
|
+
return instanceRef.current?.getCurrentPage() || null;
|
|
889
|
+
},
|
|
890
|
+
exportPage: async (pageId, format) => {
|
|
891
|
+
if (!instanceRef.current) throw new Error("Atlas not initialized");
|
|
892
|
+
return instanceRef.current.exportPage(pageId, format);
|
|
893
|
+
},
|
|
894
|
+
toggleSidebar: () => {
|
|
895
|
+
instanceRef.current?.toggleSidebar();
|
|
896
|
+
},
|
|
897
|
+
setSidebarWidth: (width) => {
|
|
898
|
+
instanceRef.current?.setSidebarWidth(width);
|
|
899
|
+
},
|
|
900
|
+
setTheme: (newTheme) => {
|
|
901
|
+
instanceRef.current?.setTheme(newTheme);
|
|
902
|
+
},
|
|
903
|
+
refresh: async () => {
|
|
904
|
+
return instanceRef.current?.refresh();
|
|
905
|
+
},
|
|
906
|
+
getLogs: () => {
|
|
907
|
+
return instanceRef.current?.getLogs() || [];
|
|
908
|
+
},
|
|
909
|
+
clearLogs: () => {
|
|
910
|
+
instanceRef.current?.clearLogs();
|
|
911
|
+
}
|
|
912
|
+
}));
|
|
913
|
+
(0, import_react2.useEffect)(() => {
|
|
914
|
+
if (!containerRef.current || !apiKey || !workspaceId) return;
|
|
915
|
+
instanceRef.current?.destroy();
|
|
916
|
+
const config = {
|
|
917
|
+
apiKey,
|
|
918
|
+
workspaceId,
|
|
919
|
+
container: containerRef.current,
|
|
920
|
+
baseUrl,
|
|
921
|
+
theme,
|
|
922
|
+
showSidebar,
|
|
923
|
+
sidebarWidth,
|
|
924
|
+
sidebarCollapsible,
|
|
925
|
+
readOnly,
|
|
926
|
+
defaultPageId,
|
|
927
|
+
allowCreate,
|
|
928
|
+
allowDelete,
|
|
929
|
+
allowExport,
|
|
930
|
+
features,
|
|
931
|
+
logging,
|
|
932
|
+
onReady,
|
|
933
|
+
onPageChange,
|
|
934
|
+
onPageCreate,
|
|
935
|
+
onPageDelete,
|
|
936
|
+
onPageUpdate,
|
|
937
|
+
onError,
|
|
938
|
+
onNavigate
|
|
939
|
+
};
|
|
940
|
+
instanceRef.current = embedAtlas(config);
|
|
941
|
+
return () => {
|
|
942
|
+
instanceRef.current?.destroy();
|
|
943
|
+
instanceRef.current = null;
|
|
944
|
+
};
|
|
945
|
+
}, [apiKey, workspaceId, baseUrl]);
|
|
946
|
+
(0, import_react2.useEffect)(() => {
|
|
947
|
+
instanceRef.current?.setTheme(theme);
|
|
948
|
+
}, [theme]);
|
|
949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
950
|
+
"div",
|
|
951
|
+
{
|
|
952
|
+
ref: containerRef,
|
|
953
|
+
className,
|
|
954
|
+
style: {
|
|
955
|
+
width: "100%",
|
|
956
|
+
height: "100%",
|
|
957
|
+
minHeight: "500px",
|
|
958
|
+
...style
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
);
|
|
962
|
+
});
|
|
963
|
+
|
|
964
|
+
// src/react/SybilNexus.tsx
|
|
965
|
+
var import_react3 = require("react");
|
|
966
|
+
|
|
967
|
+
// src/nexus/client.ts
|
|
968
|
+
var DEFAULT_BASE_URL3 = "https://app.sybil.studio";
|
|
969
|
+
var NexusLogger = class {
|
|
970
|
+
constructor(config) {
|
|
971
|
+
this.logs = [];
|
|
972
|
+
this.config = config;
|
|
973
|
+
}
|
|
974
|
+
log(level, category, message, data, duration) {
|
|
975
|
+
if (!this.config?.enabled) return;
|
|
976
|
+
const levels = ["debug", "info", "warn", "error"];
|
|
977
|
+
const configLevel = this.config.level || "info";
|
|
978
|
+
if (levels.indexOf(level) < levels.indexOf(configLevel)) return;
|
|
979
|
+
const entry = {
|
|
980
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
981
|
+
level,
|
|
982
|
+
category,
|
|
983
|
+
message,
|
|
984
|
+
data,
|
|
985
|
+
duration,
|
|
986
|
+
fileId: data?.fileId,
|
|
987
|
+
folderId: data?.folderId
|
|
988
|
+
};
|
|
989
|
+
this.logs.push(entry);
|
|
990
|
+
this.config.onLog?.(entry);
|
|
991
|
+
if (typeof console !== "undefined") {
|
|
992
|
+
const prefix = `[Nexus SDK] [${category}]`;
|
|
993
|
+
switch (level) {
|
|
994
|
+
case "debug":
|
|
995
|
+
console.debug(prefix, message, data || "");
|
|
996
|
+
break;
|
|
997
|
+
case "info":
|
|
998
|
+
console.info(prefix, message, data || "");
|
|
999
|
+
break;
|
|
1000
|
+
case "warn":
|
|
1001
|
+
console.warn(prefix, message, data || "");
|
|
1002
|
+
break;
|
|
1003
|
+
case "error":
|
|
1004
|
+
console.error(prefix, message, data || "");
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
getLogs() {
|
|
1010
|
+
return [...this.logs];
|
|
1011
|
+
}
|
|
1012
|
+
clearLogs() {
|
|
1013
|
+
this.logs = [];
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
function embedNexus(config) {
|
|
1017
|
+
const {
|
|
1018
|
+
apiKey,
|
|
1019
|
+
workspaceId,
|
|
1020
|
+
container,
|
|
1021
|
+
baseUrl = DEFAULT_BASE_URL3,
|
|
1022
|
+
theme = "dark",
|
|
1023
|
+
initialFolderId = null,
|
|
1024
|
+
viewMode = "list",
|
|
1025
|
+
showSidebar = true,
|
|
1026
|
+
showActivityFeed = true,
|
|
1027
|
+
showBreadcrumbs = true,
|
|
1028
|
+
showSearch = true,
|
|
1029
|
+
allowUpload = true,
|
|
1030
|
+
allowDownload = true,
|
|
1031
|
+
allowDelete = true,
|
|
1032
|
+
allowMove = true,
|
|
1033
|
+
allowRename = true,
|
|
1034
|
+
allowCreateFolder = true,
|
|
1035
|
+
allowMultiSelect = true,
|
|
1036
|
+
maxUploadSize,
|
|
1037
|
+
acceptedFileTypes,
|
|
1038
|
+
features = {},
|
|
1039
|
+
logging,
|
|
1040
|
+
onReady,
|
|
1041
|
+
onNavigate,
|
|
1042
|
+
onFileSelect,
|
|
1043
|
+
onFileOpen,
|
|
1044
|
+
onFileUpload,
|
|
1045
|
+
onFileDelete,
|
|
1046
|
+
onFolderCreate,
|
|
1047
|
+
onFolderDelete,
|
|
1048
|
+
onSelectionChange,
|
|
1049
|
+
onError
|
|
1050
|
+
} = config;
|
|
1051
|
+
const logger = new NexusLogger(logging);
|
|
1052
|
+
const startTime = Date.now();
|
|
1053
|
+
logger.log("info", "ui", "Initializing Nexus embed", {
|
|
1054
|
+
workspaceId,
|
|
1055
|
+
initialFolderId,
|
|
1056
|
+
viewMode,
|
|
1057
|
+
features
|
|
1058
|
+
});
|
|
1059
|
+
const containerEl = typeof container === "string" ? document.querySelector(container) : container;
|
|
1060
|
+
if (!containerEl) {
|
|
1061
|
+
const error = {
|
|
1062
|
+
code: "CONTAINER_NOT_FOUND",
|
|
1063
|
+
message: "Container element not found",
|
|
1064
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1065
|
+
};
|
|
1066
|
+
onError?.(error);
|
|
1067
|
+
throw new Error(error.message);
|
|
1068
|
+
}
|
|
1069
|
+
const params = new URLSearchParams({
|
|
1070
|
+
apiKey,
|
|
1071
|
+
workspaceId,
|
|
1072
|
+
viewMode,
|
|
1073
|
+
showSidebar: showSidebar.toString(),
|
|
1074
|
+
showActivityFeed: showActivityFeed.toString(),
|
|
1075
|
+
showBreadcrumbs: showBreadcrumbs.toString(),
|
|
1076
|
+
showSearch: showSearch.toString(),
|
|
1077
|
+
allowUpload: allowUpload.toString(),
|
|
1078
|
+
allowDownload: allowDownload.toString(),
|
|
1079
|
+
allowDelete: allowDelete.toString(),
|
|
1080
|
+
allowMove: allowMove.toString(),
|
|
1081
|
+
allowRename: allowRename.toString(),
|
|
1082
|
+
allowCreateFolder: allowCreateFolder.toString(),
|
|
1083
|
+
allowMultiSelect: allowMultiSelect.toString()
|
|
1084
|
+
});
|
|
1085
|
+
if (initialFolderId) params.set("folderId", initialFolderId);
|
|
1086
|
+
if (maxUploadSize) params.set("maxUploadSize", maxUploadSize.toString());
|
|
1087
|
+
if (acceptedFileTypes?.length) params.set("acceptedFileTypes", acceptedFileTypes.join(","));
|
|
1088
|
+
if (typeof theme === "string") {
|
|
1089
|
+
params.set("theme", theme);
|
|
1090
|
+
} else {
|
|
1091
|
+
Object.entries(theme).forEach(([key, value]) => {
|
|
1092
|
+
if (value) params.set(`theme_${key}`, value);
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
Object.entries(features).forEach(([key, value]) => {
|
|
1096
|
+
if (typeof value === "boolean") {
|
|
1097
|
+
params.set(`feature_${key}`, value.toString());
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
const iframe = document.createElement("iframe");
|
|
1101
|
+
iframe.src = `${baseUrl}/embed/nexus?${params.toString()}`;
|
|
1102
|
+
iframe.style.width = "100%";
|
|
1103
|
+
iframe.style.height = "100%";
|
|
1104
|
+
iframe.style.border = "none";
|
|
1105
|
+
iframe.style.borderRadius = "8px";
|
|
1106
|
+
iframe.allow = "clipboard-write";
|
|
1107
|
+
let currentFolderId = initialFolderId;
|
|
1108
|
+
let selectedItems = [];
|
|
1109
|
+
let isReady = false;
|
|
1110
|
+
const createError = (code, message, status) => ({
|
|
1111
|
+
code,
|
|
1112
|
+
message,
|
|
1113
|
+
status,
|
|
1114
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1115
|
+
requestId: `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
1116
|
+
});
|
|
1117
|
+
const apiRequest = async (endpoint, options = {}) => {
|
|
1118
|
+
const requestStart = Date.now();
|
|
1119
|
+
const url = `${baseUrl}/api/sdk/v1${endpoint}`;
|
|
1120
|
+
logger.log("debug", "api", `Request: ${options.method || "GET"} ${endpoint}`, {
|
|
1121
|
+
url,
|
|
1122
|
+
method: options.method || "GET"
|
|
1123
|
+
});
|
|
1124
|
+
try {
|
|
1125
|
+
const response = await fetch(url, {
|
|
1126
|
+
...options,
|
|
1127
|
+
headers: {
|
|
1128
|
+
"x-api-key": apiKey,
|
|
1129
|
+
...options.body instanceof FormData ? {} : { "Content-Type": "application/json" },
|
|
1130
|
+
...options.headers
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
const duration = Date.now() - requestStart;
|
|
1134
|
+
if (!response.ok) {
|
|
1135
|
+
const errorData = await response.json().catch(() => ({}));
|
|
1136
|
+
const error = createError(
|
|
1137
|
+
errorData.error?.code || "API_ERROR",
|
|
1138
|
+
errorData.error?.message || `Request failed with status ${response.status}`,
|
|
1139
|
+
response.status
|
|
1140
|
+
);
|
|
1141
|
+
logger.log("error", "api", `Request failed: ${endpoint}`, {
|
|
1142
|
+
status: response.status,
|
|
1143
|
+
error: errorData
|
|
1144
|
+
}, duration);
|
|
1145
|
+
onError?.(error);
|
|
1146
|
+
throw error;
|
|
1147
|
+
}
|
|
1148
|
+
const data = await response.json();
|
|
1149
|
+
logger.log("debug", "api", `Response: ${endpoint}`, { status: response.status }, duration);
|
|
1150
|
+
return data;
|
|
1151
|
+
} catch (err) {
|
|
1152
|
+
if (err.code) throw err;
|
|
1153
|
+
const error = createError("NETWORK_ERROR", err.message);
|
|
1154
|
+
logger.log("error", "api", "Network error", { error: err.message });
|
|
1155
|
+
onError?.(error);
|
|
1156
|
+
throw error;
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
const postMessage = (type, payload) => {
|
|
1160
|
+
iframe.contentWindow?.postMessage({ type, ...payload }, baseUrl);
|
|
1161
|
+
};
|
|
1162
|
+
const handleMessage = (event) => {
|
|
1163
|
+
if (event.origin !== new URL(baseUrl).origin) return;
|
|
1164
|
+
const { type, ...data } = event.data || {};
|
|
1165
|
+
logger.log("debug", "ui", `Message received: ${type}`, data);
|
|
1166
|
+
switch (type) {
|
|
1167
|
+
case "sybil:nexus:ready":
|
|
1168
|
+
isReady = true;
|
|
1169
|
+
logger.log("info", "ui", "Nexus embed ready", {}, Date.now() - startTime);
|
|
1170
|
+
onReady?.(instance);
|
|
1171
|
+
break;
|
|
1172
|
+
case "sybil:nexus:navigate":
|
|
1173
|
+
currentFolderId = data.folderId;
|
|
1174
|
+
logger.log("info", "navigation", "Navigated to folder", { folderId: data.folderId });
|
|
1175
|
+
onNavigate?.(data.folderId);
|
|
1176
|
+
break;
|
|
1177
|
+
case "sybil:nexus:file:select":
|
|
1178
|
+
logger.log("debug", "selection", "File selected", { fileId: data.file?.id });
|
|
1179
|
+
onFileSelect?.(data.file);
|
|
1180
|
+
break;
|
|
1181
|
+
case "sybil:nexus:file:open":
|
|
1182
|
+
logger.log("info", "ui", "File opened", { fileId: data.file?.id });
|
|
1183
|
+
onFileOpen?.(data.file);
|
|
1184
|
+
break;
|
|
1185
|
+
case "sybil:nexus:file:upload":
|
|
1186
|
+
logger.log("info", "upload", "File uploaded", { fileId: data.file?.id });
|
|
1187
|
+
onFileUpload?.(data.file);
|
|
1188
|
+
break;
|
|
1189
|
+
case "sybil:nexus:file:delete":
|
|
1190
|
+
logger.log("info", "api", "File deleted", { fileId: data.fileId });
|
|
1191
|
+
onFileDelete?.(data.fileId);
|
|
1192
|
+
break;
|
|
1193
|
+
case "sybil:nexus:folder:create":
|
|
1194
|
+
logger.log("info", "api", "Folder created", { folderId: data.folder?.id });
|
|
1195
|
+
onFolderCreate?.(data.folder);
|
|
1196
|
+
break;
|
|
1197
|
+
case "sybil:nexus:folder:delete":
|
|
1198
|
+
logger.log("info", "api", "Folder deleted", { folderId: data.folderId });
|
|
1199
|
+
onFolderDelete?.(data.folderId);
|
|
1200
|
+
break;
|
|
1201
|
+
case "sybil:nexus:selection:change":
|
|
1202
|
+
selectedItems = data.items || [];
|
|
1203
|
+
logger.log("debug", "selection", "Selection changed", { count: selectedItems.length });
|
|
1204
|
+
onSelectionChange?.(selectedItems);
|
|
1205
|
+
break;
|
|
1206
|
+
case "sybil:nexus:error":
|
|
1207
|
+
const error = createError(data.code || "EMBED_ERROR", data.message);
|
|
1208
|
+
logger.log("error", "ui", "Embed error", data);
|
|
1209
|
+
onError?.(error);
|
|
1210
|
+
break;
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
window.addEventListener("message", handleMessage);
|
|
1214
|
+
containerEl.appendChild(iframe);
|
|
1215
|
+
const instance = {
|
|
1216
|
+
getFiles: async (folderId) => {
|
|
1217
|
+
logger.log("info", "api", "Fetching files", { folderId });
|
|
1218
|
+
const params2 = new URLSearchParams({ workspaceId });
|
|
1219
|
+
if (folderId !== void 0) params2.set("folderId", folderId || "null");
|
|
1220
|
+
const response = await apiRequest(
|
|
1221
|
+
`/nexus/files?${params2.toString()}`
|
|
1222
|
+
);
|
|
1223
|
+
return response.files.map((f) => ({
|
|
1224
|
+
...f,
|
|
1225
|
+
itemType: "file"
|
|
1226
|
+
}));
|
|
1227
|
+
},
|
|
1228
|
+
getFolders: async (parentId) => {
|
|
1229
|
+
logger.log("info", "api", "Fetching folders", { parentId });
|
|
1230
|
+
const params2 = new URLSearchParams({ workspaceId });
|
|
1231
|
+
if (parentId !== void 0) params2.set("parentId", parentId || "null");
|
|
1232
|
+
const response = await apiRequest(
|
|
1233
|
+
`/nexus/folders?${params2.toString()}`
|
|
1234
|
+
);
|
|
1235
|
+
return response.folders;
|
|
1236
|
+
},
|
|
1237
|
+
getFolderContents: async (folderId) => {
|
|
1238
|
+
logger.log("info", "api", "Fetching folder contents", { folderId });
|
|
1239
|
+
const params2 = new URLSearchParams({ workspaceId });
|
|
1240
|
+
if (folderId) params2.set("folderId", folderId);
|
|
1241
|
+
const response = await apiRequest(
|
|
1242
|
+
`/nexus/folders/contents?${params2.toString()}`
|
|
1243
|
+
);
|
|
1244
|
+
return response;
|
|
1245
|
+
},
|
|
1246
|
+
getFolderTree: async () => {
|
|
1247
|
+
logger.log("info", "api", "Fetching folder tree");
|
|
1248
|
+
const response = await apiRequest(
|
|
1249
|
+
`/nexus/folders/tree?workspaceId=${workspaceId}`
|
|
1250
|
+
);
|
|
1251
|
+
return response.tree;
|
|
1252
|
+
},
|
|
1253
|
+
getFile: async (fileId) => {
|
|
1254
|
+
logger.log("info", "api", "Fetching file", { fileId });
|
|
1255
|
+
const response = await apiRequest(`/nexus/files/${fileId}`);
|
|
1256
|
+
return response.file;
|
|
1257
|
+
},
|
|
1258
|
+
getFolder: async (folderId) => {
|
|
1259
|
+
logger.log("info", "api", "Fetching folder", { folderId });
|
|
1260
|
+
const response = await apiRequest(
|
|
1261
|
+
`/nexus/folders/${folderId}`
|
|
1262
|
+
);
|
|
1263
|
+
return response.folder;
|
|
1264
|
+
},
|
|
1265
|
+
uploadFile: async (file, folderId, onProgress) => {
|
|
1266
|
+
logger.log("info", "upload", "Uploading file", { fileName: file.name, size: file.size, folderId });
|
|
1267
|
+
const formData = new FormData();
|
|
1268
|
+
formData.append("file", file);
|
|
1269
|
+
formData.append("workspaceId", workspaceId);
|
|
1270
|
+
if (folderId) formData.append("folderId", folderId);
|
|
1271
|
+
const xhr = new XMLHttpRequest();
|
|
1272
|
+
return new Promise((resolve, reject) => {
|
|
1273
|
+
xhr.upload.addEventListener("progress", (e) => {
|
|
1274
|
+
if (e.lengthComputable) {
|
|
1275
|
+
const progress = Math.round(e.loaded / e.total * 100);
|
|
1276
|
+
logger.log("debug", "upload", "Upload progress", { progress, fileName: file.name });
|
|
1277
|
+
onProgress?.(progress);
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
xhr.addEventListener("load", () => {
|
|
1281
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
1282
|
+
const response = JSON.parse(xhr.responseText);
|
|
1283
|
+
logger.log("info", "upload", "Upload complete", { fileId: response.file?.id });
|
|
1284
|
+
postMessage("sybil:nexus:refresh");
|
|
1285
|
+
resolve(response.file);
|
|
1286
|
+
} else {
|
|
1287
|
+
const error = createError("UPLOAD_FAILED", "Failed to upload file", xhr.status);
|
|
1288
|
+
logger.log("error", "upload", "Upload failed", { status: xhr.status });
|
|
1289
|
+
onError?.(error);
|
|
1290
|
+
reject(error);
|
|
1291
|
+
}
|
|
1292
|
+
});
|
|
1293
|
+
xhr.addEventListener("error", () => {
|
|
1294
|
+
const error = createError("UPLOAD_ERROR", "Network error during upload");
|
|
1295
|
+
logger.log("error", "upload", "Upload network error");
|
|
1296
|
+
onError?.(error);
|
|
1297
|
+
reject(error);
|
|
1298
|
+
});
|
|
1299
|
+
xhr.open("POST", `${baseUrl}/api/sdk/v1/nexus/upload`);
|
|
1300
|
+
xhr.setRequestHeader("x-api-key", apiKey);
|
|
1301
|
+
xhr.send(formData);
|
|
1302
|
+
});
|
|
1303
|
+
},
|
|
1304
|
+
uploadFiles: async (files, folderId, onProgress) => {
|
|
1305
|
+
logger.log("info", "upload", "Uploading multiple files", { count: files.length, folderId });
|
|
1306
|
+
const results = [];
|
|
1307
|
+
for (let i = 0; i < files.length; i++) {
|
|
1308
|
+
const file = await instance.uploadFile(files[i], folderId, (progress) => {
|
|
1309
|
+
onProgress?.(i, progress);
|
|
1310
|
+
});
|
|
1311
|
+
results.push(file);
|
|
1312
|
+
}
|
|
1313
|
+
return results;
|
|
1314
|
+
},
|
|
1315
|
+
downloadFile: async (fileId) => {
|
|
1316
|
+
logger.log("info", "download", "Downloading file", { fileId });
|
|
1317
|
+
const response = await fetch(`${baseUrl}/api/sdk/v1/nexus/files/${fileId}/content`, {
|
|
1318
|
+
headers: { "x-api-key": apiKey }
|
|
1319
|
+
});
|
|
1320
|
+
if (!response.ok) {
|
|
1321
|
+
const error = createError("DOWNLOAD_FAILED", "Failed to download file", response.status);
|
|
1322
|
+
onError?.(error);
|
|
1323
|
+
throw error;
|
|
1324
|
+
}
|
|
1325
|
+
return response.blob();
|
|
1326
|
+
},
|
|
1327
|
+
getDownloadUrl: async (fileId) => {
|
|
1328
|
+
logger.log("info", "download", "Getting download URL", { fileId });
|
|
1329
|
+
const response = await apiRequest(`/nexus/files/${fileId}/url`);
|
|
1330
|
+
return response.signedUrl;
|
|
1331
|
+
},
|
|
1332
|
+
deleteFile: async (fileId) => {
|
|
1333
|
+
logger.log("info", "api", "Deleting file", { fileId });
|
|
1334
|
+
await apiRequest(`/nexus/files/${fileId}`, { method: "DELETE" });
|
|
1335
|
+
postMessage("sybil:nexus:refresh");
|
|
1336
|
+
},
|
|
1337
|
+
deleteFiles: async (fileIds) => {
|
|
1338
|
+
logger.log("info", "api", "Deleting multiple files", { count: fileIds.length });
|
|
1339
|
+
await apiRequest("/nexus/files/bulk", {
|
|
1340
|
+
method: "DELETE",
|
|
1341
|
+
body: JSON.stringify({ fileIds })
|
|
1342
|
+
});
|
|
1343
|
+
postMessage("sybil:nexus:refresh");
|
|
1344
|
+
},
|
|
1345
|
+
moveFile: async (fileId, targetFolderId) => {
|
|
1346
|
+
logger.log("info", "api", "Moving file", { fileId, targetFolderId });
|
|
1347
|
+
const response = await apiRequest(`/nexus/files/${fileId}`, {
|
|
1348
|
+
method: "PATCH",
|
|
1349
|
+
body: JSON.stringify({ folderId: targetFolderId })
|
|
1350
|
+
});
|
|
1351
|
+
postMessage("sybil:nexus:refresh");
|
|
1352
|
+
return response.file;
|
|
1353
|
+
},
|
|
1354
|
+
moveFiles: async (fileIds, targetFolderId) => {
|
|
1355
|
+
logger.log("info", "api", "Moving multiple files", { count: fileIds.length, targetFolderId });
|
|
1356
|
+
const response = await apiRequest("/nexus/files/bulk", {
|
|
1357
|
+
method: "PATCH",
|
|
1358
|
+
body: JSON.stringify({ fileIds, folderId: targetFolderId })
|
|
1359
|
+
});
|
|
1360
|
+
postMessage("sybil:nexus:refresh");
|
|
1361
|
+
return response.files;
|
|
1362
|
+
},
|
|
1363
|
+
renameFile: async (fileId, newName) => {
|
|
1364
|
+
logger.log("info", "api", "Renaming file", { fileId, newName });
|
|
1365
|
+
const response = await apiRequest(`/nexus/files/${fileId}`, {
|
|
1366
|
+
method: "PATCH",
|
|
1367
|
+
body: JSON.stringify({ name: newName })
|
|
1368
|
+
});
|
|
1369
|
+
postMessage("sybil:nexus:refresh");
|
|
1370
|
+
return response.file;
|
|
1371
|
+
},
|
|
1372
|
+
starFile: async (fileId, starred) => {
|
|
1373
|
+
logger.log("info", "api", "Starring file", { fileId, starred });
|
|
1374
|
+
const response = await apiRequest(`/nexus/files/${fileId}`, {
|
|
1375
|
+
method: "PATCH",
|
|
1376
|
+
body: JSON.stringify({ isStarred: starred })
|
|
1377
|
+
});
|
|
1378
|
+
postMessage("sybil:nexus:refresh");
|
|
1379
|
+
return response.file;
|
|
1380
|
+
},
|
|
1381
|
+
starFiles: async (fileIds, starred) => {
|
|
1382
|
+
logger.log("info", "api", "Starring multiple files", { count: fileIds.length, starred });
|
|
1383
|
+
await apiRequest("/nexus/files/bulk", {
|
|
1384
|
+
method: "PATCH",
|
|
1385
|
+
body: JSON.stringify({ fileIds, isStarred: starred })
|
|
1386
|
+
});
|
|
1387
|
+
postMessage("sybil:nexus:refresh");
|
|
1388
|
+
},
|
|
1389
|
+
trashFile: async (fileId) => {
|
|
1390
|
+
logger.log("info", "api", "Trashing file", { fileId });
|
|
1391
|
+
await apiRequest(`/nexus/files/${fileId}`, { method: "DELETE" });
|
|
1392
|
+
postMessage("sybil:nexus:refresh");
|
|
1393
|
+
},
|
|
1394
|
+
restoreFile: async (fileId, folderId) => {
|
|
1395
|
+
logger.log("info", "api", "Restoring file", { fileId, folderId });
|
|
1396
|
+
const response = await apiRequest(`/nexus/files/${fileId}/restore`, {
|
|
1397
|
+
method: "POST",
|
|
1398
|
+
body: JSON.stringify({ folderId })
|
|
1399
|
+
});
|
|
1400
|
+
postMessage("sybil:nexus:refresh");
|
|
1401
|
+
return response.file;
|
|
1402
|
+
},
|
|
1403
|
+
createFolder: async (name, parentId, options) => {
|
|
1404
|
+
logger.log("info", "api", "Creating folder", { name, parentId, options });
|
|
1405
|
+
const response = await apiRequest("/nexus/folders", {
|
|
1406
|
+
method: "POST",
|
|
1407
|
+
body: JSON.stringify({ workspaceId, name, parentId, ...options })
|
|
1408
|
+
});
|
|
1409
|
+
postMessage("sybil:nexus:refresh");
|
|
1410
|
+
return response.folder;
|
|
1411
|
+
},
|
|
1412
|
+
deleteFolder: async (folderId) => {
|
|
1413
|
+
logger.log("info", "api", "Deleting folder", { folderId });
|
|
1414
|
+
await apiRequest(`/nexus/folders/${folderId}`, { method: "DELETE" });
|
|
1415
|
+
postMessage("sybil:nexus:refresh");
|
|
1416
|
+
},
|
|
1417
|
+
moveFolder: async (folderId, targetParentId) => {
|
|
1418
|
+
logger.log("info", "api", "Moving folder", { folderId, targetParentId });
|
|
1419
|
+
const response = await apiRequest(`/nexus/folders/${folderId}`, {
|
|
1420
|
+
method: "PATCH",
|
|
1421
|
+
body: JSON.stringify({ parentId: targetParentId })
|
|
1422
|
+
});
|
|
1423
|
+
postMessage("sybil:nexus:refresh");
|
|
1424
|
+
return response.folder;
|
|
1425
|
+
},
|
|
1426
|
+
renameFolder: async (folderId, newName) => {
|
|
1427
|
+
logger.log("info", "api", "Renaming folder", { folderId, newName });
|
|
1428
|
+
const response = await apiRequest(`/nexus/folders/${folderId}`, {
|
|
1429
|
+
method: "PATCH",
|
|
1430
|
+
body: JSON.stringify({ name: newName })
|
|
1431
|
+
});
|
|
1432
|
+
postMessage("sybil:nexus:refresh");
|
|
1433
|
+
return response.folder;
|
|
1434
|
+
},
|
|
1435
|
+
navigateTo: (folderId) => {
|
|
1436
|
+
currentFolderId = folderId;
|
|
1437
|
+
logger.log("info", "navigation", "Navigating to folder", { folderId });
|
|
1438
|
+
postMessage("sybil:nexus:navigate", { folderId });
|
|
1439
|
+
},
|
|
1440
|
+
getCurrentFolder: () => currentFolderId,
|
|
1441
|
+
getSelection: () => [...selectedItems],
|
|
1442
|
+
setSelection: (itemIds) => {
|
|
1443
|
+
logger.log("debug", "selection", "Setting selection", { count: itemIds.length });
|
|
1444
|
+
postMessage("sybil:nexus:setSelection", { itemIds });
|
|
1445
|
+
},
|
|
1446
|
+
clearSelection: () => {
|
|
1447
|
+
logger.log("debug", "selection", "Clearing selection");
|
|
1448
|
+
postMessage("sybil:nexus:clearSelection");
|
|
1449
|
+
},
|
|
1450
|
+
selectAll: () => {
|
|
1451
|
+
logger.log("debug", "selection", "Selecting all");
|
|
1452
|
+
postMessage("sybil:nexus:selectAll");
|
|
1453
|
+
},
|
|
1454
|
+
setViewMode: (mode) => {
|
|
1455
|
+
logger.log("debug", "ui", "Setting view mode", { mode });
|
|
1456
|
+
postMessage("sybil:nexus:setViewMode", { mode });
|
|
1457
|
+
},
|
|
1458
|
+
toggleActivityFeed: () => {
|
|
1459
|
+
logger.log("debug", "ui", "Toggling activity feed");
|
|
1460
|
+
postMessage("sybil:nexus:toggleActivity");
|
|
1461
|
+
},
|
|
1462
|
+
toggleSidebar: () => {
|
|
1463
|
+
logger.log("debug", "ui", "Toggling sidebar");
|
|
1464
|
+
postMessage("sybil:nexus:toggleSidebar");
|
|
1465
|
+
},
|
|
1466
|
+
refresh: async () => {
|
|
1467
|
+
logger.log("info", "ui", "Refreshing");
|
|
1468
|
+
postMessage("sybil:nexus:refresh");
|
|
1469
|
+
},
|
|
1470
|
+
search: async (query) => {
|
|
1471
|
+
logger.log("info", "api", "Searching", { query });
|
|
1472
|
+
const params2 = new URLSearchParams({ workspaceId, search: query });
|
|
1473
|
+
const response = await apiRequest(
|
|
1474
|
+
`/nexus/files?${params2.toString()}`
|
|
1475
|
+
);
|
|
1476
|
+
return response.files.map((f) => ({
|
|
1477
|
+
...f,
|
|
1478
|
+
itemType: "file"
|
|
1479
|
+
}));
|
|
1480
|
+
},
|
|
1481
|
+
getStats: async () => {
|
|
1482
|
+
logger.log("info", "api", "Fetching stats");
|
|
1483
|
+
const response = await apiRequest(
|
|
1484
|
+
`/nexus/stats?workspaceId=${workspaceId}`
|
|
1485
|
+
);
|
|
1486
|
+
return response.stats;
|
|
1487
|
+
},
|
|
1488
|
+
getActivity: async (limit = 50) => {
|
|
1489
|
+
logger.log("info", "api", "Fetching activity", { limit });
|
|
1490
|
+
const response = await apiRequest(
|
|
1491
|
+
`/nexus/activity?workspaceId=${workspaceId}&limit=${limit}`
|
|
1492
|
+
);
|
|
1493
|
+
return response.activities;
|
|
1494
|
+
},
|
|
1495
|
+
getLabels: async () => {
|
|
1496
|
+
logger.log("info", "api", "Fetching labels");
|
|
1497
|
+
const response = await apiRequest(
|
|
1498
|
+
`/nexus/labels?workspaceId=${workspaceId}`
|
|
1499
|
+
);
|
|
1500
|
+
return response.labels;
|
|
1501
|
+
},
|
|
1502
|
+
applyLabel: async (itemIds, labelId) => {
|
|
1503
|
+
logger.log("info", "api", "Applying label", { count: itemIds.length, labelId });
|
|
1504
|
+
await apiRequest("/nexus/labels/apply", {
|
|
1505
|
+
method: "POST",
|
|
1506
|
+
body: JSON.stringify({ itemIds, labelId })
|
|
1507
|
+
});
|
|
1508
|
+
postMessage("sybil:nexus:refresh");
|
|
1509
|
+
},
|
|
1510
|
+
removeLabel: async (itemIds, labelId) => {
|
|
1511
|
+
logger.log("info", "api", "Removing label", { count: itemIds.length, labelId });
|
|
1512
|
+
await apiRequest("/nexus/labels/apply", {
|
|
1513
|
+
method: "DELETE",
|
|
1514
|
+
body: JSON.stringify({ itemIds, labelId })
|
|
1515
|
+
});
|
|
1516
|
+
postMessage("sybil:nexus:refresh");
|
|
1517
|
+
},
|
|
1518
|
+
setTheme: (newTheme) => {
|
|
1519
|
+
logger.log("debug", "ui", "Setting theme", { theme: newTheme });
|
|
1520
|
+
postMessage("sybil:nexus:setTheme", { theme: newTheme });
|
|
1521
|
+
},
|
|
1522
|
+
destroy: () => {
|
|
1523
|
+
logger.log("info", "ui", "Destroying Nexus embed");
|
|
1524
|
+
window.removeEventListener("message", handleMessage);
|
|
1525
|
+
iframe.remove();
|
|
1526
|
+
},
|
|
1527
|
+
getLogs: () => logger.getLogs(),
|
|
1528
|
+
clearLogs: () => logger.clearLogs()
|
|
1529
|
+
};
|
|
1530
|
+
return instance;
|
|
1531
|
+
}
|
|
1532
|
+
var NexusClient = class {
|
|
1533
|
+
constructor(config) {
|
|
1534
|
+
this.apiKey = config.apiKey;
|
|
1535
|
+
this.workspaceId = config.workspaceId;
|
|
1536
|
+
this.baseUrl = config.baseUrl || DEFAULT_BASE_URL3;
|
|
1537
|
+
this.logger = new NexusLogger(config.logging);
|
|
1538
|
+
}
|
|
1539
|
+
async request(endpoint, options = {}) {
|
|
1540
|
+
const url = `${this.baseUrl}/api/sdk/v1${endpoint}`;
|
|
1541
|
+
const startTime = Date.now();
|
|
1542
|
+
this.logger.log("debug", "api", `Request: ${options.method || "GET"} ${endpoint}`);
|
|
1543
|
+
const response = await fetch(url, {
|
|
1544
|
+
...options,
|
|
1545
|
+
headers: {
|
|
1546
|
+
"x-api-key": this.apiKey,
|
|
1547
|
+
...options.body instanceof FormData ? {} : { "Content-Type": "application/json" },
|
|
1548
|
+
...options.headers
|
|
1549
|
+
}
|
|
1550
|
+
});
|
|
1551
|
+
const duration = Date.now() - startTime;
|
|
1552
|
+
if (!response.ok) {
|
|
1553
|
+
const errorData = await response.json().catch(() => ({}));
|
|
1554
|
+
this.logger.log("error", "api", `Request failed: ${endpoint}`, {
|
|
1555
|
+
status: response.status,
|
|
1556
|
+
error: errorData
|
|
1557
|
+
}, duration);
|
|
1558
|
+
throw new Error(errorData.error?.message || `Request failed with status ${response.status}`);
|
|
1559
|
+
}
|
|
1560
|
+
this.logger.log("debug", "api", `Response: ${endpoint}`, { status: response.status }, duration);
|
|
1561
|
+
return response.json();
|
|
1562
|
+
}
|
|
1563
|
+
async listFiles(folderId) {
|
|
1564
|
+
const params = new URLSearchParams({ workspaceId: this.workspaceId });
|
|
1565
|
+
if (folderId !== void 0) params.set("folderId", folderId || "null");
|
|
1566
|
+
const response = await this.request(`/nexus/files?${params.toString()}`);
|
|
1567
|
+
return response.files;
|
|
1568
|
+
}
|
|
1569
|
+
async listFolders(parentId) {
|
|
1570
|
+
const params = new URLSearchParams({ workspaceId: this.workspaceId });
|
|
1571
|
+
if (parentId !== void 0) params.set("parentId", parentId || "null");
|
|
1572
|
+
const response = await this.request(`/nexus/folders?${params.toString()}`);
|
|
1573
|
+
return response.folders;
|
|
1574
|
+
}
|
|
1575
|
+
async getFolderContents(folderId) {
|
|
1576
|
+
const params = new URLSearchParams({ workspaceId: this.workspaceId });
|
|
1577
|
+
if (folderId) params.set("folderId", folderId);
|
|
1578
|
+
return this.request(`/nexus/folders/contents?${params.toString()}`);
|
|
1579
|
+
}
|
|
1580
|
+
async getFile(fileId) {
|
|
1581
|
+
const response = await this.request(`/nexus/files/${fileId}`);
|
|
1582
|
+
return response.file;
|
|
1583
|
+
}
|
|
1584
|
+
async uploadFile(file, folderId) {
|
|
1585
|
+
const formData = new FormData();
|
|
1586
|
+
formData.append("file", file);
|
|
1587
|
+
formData.append("workspaceId", this.workspaceId);
|
|
1588
|
+
if (folderId) formData.append("folderId", folderId);
|
|
1589
|
+
const response = await fetch(`${this.baseUrl}/api/sdk/v1/nexus/upload`, {
|
|
1590
|
+
method: "POST",
|
|
1591
|
+
headers: { "x-api-key": this.apiKey },
|
|
1592
|
+
body: formData
|
|
1593
|
+
});
|
|
1594
|
+
if (!response.ok) throw new Error("Failed to upload file");
|
|
1595
|
+
const data = await response.json();
|
|
1596
|
+
return data.file;
|
|
1597
|
+
}
|
|
1598
|
+
async deleteFile(fileId) {
|
|
1599
|
+
await this.request(`/nexus/files/${fileId}`, { method: "DELETE" });
|
|
1600
|
+
}
|
|
1601
|
+
async createFolder(name, parentId) {
|
|
1602
|
+
const response = await this.request("/nexus/folders", {
|
|
1603
|
+
method: "POST",
|
|
1604
|
+
body: JSON.stringify({ workspaceId: this.workspaceId, name, parentId })
|
|
1605
|
+
});
|
|
1606
|
+
return response.folder;
|
|
1607
|
+
}
|
|
1608
|
+
async deleteFolder(folderId) {
|
|
1609
|
+
await this.request(`/nexus/folders/${folderId}`, { method: "DELETE" });
|
|
1610
|
+
}
|
|
1611
|
+
async getStats() {
|
|
1612
|
+
const response = await this.request(
|
|
1613
|
+
`/nexus/stats?workspaceId=${this.workspaceId}`
|
|
1614
|
+
);
|
|
1615
|
+
return response.stats;
|
|
1616
|
+
}
|
|
1617
|
+
async getActivity(limit = 50) {
|
|
1618
|
+
const response = await this.request(
|
|
1619
|
+
`/nexus/activity?workspaceId=${this.workspaceId}&limit=${limit}`
|
|
1620
|
+
);
|
|
1621
|
+
return response.activities;
|
|
1622
|
+
}
|
|
1623
|
+
getLogs() {
|
|
1624
|
+
return this.logger.getLogs();
|
|
1625
|
+
}
|
|
1626
|
+
clearLogs() {
|
|
1627
|
+
this.logger.clearLogs();
|
|
1628
|
+
}
|
|
1629
|
+
};
|
|
1630
|
+
|
|
1631
|
+
// src/react/SybilNexus.tsx
|
|
1632
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1633
|
+
var SybilNexus = (0, import_react3.forwardRef)(function SybilNexus2({
|
|
1634
|
+
apiKey,
|
|
1635
|
+
workspaceId,
|
|
1636
|
+
baseUrl,
|
|
1637
|
+
theme = "dark",
|
|
1638
|
+
initialFolderId = null,
|
|
1639
|
+
viewMode = "list",
|
|
1640
|
+
showSidebar = true,
|
|
1641
|
+
showActivityFeed = true,
|
|
1642
|
+
showBreadcrumbs = true,
|
|
1643
|
+
showSearch = true,
|
|
1644
|
+
allowUpload = true,
|
|
1645
|
+
allowDownload = true,
|
|
1646
|
+
allowDelete = true,
|
|
1647
|
+
allowMove = true,
|
|
1648
|
+
allowRename = true,
|
|
1649
|
+
allowCreateFolder = true,
|
|
1650
|
+
allowMultiSelect = true,
|
|
1651
|
+
maxUploadSize,
|
|
1652
|
+
acceptedFileTypes,
|
|
1653
|
+
features,
|
|
1654
|
+
logging,
|
|
1655
|
+
className,
|
|
1656
|
+
style,
|
|
1657
|
+
onReady,
|
|
1658
|
+
onNavigate,
|
|
1659
|
+
onFileSelect,
|
|
1660
|
+
onFileOpen,
|
|
1661
|
+
onFileUpload,
|
|
1662
|
+
onFileDelete,
|
|
1663
|
+
onFolderCreate,
|
|
1664
|
+
onFolderDelete,
|
|
1665
|
+
onSelectionChange,
|
|
1666
|
+
onError
|
|
1667
|
+
}, ref) {
|
|
1668
|
+
const containerRef = (0, import_react3.useRef)(null);
|
|
1669
|
+
const instanceRef = (0, import_react3.useRef)(null);
|
|
1670
|
+
(0, import_react3.useImperativeHandle)(ref, () => ({
|
|
1671
|
+
getFiles: async (folderId) => {
|
|
1672
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1673
|
+
return instanceRef.current.getFiles(folderId);
|
|
1674
|
+
},
|
|
1675
|
+
getFolders: async (parentId) => {
|
|
1676
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1677
|
+
return instanceRef.current.getFolders(parentId);
|
|
1678
|
+
},
|
|
1679
|
+
getFolderContents: async (folderId) => {
|
|
1680
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1681
|
+
return instanceRef.current.getFolderContents(folderId);
|
|
1682
|
+
},
|
|
1683
|
+
getFolderTree: async () => {
|
|
1684
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1685
|
+
return instanceRef.current.getFolderTree();
|
|
1686
|
+
},
|
|
1687
|
+
getFile: async (fileId) => {
|
|
1688
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1689
|
+
return instanceRef.current.getFile(fileId);
|
|
1690
|
+
},
|
|
1691
|
+
getFolder: async (folderId) => {
|
|
1692
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1693
|
+
return instanceRef.current.getFolder(folderId);
|
|
1694
|
+
},
|
|
1695
|
+
uploadFile: async (file, folderId, onProgress) => {
|
|
1696
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1697
|
+
return instanceRef.current.uploadFile(file, folderId, onProgress);
|
|
1698
|
+
},
|
|
1699
|
+
uploadFiles: async (files, folderId, onProgress) => {
|
|
1700
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1701
|
+
return instanceRef.current.uploadFiles(files, folderId, onProgress);
|
|
1702
|
+
},
|
|
1703
|
+
downloadFile: async (fileId) => {
|
|
1704
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1705
|
+
return instanceRef.current.downloadFile(fileId);
|
|
1706
|
+
},
|
|
1707
|
+
getDownloadUrl: async (fileId) => {
|
|
1708
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1709
|
+
return instanceRef.current.getDownloadUrl(fileId);
|
|
1710
|
+
},
|
|
1711
|
+
deleteFile: async (fileId) => {
|
|
1712
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1713
|
+
return instanceRef.current.deleteFile(fileId);
|
|
1714
|
+
},
|
|
1715
|
+
deleteFiles: async (fileIds) => {
|
|
1716
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1717
|
+
return instanceRef.current.deleteFiles(fileIds);
|
|
1718
|
+
},
|
|
1719
|
+
moveFile: async (fileId, targetFolderId) => {
|
|
1720
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1721
|
+
return instanceRef.current.moveFile(fileId, targetFolderId);
|
|
1722
|
+
},
|
|
1723
|
+
renameFile: async (fileId, newName) => {
|
|
1724
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1725
|
+
return instanceRef.current.renameFile(fileId, newName);
|
|
1726
|
+
},
|
|
1727
|
+
starFile: async (fileId, starred) => {
|
|
1728
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1729
|
+
return instanceRef.current.starFile(fileId, starred);
|
|
1730
|
+
},
|
|
1731
|
+
createFolder: async (name, parentId, options) => {
|
|
1732
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1733
|
+
return instanceRef.current.createFolder(name, parentId, options);
|
|
1734
|
+
},
|
|
1735
|
+
deleteFolder: async (folderId) => {
|
|
1736
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1737
|
+
return instanceRef.current.deleteFolder(folderId);
|
|
1738
|
+
},
|
|
1739
|
+
moveFolder: async (folderId, targetParentId) => {
|
|
1740
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1741
|
+
return instanceRef.current.moveFolder(folderId, targetParentId);
|
|
1742
|
+
},
|
|
1743
|
+
renameFolder: async (folderId, newName) => {
|
|
1744
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1745
|
+
return instanceRef.current.renameFolder(folderId, newName);
|
|
1746
|
+
},
|
|
1747
|
+
navigateTo: (folderId) => {
|
|
1748
|
+
instanceRef.current?.navigateTo(folderId);
|
|
1749
|
+
},
|
|
1750
|
+
getCurrentFolder: () => {
|
|
1751
|
+
return instanceRef.current?.getCurrentFolder() || null;
|
|
1752
|
+
},
|
|
1753
|
+
getSelection: () => {
|
|
1754
|
+
return instanceRef.current?.getSelection() || [];
|
|
1755
|
+
},
|
|
1756
|
+
setSelection: (itemIds) => {
|
|
1757
|
+
instanceRef.current?.setSelection(itemIds);
|
|
1758
|
+
},
|
|
1759
|
+
clearSelection: () => {
|
|
1760
|
+
instanceRef.current?.clearSelection();
|
|
1761
|
+
},
|
|
1762
|
+
selectAll: () => {
|
|
1763
|
+
instanceRef.current?.selectAll();
|
|
1764
|
+
},
|
|
1765
|
+
setViewMode: (mode) => {
|
|
1766
|
+
instanceRef.current?.setViewMode(mode);
|
|
1767
|
+
},
|
|
1768
|
+
toggleActivityFeed: () => {
|
|
1769
|
+
instanceRef.current?.toggleActivityFeed();
|
|
1770
|
+
},
|
|
1771
|
+
toggleSidebar: () => {
|
|
1772
|
+
instanceRef.current?.toggleSidebar();
|
|
1773
|
+
},
|
|
1774
|
+
refresh: async () => {
|
|
1775
|
+
return instanceRef.current?.refresh();
|
|
1776
|
+
},
|
|
1777
|
+
search: async (query) => {
|
|
1778
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1779
|
+
return instanceRef.current.search(query);
|
|
1780
|
+
},
|
|
1781
|
+
getStats: async () => {
|
|
1782
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1783
|
+
return instanceRef.current.getStats();
|
|
1784
|
+
},
|
|
1785
|
+
getActivity: async (limit) => {
|
|
1786
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1787
|
+
return instanceRef.current.getActivity(limit);
|
|
1788
|
+
},
|
|
1789
|
+
getLabels: async () => {
|
|
1790
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1791
|
+
return instanceRef.current.getLabels();
|
|
1792
|
+
},
|
|
1793
|
+
applyLabel: async (itemIds, labelId) => {
|
|
1794
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1795
|
+
return instanceRef.current.applyLabel(itemIds, labelId);
|
|
1796
|
+
},
|
|
1797
|
+
removeLabel: async (itemIds, labelId) => {
|
|
1798
|
+
if (!instanceRef.current) throw new Error("Nexus not initialized");
|
|
1799
|
+
return instanceRef.current.removeLabel(itemIds, labelId);
|
|
1800
|
+
},
|
|
1801
|
+
setTheme: (newTheme) => {
|
|
1802
|
+
instanceRef.current?.setTheme(newTheme);
|
|
1803
|
+
},
|
|
1804
|
+
getLogs: () => {
|
|
1805
|
+
return instanceRef.current?.getLogs() || [];
|
|
1806
|
+
},
|
|
1807
|
+
clearLogs: () => {
|
|
1808
|
+
instanceRef.current?.clearLogs();
|
|
1809
|
+
}
|
|
1810
|
+
}));
|
|
1811
|
+
(0, import_react3.useEffect)(() => {
|
|
1812
|
+
if (!containerRef.current || !apiKey || !workspaceId) return;
|
|
1813
|
+
instanceRef.current?.destroy();
|
|
1814
|
+
const config = {
|
|
1815
|
+
apiKey,
|
|
1816
|
+
workspaceId,
|
|
1817
|
+
container: containerRef.current,
|
|
1818
|
+
baseUrl,
|
|
1819
|
+
theme,
|
|
1820
|
+
initialFolderId,
|
|
1821
|
+
viewMode,
|
|
1822
|
+
showSidebar,
|
|
1823
|
+
showActivityFeed,
|
|
1824
|
+
showBreadcrumbs,
|
|
1825
|
+
showSearch,
|
|
1826
|
+
allowUpload,
|
|
1827
|
+
allowDownload,
|
|
1828
|
+
allowDelete,
|
|
1829
|
+
allowMove,
|
|
1830
|
+
allowRename,
|
|
1831
|
+
allowCreateFolder,
|
|
1832
|
+
allowMultiSelect,
|
|
1833
|
+
maxUploadSize,
|
|
1834
|
+
acceptedFileTypes,
|
|
1835
|
+
features,
|
|
1836
|
+
logging,
|
|
1837
|
+
onReady,
|
|
1838
|
+
onNavigate,
|
|
1839
|
+
onFileSelect,
|
|
1840
|
+
onFileOpen,
|
|
1841
|
+
onFileUpload,
|
|
1842
|
+
onFileDelete,
|
|
1843
|
+
onFolderCreate,
|
|
1844
|
+
onFolderDelete,
|
|
1845
|
+
onSelectionChange,
|
|
1846
|
+
onError
|
|
1847
|
+
};
|
|
1848
|
+
instanceRef.current = embedNexus(config);
|
|
1849
|
+
return () => {
|
|
1850
|
+
instanceRef.current?.destroy();
|
|
1851
|
+
instanceRef.current = null;
|
|
1852
|
+
};
|
|
1853
|
+
}, [apiKey, workspaceId, baseUrl]);
|
|
1854
|
+
(0, import_react3.useEffect)(() => {
|
|
1855
|
+
instanceRef.current?.setTheme(theme);
|
|
1856
|
+
}, [theme]);
|
|
1857
|
+
(0, import_react3.useEffect)(() => {
|
|
1858
|
+
instanceRef.current?.setViewMode(viewMode);
|
|
1859
|
+
}, [viewMode]);
|
|
1860
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1861
|
+
"div",
|
|
1862
|
+
{
|
|
1863
|
+
ref: containerRef,
|
|
1864
|
+
className,
|
|
1865
|
+
style: {
|
|
1866
|
+
width: "100%",
|
|
1867
|
+
height: "100%",
|
|
1868
|
+
minHeight: "500px",
|
|
1869
|
+
...style
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
);
|
|
1873
|
+
});
|
|
1874
|
+
|
|
440
1875
|
// src/react/hooks.ts
|
|
441
|
-
var
|
|
1876
|
+
var import_react4 = require("react");
|
|
442
1877
|
function useSybilPages(options) {
|
|
443
1878
|
const { apiKey, baseUrl } = options;
|
|
444
|
-
const [page, setPage] = (0,
|
|
445
|
-
const [loading, setLoading] = (0,
|
|
446
|
-
const [saving, setSaving] = (0,
|
|
447
|
-
const [error, setError] = (0,
|
|
448
|
-
const sdkRef = (0,
|
|
449
|
-
const pendingBlocksRef = (0,
|
|
450
|
-
(0,
|
|
1879
|
+
const [page, setPage] = (0, import_react4.useState)(null);
|
|
1880
|
+
const [loading, setLoading] = (0, import_react4.useState)(false);
|
|
1881
|
+
const [saving, setSaving] = (0, import_react4.useState)(false);
|
|
1882
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1883
|
+
const sdkRef = (0, import_react4.useRef)(null);
|
|
1884
|
+
const pendingBlocksRef = (0, import_react4.useRef)(null);
|
|
1885
|
+
(0, import_react4.useEffect)(() => {
|
|
451
1886
|
sdkRef.current = new SybilSDK({
|
|
452
1887
|
apiKey,
|
|
453
1888
|
baseUrl: baseUrl ? `${baseUrl}/api/sdk/v1` : void 0
|
|
454
1889
|
});
|
|
455
1890
|
}, [apiKey, baseUrl]);
|
|
456
|
-
const fetchPage = (0,
|
|
1891
|
+
const fetchPage = (0, import_react4.useCallback)(async (pageId) => {
|
|
457
1892
|
if (!sdkRef.current) return;
|
|
458
1893
|
setLoading(true);
|
|
459
1894
|
setError(null);
|
|
@@ -466,7 +1901,7 @@ function useSybilPages(options) {
|
|
|
466
1901
|
setLoading(false);
|
|
467
1902
|
}
|
|
468
1903
|
}, []);
|
|
469
|
-
const createPage = (0,
|
|
1904
|
+
const createPage = (0, import_react4.useCallback)(async (params = {}) => {
|
|
470
1905
|
if (!sdkRef.current) throw new Error("SDK not initialized");
|
|
471
1906
|
setLoading(true);
|
|
472
1907
|
setError(null);
|
|
@@ -482,7 +1917,7 @@ function useSybilPages(options) {
|
|
|
482
1917
|
setLoading(false);
|
|
483
1918
|
}
|
|
484
1919
|
}, []);
|
|
485
|
-
const updatePage = (0,
|
|
1920
|
+
const updatePage = (0, import_react4.useCallback)(async (pageId, params) => {
|
|
486
1921
|
if (!sdkRef.current) throw new Error("SDK not initialized");
|
|
487
1922
|
setSaving(true);
|
|
488
1923
|
setError(null);
|
|
@@ -498,7 +1933,7 @@ function useSybilPages(options) {
|
|
|
498
1933
|
setSaving(false);
|
|
499
1934
|
}
|
|
500
1935
|
}, []);
|
|
501
|
-
const deletePage = (0,
|
|
1936
|
+
const deletePage = (0, import_react4.useCallback)(async (pageId) => {
|
|
502
1937
|
if (!sdkRef.current) throw new Error("SDK not initialized");
|
|
503
1938
|
setLoading(true);
|
|
504
1939
|
setError(null);
|
|
@@ -513,11 +1948,11 @@ function useSybilPages(options) {
|
|
|
513
1948
|
setLoading(false);
|
|
514
1949
|
}
|
|
515
1950
|
}, []);
|
|
516
|
-
const setBlocks = (0,
|
|
1951
|
+
const setBlocks = (0, import_react4.useCallback)((blocks) => {
|
|
517
1952
|
pendingBlocksRef.current = blocks;
|
|
518
1953
|
setPage((prev) => prev ? { ...prev, blocks } : null);
|
|
519
1954
|
}, []);
|
|
520
|
-
const save = (0,
|
|
1955
|
+
const save = (0, import_react4.useCallback)(async () => {
|
|
521
1956
|
if (!page || !sdkRef.current || !pendingBlocksRef.current) return;
|
|
522
1957
|
await updatePage(page.id, { blocks: pendingBlocksRef.current });
|
|
523
1958
|
pendingBlocksRef.current = null;
|
|
@@ -535,8 +1970,385 @@ function useSybilPages(options) {
|
|
|
535
1970
|
save
|
|
536
1971
|
};
|
|
537
1972
|
}
|
|
1973
|
+
|
|
1974
|
+
// src/react/hooks/useAtlas.ts
|
|
1975
|
+
var import_react5 = require("react");
|
|
1976
|
+
function useAtlas(options) {
|
|
1977
|
+
const { apiKey, workspaceId, baseUrl, logging } = options;
|
|
1978
|
+
const [sidebar, setSidebar] = (0, import_react5.useState)(null);
|
|
1979
|
+
const [currentPage, setCurrentPage] = (0, import_react5.useState)(null);
|
|
1980
|
+
const [loading, setLoading] = (0, import_react5.useState)(false);
|
|
1981
|
+
const [saving, setSaving] = (0, import_react5.useState)(false);
|
|
1982
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
1983
|
+
const clientRef = (0, import_react5.useRef)(null);
|
|
1984
|
+
(0, import_react5.useEffect)(() => {
|
|
1985
|
+
clientRef.current = new AtlasClient({
|
|
1986
|
+
apiKey,
|
|
1987
|
+
workspaceId,
|
|
1988
|
+
baseUrl,
|
|
1989
|
+
logging
|
|
1990
|
+
});
|
|
1991
|
+
}, [apiKey, workspaceId, baseUrl, logging]);
|
|
1992
|
+
const fetchSidebar = (0, import_react5.useCallback)(async () => {
|
|
1993
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
1994
|
+
setLoading(true);
|
|
1995
|
+
setError(null);
|
|
1996
|
+
try {
|
|
1997
|
+
const data = await clientRef.current.getSidebar();
|
|
1998
|
+
setSidebar(data);
|
|
1999
|
+
return data;
|
|
2000
|
+
} catch (err) {
|
|
2001
|
+
const error2 = err instanceof Error ? err : new Error("Failed to fetch sidebar");
|
|
2002
|
+
setError(error2);
|
|
2003
|
+
throw error2;
|
|
2004
|
+
} finally {
|
|
2005
|
+
setLoading(false);
|
|
2006
|
+
}
|
|
2007
|
+
}, []);
|
|
2008
|
+
const fetchPage = (0, import_react5.useCallback)(async (pageId) => {
|
|
2009
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2010
|
+
setLoading(true);
|
|
2011
|
+
setError(null);
|
|
2012
|
+
try {
|
|
2013
|
+
const page = await clientRef.current.getPage(pageId);
|
|
2014
|
+
setCurrentPage(page);
|
|
2015
|
+
return page;
|
|
2016
|
+
} catch (err) {
|
|
2017
|
+
const error2 = err instanceof Error ? err : new Error("Failed to fetch page");
|
|
2018
|
+
setError(error2);
|
|
2019
|
+
throw error2;
|
|
2020
|
+
} finally {
|
|
2021
|
+
setLoading(false);
|
|
2022
|
+
}
|
|
2023
|
+
}, []);
|
|
2024
|
+
const createPage = (0, import_react5.useCallback)(async (params = {}) => {
|
|
2025
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2026
|
+
setSaving(true);
|
|
2027
|
+
setError(null);
|
|
2028
|
+
try {
|
|
2029
|
+
const page = await clientRef.current.createPage(params);
|
|
2030
|
+
await fetchSidebar();
|
|
2031
|
+
return page;
|
|
2032
|
+
} catch (err) {
|
|
2033
|
+
const error2 = err instanceof Error ? err : new Error("Failed to create page");
|
|
2034
|
+
setError(error2);
|
|
2035
|
+
throw error2;
|
|
2036
|
+
} finally {
|
|
2037
|
+
setSaving(false);
|
|
2038
|
+
}
|
|
2039
|
+
}, [fetchSidebar]);
|
|
2040
|
+
const updatePage = (0, import_react5.useCallback)(async (pageId, params) => {
|
|
2041
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2042
|
+
setSaving(true);
|
|
2043
|
+
setError(null);
|
|
2044
|
+
try {
|
|
2045
|
+
const page = await clientRef.current.updatePage(pageId, params);
|
|
2046
|
+
setCurrentPage(page);
|
|
2047
|
+
await fetchSidebar();
|
|
2048
|
+
return page;
|
|
2049
|
+
} catch (err) {
|
|
2050
|
+
const error2 = err instanceof Error ? err : new Error("Failed to update page");
|
|
2051
|
+
setError(error2);
|
|
2052
|
+
throw error2;
|
|
2053
|
+
} finally {
|
|
2054
|
+
setSaving(false);
|
|
2055
|
+
}
|
|
2056
|
+
}, [fetchSidebar]);
|
|
2057
|
+
const deletePage = (0, import_react5.useCallback)(async (pageId) => {
|
|
2058
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2059
|
+
setSaving(true);
|
|
2060
|
+
setError(null);
|
|
2061
|
+
try {
|
|
2062
|
+
await clientRef.current.deletePage(pageId);
|
|
2063
|
+
if (currentPage?.id === pageId) {
|
|
2064
|
+
setCurrentPage(null);
|
|
2065
|
+
}
|
|
2066
|
+
await fetchSidebar();
|
|
2067
|
+
} catch (err) {
|
|
2068
|
+
const error2 = err instanceof Error ? err : new Error("Failed to delete page");
|
|
2069
|
+
setError(error2);
|
|
2070
|
+
throw error2;
|
|
2071
|
+
} finally {
|
|
2072
|
+
setSaving(false);
|
|
2073
|
+
}
|
|
2074
|
+
}, [currentPage, fetchSidebar]);
|
|
2075
|
+
const toggleFavorite = (0, import_react5.useCallback)(async (pageId) => {
|
|
2076
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2077
|
+
try {
|
|
2078
|
+
const page = await clientRef.current.toggleFavorite(pageId);
|
|
2079
|
+
if (currentPage?.id === pageId) {
|
|
2080
|
+
setCurrentPage(page);
|
|
2081
|
+
}
|
|
2082
|
+
await fetchSidebar();
|
|
2083
|
+
return page;
|
|
2084
|
+
} catch (err) {
|
|
2085
|
+
const error2 = err instanceof Error ? err : new Error("Failed to toggle favorite");
|
|
2086
|
+
setError(error2);
|
|
2087
|
+
throw error2;
|
|
2088
|
+
}
|
|
2089
|
+
}, [currentPage, fetchSidebar]);
|
|
2090
|
+
const exportPage = (0, import_react5.useCallback)(async (pageId, format) => {
|
|
2091
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2092
|
+
setLoading(true);
|
|
2093
|
+
try {
|
|
2094
|
+
return await clientRef.current.exportPage(pageId, format);
|
|
2095
|
+
} catch (err) {
|
|
2096
|
+
const error2 = err instanceof Error ? err : new Error("Failed to export page");
|
|
2097
|
+
setError(error2);
|
|
2098
|
+
throw error2;
|
|
2099
|
+
} finally {
|
|
2100
|
+
setLoading(false);
|
|
2101
|
+
}
|
|
2102
|
+
}, []);
|
|
2103
|
+
const getLogs = (0, import_react5.useCallback)(() => {
|
|
2104
|
+
return clientRef.current?.getLogs() || [];
|
|
2105
|
+
}, []);
|
|
2106
|
+
const clearLogs = (0, import_react5.useCallback)(() => {
|
|
2107
|
+
clientRef.current?.clearLogs();
|
|
2108
|
+
}, []);
|
|
2109
|
+
return {
|
|
2110
|
+
sidebar,
|
|
2111
|
+
currentPage,
|
|
2112
|
+
loading,
|
|
2113
|
+
saving,
|
|
2114
|
+
error,
|
|
2115
|
+
fetchSidebar,
|
|
2116
|
+
fetchPage,
|
|
2117
|
+
createPage,
|
|
2118
|
+
updatePage,
|
|
2119
|
+
deletePage,
|
|
2120
|
+
toggleFavorite,
|
|
2121
|
+
exportPage,
|
|
2122
|
+
setCurrentPage,
|
|
2123
|
+
getLogs,
|
|
2124
|
+
clearLogs
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
// src/react/hooks/useNexus.ts
|
|
2129
|
+
var import_react6 = require("react");
|
|
2130
|
+
function useNexus(options) {
|
|
2131
|
+
const { apiKey, workspaceId, baseUrl, logging } = options;
|
|
2132
|
+
const [files, setFiles] = (0, import_react6.useState)([]);
|
|
2133
|
+
const [folders, setFolders] = (0, import_react6.useState)([]);
|
|
2134
|
+
const [currentFolder, setCurrentFolder] = (0, import_react6.useState)(null);
|
|
2135
|
+
const [breadcrumb, setBreadcrumb] = (0, import_react6.useState)([]);
|
|
2136
|
+
const [loading, setLoading] = (0, import_react6.useState)(false);
|
|
2137
|
+
const [uploading, setUploading] = (0, import_react6.useState)(false);
|
|
2138
|
+
const [uploadProgress, setUploadProgress] = (0, import_react6.useState)(0);
|
|
2139
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
2140
|
+
const clientRef = (0, import_react6.useRef)(null);
|
|
2141
|
+
(0, import_react6.useEffect)(() => {
|
|
2142
|
+
clientRef.current = new NexusClient({
|
|
2143
|
+
apiKey,
|
|
2144
|
+
workspaceId,
|
|
2145
|
+
baseUrl,
|
|
2146
|
+
logging
|
|
2147
|
+
});
|
|
2148
|
+
}, [apiKey, workspaceId, baseUrl, logging]);
|
|
2149
|
+
const fetchFiles = (0, import_react6.useCallback)(async (folderId) => {
|
|
2150
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2151
|
+
setLoading(true);
|
|
2152
|
+
setError(null);
|
|
2153
|
+
try {
|
|
2154
|
+
const data = await clientRef.current.listFiles(folderId);
|
|
2155
|
+
setFiles(data);
|
|
2156
|
+
return data;
|
|
2157
|
+
} catch (err) {
|
|
2158
|
+
const error2 = err instanceof Error ? err : new Error("Failed to fetch files");
|
|
2159
|
+
setError(error2);
|
|
2160
|
+
throw error2;
|
|
2161
|
+
} finally {
|
|
2162
|
+
setLoading(false);
|
|
2163
|
+
}
|
|
2164
|
+
}, []);
|
|
2165
|
+
const fetchFolders = (0, import_react6.useCallback)(async (parentId) => {
|
|
2166
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2167
|
+
setLoading(true);
|
|
2168
|
+
setError(null);
|
|
2169
|
+
try {
|
|
2170
|
+
const data = await clientRef.current.listFolders(parentId);
|
|
2171
|
+
setFolders(data);
|
|
2172
|
+
return data;
|
|
2173
|
+
} catch (err) {
|
|
2174
|
+
const error2 = err instanceof Error ? err : new Error("Failed to fetch folders");
|
|
2175
|
+
setError(error2);
|
|
2176
|
+
throw error2;
|
|
2177
|
+
} finally {
|
|
2178
|
+
setLoading(false);
|
|
2179
|
+
}
|
|
2180
|
+
}, []);
|
|
2181
|
+
const fetchFolderContents = (0, import_react6.useCallback)(async (folderId) => {
|
|
2182
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2183
|
+
setLoading(true);
|
|
2184
|
+
setError(null);
|
|
2185
|
+
try {
|
|
2186
|
+
const data = await clientRef.current.getFolderContents(folderId);
|
|
2187
|
+
setBreadcrumb(data.breadcrumb);
|
|
2188
|
+
setCurrentFolder(folderId || null);
|
|
2189
|
+
return data;
|
|
2190
|
+
} catch (err) {
|
|
2191
|
+
const error2 = err instanceof Error ? err : new Error("Failed to fetch folder contents");
|
|
2192
|
+
setError(error2);
|
|
2193
|
+
throw error2;
|
|
2194
|
+
} finally {
|
|
2195
|
+
setLoading(false);
|
|
2196
|
+
}
|
|
2197
|
+
}, []);
|
|
2198
|
+
const getFile = (0, import_react6.useCallback)(async (fileId) => {
|
|
2199
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2200
|
+
setLoading(true);
|
|
2201
|
+
setError(null);
|
|
2202
|
+
try {
|
|
2203
|
+
return await clientRef.current.getFile(fileId);
|
|
2204
|
+
} catch (err) {
|
|
2205
|
+
const error2 = err instanceof Error ? err : new Error("Failed to get file");
|
|
2206
|
+
setError(error2);
|
|
2207
|
+
throw error2;
|
|
2208
|
+
} finally {
|
|
2209
|
+
setLoading(false);
|
|
2210
|
+
}
|
|
2211
|
+
}, []);
|
|
2212
|
+
const uploadFile = (0, import_react6.useCallback)(async (file, folderId) => {
|
|
2213
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2214
|
+
setUploading(true);
|
|
2215
|
+
setUploadProgress(0);
|
|
2216
|
+
setError(null);
|
|
2217
|
+
try {
|
|
2218
|
+
const result = await clientRef.current.uploadFile(file, folderId);
|
|
2219
|
+
await fetchFiles(folderId);
|
|
2220
|
+
return result;
|
|
2221
|
+
} catch (err) {
|
|
2222
|
+
const error2 = err instanceof Error ? err : new Error("Failed to upload file");
|
|
2223
|
+
setError(error2);
|
|
2224
|
+
throw error2;
|
|
2225
|
+
} finally {
|
|
2226
|
+
setUploading(false);
|
|
2227
|
+
setUploadProgress(0);
|
|
2228
|
+
}
|
|
2229
|
+
}, [fetchFiles]);
|
|
2230
|
+
const uploadFiles = (0, import_react6.useCallback)(async (filesToUpload, folderId) => {
|
|
2231
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2232
|
+
setUploading(true);
|
|
2233
|
+
setUploadProgress(0);
|
|
2234
|
+
setError(null);
|
|
2235
|
+
const results = [];
|
|
2236
|
+
try {
|
|
2237
|
+
for (let i = 0; i < filesToUpload.length; i++) {
|
|
2238
|
+
const result = await clientRef.current.uploadFile(filesToUpload[i], folderId);
|
|
2239
|
+
results.push(result);
|
|
2240
|
+
setUploadProgress((i + 1) / filesToUpload.length * 100);
|
|
2241
|
+
}
|
|
2242
|
+
await fetchFiles(folderId);
|
|
2243
|
+
return results;
|
|
2244
|
+
} catch (err) {
|
|
2245
|
+
const error2 = err instanceof Error ? err : new Error("Failed to upload files");
|
|
2246
|
+
setError(error2);
|
|
2247
|
+
throw error2;
|
|
2248
|
+
} finally {
|
|
2249
|
+
setUploading(false);
|
|
2250
|
+
setUploadProgress(0);
|
|
2251
|
+
}
|
|
2252
|
+
}, [fetchFiles]);
|
|
2253
|
+
const deleteFile = (0, import_react6.useCallback)(async (fileId) => {
|
|
2254
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2255
|
+
setLoading(true);
|
|
2256
|
+
setError(null);
|
|
2257
|
+
try {
|
|
2258
|
+
await clientRef.current.deleteFile(fileId);
|
|
2259
|
+
await fetchFiles(currentFolder);
|
|
2260
|
+
} catch (err) {
|
|
2261
|
+
const error2 = err instanceof Error ? err : new Error("Failed to delete file");
|
|
2262
|
+
setError(error2);
|
|
2263
|
+
throw error2;
|
|
2264
|
+
} finally {
|
|
2265
|
+
setLoading(false);
|
|
2266
|
+
}
|
|
2267
|
+
}, [currentFolder, fetchFiles]);
|
|
2268
|
+
const createFolder = (0, import_react6.useCallback)(async (name, parentId) => {
|
|
2269
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2270
|
+
setLoading(true);
|
|
2271
|
+
setError(null);
|
|
2272
|
+
try {
|
|
2273
|
+
const result = await clientRef.current.createFolder(name, parentId);
|
|
2274
|
+
await fetchFolders(parentId);
|
|
2275
|
+
return result;
|
|
2276
|
+
} catch (err) {
|
|
2277
|
+
const error2 = err instanceof Error ? err : new Error("Failed to create folder");
|
|
2278
|
+
setError(error2);
|
|
2279
|
+
throw error2;
|
|
2280
|
+
} finally {
|
|
2281
|
+
setLoading(false);
|
|
2282
|
+
}
|
|
2283
|
+
}, [fetchFolders]);
|
|
2284
|
+
const deleteFolder = (0, import_react6.useCallback)(async (folderId) => {
|
|
2285
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2286
|
+
setLoading(true);
|
|
2287
|
+
setError(null);
|
|
2288
|
+
try {
|
|
2289
|
+
await clientRef.current.deleteFolder(folderId);
|
|
2290
|
+
await fetchFolders(currentFolder);
|
|
2291
|
+
} catch (err) {
|
|
2292
|
+
const error2 = err instanceof Error ? err : new Error("Failed to delete folder");
|
|
2293
|
+
setError(error2);
|
|
2294
|
+
throw error2;
|
|
2295
|
+
} finally {
|
|
2296
|
+
setLoading(false);
|
|
2297
|
+
}
|
|
2298
|
+
}, [currentFolder, fetchFolders]);
|
|
2299
|
+
const navigateTo = (0, import_react6.useCallback)((folderId) => {
|
|
2300
|
+
setCurrentFolder(folderId);
|
|
2301
|
+
fetchFolderContents(folderId);
|
|
2302
|
+
}, [fetchFolderContents]);
|
|
2303
|
+
const getStats = (0, import_react6.useCallback)(async () => {
|
|
2304
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2305
|
+
return clientRef.current.getStats();
|
|
2306
|
+
}, []);
|
|
2307
|
+
const getActivity = (0, import_react6.useCallback)(async (limit) => {
|
|
2308
|
+
if (!clientRef.current) throw new Error("Client not initialized");
|
|
2309
|
+
return clientRef.current.getActivity(limit);
|
|
2310
|
+
}, []);
|
|
2311
|
+
const refresh = (0, import_react6.useCallback)(async () => {
|
|
2312
|
+
await fetchFolderContents(currentFolder);
|
|
2313
|
+
}, [currentFolder, fetchFolderContents]);
|
|
2314
|
+
const getLogs = (0, import_react6.useCallback)(() => {
|
|
2315
|
+
return clientRef.current?.getLogs() || [];
|
|
2316
|
+
}, []);
|
|
2317
|
+
const clearLogs = (0, import_react6.useCallback)(() => {
|
|
2318
|
+
clientRef.current?.clearLogs();
|
|
2319
|
+
}, []);
|
|
2320
|
+
return {
|
|
2321
|
+
files,
|
|
2322
|
+
folders,
|
|
2323
|
+
currentFolder,
|
|
2324
|
+
breadcrumb,
|
|
2325
|
+
loading,
|
|
2326
|
+
uploading,
|
|
2327
|
+
uploadProgress,
|
|
2328
|
+
error,
|
|
2329
|
+
fetchFiles,
|
|
2330
|
+
fetchFolders,
|
|
2331
|
+
fetchFolderContents,
|
|
2332
|
+
getFile,
|
|
2333
|
+
uploadFile,
|
|
2334
|
+
uploadFiles,
|
|
2335
|
+
deleteFile,
|
|
2336
|
+
createFolder,
|
|
2337
|
+
deleteFolder,
|
|
2338
|
+
navigateTo,
|
|
2339
|
+
getStats,
|
|
2340
|
+
getActivity,
|
|
2341
|
+
refresh,
|
|
2342
|
+
getLogs,
|
|
2343
|
+
clearLogs
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
538
2346
|
// Annotate the CommonJS export names for ESM import in node:
|
|
539
2347
|
0 && (module.exports = {
|
|
2348
|
+
SybilAtlas,
|
|
2349
|
+
SybilNexus,
|
|
540
2350
|
SybilPages,
|
|
2351
|
+
useAtlas,
|
|
2352
|
+
useNexus,
|
|
541
2353
|
useSybilPages
|
|
542
2354
|
});
|