@palettelab/sdk 0.1.14 → 0.1.16
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 +46 -2
- package/dist/components/index.d.mts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/{index-Bu5EQGYo.d.mts → index-BGT6xBGD.d.mts} +1 -1
- package/dist/{index-BDVWt7DE.d.ts → index-Beo6F2Fr.d.ts} +1 -1
- package/dist/index.d.mts +38 -4
- package/dist/index.d.ts +38 -4
- package/dist/index.js +410 -32
- package/dist/index.mjs +411 -31
- package/dist/{plugin-UV46q1mU.d.mts → plugin-CG6spHKI.d.mts} +3 -1
- package/dist/{plugin-UV46q1mU.d.ts → plugin-CG6spHKI.d.ts} +3 -1
- package/dist/router/index.d.mts +346 -0
- package/dist/router/index.d.ts +346 -0
- package/dist/router/index.js +247 -0
- package/dist/router/index.mjs +225 -0
- package/dist/types/index.d.mts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -21,8 +21,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
DataRoomClient: () => DataRoomClient,
|
|
24
|
+
Link: () => Link,
|
|
24
25
|
OrganizationClient: () => OrganizationClient,
|
|
25
26
|
PaletteApiError: () => PaletteApiError,
|
|
27
|
+
PaletteAppRouter: () => PaletteAppRouter,
|
|
26
28
|
PlatformCtx: () => PlatformCtx,
|
|
27
29
|
PluginProvider: () => PluginProvider,
|
|
28
30
|
StorageClient: () => StorageClient,
|
|
@@ -42,15 +44,20 @@ __export(src_exports, {
|
|
|
42
44
|
isPaletteApiError: () => isPaletteApiError,
|
|
43
45
|
isSandboxRuntime: () => isSandboxRuntime,
|
|
44
46
|
normalizePaletteLanguage: () => normalizePaletteLanguage,
|
|
47
|
+
notFound: () => notFound,
|
|
45
48
|
setBaseUrl: () => setBaseUrl,
|
|
46
49
|
translate: () => translate,
|
|
47
50
|
updateInstallConfig: () => updateInstallConfig,
|
|
48
51
|
uploadToSignedUrl: () => uploadToSignedUrl,
|
|
52
|
+
useParams: () => useParams,
|
|
53
|
+
usePathname: () => usePathname,
|
|
49
54
|
usePlatform: () => usePlatform,
|
|
50
55
|
usePluginChat: () => usePluginChat,
|
|
51
56
|
usePluginDataRooms: () => usePluginDataRooms,
|
|
52
57
|
usePluginTasks: () => usePluginTasks,
|
|
53
58
|
usePluginTranslations: () => usePluginTranslations,
|
|
59
|
+
useRouter: () => useRouter,
|
|
60
|
+
useSearchParams: () => useSearchParams,
|
|
54
61
|
withPluginProvider: () => withPluginProvider
|
|
55
62
|
});
|
|
56
63
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -228,6 +235,7 @@ function createMockPlatformContext(overrides = {}) {
|
|
|
228
235
|
apiFetch: async () => new Response(JSON.stringify({}), { status: 200 }),
|
|
229
236
|
navigate: () => {
|
|
230
237
|
},
|
|
238
|
+
routePath: "/",
|
|
231
239
|
showToast: () => {
|
|
232
240
|
},
|
|
233
241
|
...overrides
|
|
@@ -359,6 +367,8 @@ function hasAllPermissions(ctx, permissions) {
|
|
|
359
367
|
}
|
|
360
368
|
|
|
361
369
|
// src/storage.ts
|
|
370
|
+
var DEFAULT_CHUNK_SIZE = 8 * 1024 * 1024;
|
|
371
|
+
var MIN_CHUNK_SIZE = 256 * 1024;
|
|
362
372
|
async function uploadToSignedUrl(uploadUrl, file, contentType = "application/octet-stream") {
|
|
363
373
|
const res = await fetch(uploadUrl, {
|
|
364
374
|
method: "PUT",
|
|
@@ -367,10 +377,178 @@ async function uploadToSignedUrl(uploadUrl, file, contentType = "application/oct
|
|
|
367
377
|
});
|
|
368
378
|
if (!res.ok) throw new Error(`Upload failed: ${res.statusText}`);
|
|
369
379
|
}
|
|
380
|
+
function normalizeChunkSize(value) {
|
|
381
|
+
const raw = Math.max(value || DEFAULT_CHUNK_SIZE, MIN_CHUNK_SIZE);
|
|
382
|
+
return Math.ceil(raw / MIN_CHUNK_SIZE) * MIN_CHUNK_SIZE;
|
|
383
|
+
}
|
|
384
|
+
function defaultPluginId() {
|
|
385
|
+
if (typeof window === "undefined") return "";
|
|
386
|
+
const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
|
|
387
|
+
return match ? decodeURIComponent(match[1]) : "";
|
|
388
|
+
}
|
|
389
|
+
function fileFingerprint(pluginId, file, key) {
|
|
390
|
+
return [pluginId, key || file.name, file.size, file.lastModified].join(":");
|
|
391
|
+
}
|
|
392
|
+
function sessionStorageKey(pluginId, fingerprint) {
|
|
393
|
+
return `palette:storage-upload:${pluginId}:${fingerprint}`;
|
|
394
|
+
}
|
|
395
|
+
function readStoredSession(pluginId, fingerprint) {
|
|
396
|
+
if (typeof window === "undefined") return null;
|
|
397
|
+
try {
|
|
398
|
+
const raw = window.localStorage.getItem(sessionStorageKey(pluginId, fingerprint));
|
|
399
|
+
if (!raw) return null;
|
|
400
|
+
const session = JSON.parse(raw);
|
|
401
|
+
return session.plugin_id === pluginId && session.fingerprint === fingerprint ? session : null;
|
|
402
|
+
} catch {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function writeStoredSession(pluginId, fingerprint, session) {
|
|
407
|
+
if (typeof window === "undefined") return;
|
|
408
|
+
const stored = { ...session, plugin_id: pluginId, fingerprint, updated_at: Date.now() };
|
|
409
|
+
window.localStorage.setItem(sessionStorageKey(pluginId, fingerprint), JSON.stringify(stored));
|
|
410
|
+
}
|
|
411
|
+
function clearStoredSession(pluginId, fingerprint) {
|
|
412
|
+
if (typeof window === "undefined") return;
|
|
413
|
+
window.localStorage.removeItem(sessionStorageKey(pluginId, fingerprint));
|
|
414
|
+
}
|
|
415
|
+
function absoluteApiUrl(pathOrUrl) {
|
|
416
|
+
return /^https?:\/\//i.test(pathOrUrl) ? pathOrUrl : `${getBaseUrl()}${pathOrUrl}`;
|
|
417
|
+
}
|
|
418
|
+
function isPaletteApiUpload(url) {
|
|
419
|
+
return url.startsWith(getBaseUrl()) || url.startsWith("/");
|
|
420
|
+
}
|
|
421
|
+
function report(loaded, total, chunkIndex, chunkCount, state, onProgress) {
|
|
422
|
+
onProgress?.({
|
|
423
|
+
loaded,
|
|
424
|
+
total,
|
|
425
|
+
percentage: total > 0 ? Math.min(100, Math.round(loaded / total * 1e4) / 100) : 100,
|
|
426
|
+
chunkIndex,
|
|
427
|
+
chunkCount,
|
|
428
|
+
state
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
function xhrPut(url, body, headers, signal, onUploadProgress) {
|
|
432
|
+
return new Promise((resolve, reject) => {
|
|
433
|
+
const xhr = new XMLHttpRequest();
|
|
434
|
+
xhr.open("PUT", absoluteApiUrl(url), true);
|
|
435
|
+
xhr.withCredentials = isPaletteApiUpload(url);
|
|
436
|
+
for (const [key, value] of Object.entries(headers)) xhr.setRequestHeader(key, value);
|
|
437
|
+
xhr.upload.onprogress = (event) => {
|
|
438
|
+
if (event.lengthComputable) onUploadProgress?.(event.loaded);
|
|
439
|
+
};
|
|
440
|
+
xhr.onload = () => {
|
|
441
|
+
const ok = [200, 201, 204, 308].includes(xhr.status);
|
|
442
|
+
if (!ok) reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));
|
|
443
|
+
else resolve({ status: xhr.status, range: xhr.getResponseHeader("Range") });
|
|
444
|
+
};
|
|
445
|
+
xhr.onerror = () => reject(new Error("Upload failed"));
|
|
446
|
+
xhr.onabort = () => reject(new DOMException("Upload aborted", "AbortError"));
|
|
447
|
+
if (signal) {
|
|
448
|
+
if (signal.aborted) {
|
|
449
|
+
xhr.abort();
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
signal.addEventListener("abort", () => xhr.abort(), { once: true });
|
|
453
|
+
}
|
|
454
|
+
xhr.send(body);
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
function uploadedFromRange(range) {
|
|
458
|
+
if (!range) return 0;
|
|
459
|
+
const match = range.match(/bytes=0-(\d+)/);
|
|
460
|
+
return match ? Number(match[1]) + 1 : 0;
|
|
461
|
+
}
|
|
462
|
+
async function queryGcsOffset(session) {
|
|
463
|
+
try {
|
|
464
|
+
const result = await xhrPut(session.upload_url, new Blob([]), {
|
|
465
|
+
"Content-Range": `bytes */${session.size}`
|
|
466
|
+
});
|
|
467
|
+
if ([200, 201, 204].includes(result.status)) return session.size;
|
|
468
|
+
return uploadedFromRange(result.range);
|
|
469
|
+
} catch {
|
|
470
|
+
return 0;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
async function queryLocalOffset(session) {
|
|
474
|
+
const res = await fetch(absoluteApiUrl(session.status_url), { credentials: "include" });
|
|
475
|
+
if (!res.ok) return 0;
|
|
476
|
+
const body = await res.json();
|
|
477
|
+
return Number(body.uploaded_bytes || 0);
|
|
478
|
+
}
|
|
479
|
+
async function queryOffset(session) {
|
|
480
|
+
if (session.mode === "local_resumable") return queryLocalOffset(session);
|
|
481
|
+
return queryGcsOffset(session);
|
|
482
|
+
}
|
|
370
483
|
var StorageClient = class {
|
|
371
|
-
constructor() {
|
|
484
|
+
constructor(ctx) {
|
|
485
|
+
this.ctx = ctx;
|
|
372
486
|
this.uploadToSignedUrl = uploadToSignedUrl;
|
|
373
487
|
}
|
|
488
|
+
pluginId(explicit) {
|
|
489
|
+
const resolved = explicit || this.ctx?.pluginId || defaultPluginId();
|
|
490
|
+
if (!resolved) throw new Error("pluginId is required for app storage uploads");
|
|
491
|
+
return resolved;
|
|
492
|
+
}
|
|
493
|
+
async createSession(pluginId, file, options) {
|
|
494
|
+
const res = await (this.ctx?.apiFetch || apiFetch)(`/api/v1/app-storage/${encodeURIComponent(pluginId)}/uploads`, {
|
|
495
|
+
method: "POST",
|
|
496
|
+
body: JSON.stringify({
|
|
497
|
+
filename: file.name,
|
|
498
|
+
content_type: options.contentType || file.type || "application/octet-stream",
|
|
499
|
+
size: file.size,
|
|
500
|
+
key: options.key || null,
|
|
501
|
+
resumable: options.resumable ?? true,
|
|
502
|
+
chunk_size: normalizeChunkSize(options.chunkSize)
|
|
503
|
+
})
|
|
504
|
+
});
|
|
505
|
+
return res.json();
|
|
506
|
+
}
|
|
507
|
+
async upload(file, options = {}) {
|
|
508
|
+
const pluginId = this.pluginId(options.pluginId);
|
|
509
|
+
const fingerprint = fileFingerprint(pluginId, file, options.key);
|
|
510
|
+
const stored = options.resumable === false ? null : readStoredSession(pluginId, fingerprint);
|
|
511
|
+
const session = stored || await this.createSession(pluginId, file, options);
|
|
512
|
+
writeStoredSession(pluginId, fingerprint, session);
|
|
513
|
+
const chunkSize = normalizeChunkSize(options.chunkSize || session.chunk_size);
|
|
514
|
+
const chunkCount = Math.max(1, Math.ceil(file.size / chunkSize));
|
|
515
|
+
let offset = stored ? await queryOffset(session) : 0;
|
|
516
|
+
report(offset, file.size, Math.floor(offset / chunkSize), chunkCount, "starting", options.onProgress);
|
|
517
|
+
while (offset < file.size) {
|
|
518
|
+
if (options.signal?.aborted) throw new DOMException("Upload aborted", "AbortError");
|
|
519
|
+
const start = offset;
|
|
520
|
+
const end = Math.min(file.size, start + chunkSize) - 1;
|
|
521
|
+
const chunk = file.slice(start, end + 1);
|
|
522
|
+
const chunkIndex = Math.floor(start / chunkSize) + 1;
|
|
523
|
+
const lastReportedBase = start;
|
|
524
|
+
await xhrPut(
|
|
525
|
+
session.upload_url,
|
|
526
|
+
chunk,
|
|
527
|
+
{
|
|
528
|
+
"Content-Type": session.content_type,
|
|
529
|
+
"Content-Range": `bytes ${start}-${end}/${file.size}`
|
|
530
|
+
},
|
|
531
|
+
options.signal,
|
|
532
|
+
(loaded) => report(lastReportedBase + loaded, file.size, chunkIndex, chunkCount, "uploading", options.onProgress)
|
|
533
|
+
);
|
|
534
|
+
offset = end + 1;
|
|
535
|
+
report(offset, file.size, chunkIndex, chunkCount, offset >= file.size ? "complete" : "uploading", options.onProgress);
|
|
536
|
+
writeStoredSession(pluginId, fingerprint, session);
|
|
537
|
+
}
|
|
538
|
+
clearStoredSession(pluginId, fingerprint);
|
|
539
|
+
return {
|
|
540
|
+
uploadId: session.upload_id,
|
|
541
|
+
mode: session.mode,
|
|
542
|
+
bucket: session.bucket,
|
|
543
|
+
objectPath: session.object_path,
|
|
544
|
+
fileUrl: session.file_url,
|
|
545
|
+
contentType: session.content_type,
|
|
546
|
+
size: session.size
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
async resume(file, options = {}) {
|
|
550
|
+
return this.upload(file, { ...options, resumable: true });
|
|
551
|
+
}
|
|
374
552
|
};
|
|
375
553
|
|
|
376
554
|
// src/user-org.ts
|
|
@@ -448,7 +626,7 @@ var OrganizationClient = class {
|
|
|
448
626
|
|
|
449
627
|
// src/palette-client.ts
|
|
450
628
|
function createPaletteClient(ctx) {
|
|
451
|
-
const
|
|
629
|
+
const defaultPluginId2 = () => {
|
|
452
630
|
if (ctx?.pluginId) return ctx.pluginId;
|
|
453
631
|
if (typeof window === "undefined") return "";
|
|
454
632
|
const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
|
|
@@ -458,15 +636,15 @@ function createPaletteClient(ctx) {
|
|
|
458
636
|
user: new UserClient(ctx),
|
|
459
637
|
organization: new OrganizationClient(ctx),
|
|
460
638
|
dataRooms: new DataRoomClient(),
|
|
461
|
-
storage: new StorageClient(),
|
|
639
|
+
storage: new StorageClient(ctx),
|
|
462
640
|
config: {
|
|
463
641
|
get: (pluginId = ctx?.pluginId ?? "") => {
|
|
464
|
-
const resolved = pluginId ||
|
|
642
|
+
const resolved = pluginId || defaultPluginId2();
|
|
465
643
|
if (!resolved) throw new Error("pluginId is required to read install config");
|
|
466
644
|
return getInstallConfig(resolved);
|
|
467
645
|
},
|
|
468
646
|
update: (values, pluginId = ctx?.pluginId ?? "") => {
|
|
469
|
-
const resolved = pluginId ||
|
|
647
|
+
const resolved = pluginId || defaultPluginId2();
|
|
470
648
|
if (!resolved) throw new Error("pluginId is required to update install config");
|
|
471
649
|
return updateInstallConfig(resolved, values);
|
|
472
650
|
}
|
|
@@ -547,14 +725,207 @@ function usePluginTranslations(resources, options = {}) {
|
|
|
547
725
|
};
|
|
548
726
|
}
|
|
549
727
|
|
|
550
|
-
// src/
|
|
728
|
+
// src/router.tsx
|
|
551
729
|
var import_react4 = require("react");
|
|
730
|
+
var RouterCtx = (0, import_react4.createContext)(null);
|
|
731
|
+
var NOT_FOUND = /* @__PURE__ */ Symbol.for("palette.router.not-found");
|
|
732
|
+
function notFound() {
|
|
733
|
+
throw Object.assign(new Error("Palette route not found"), { code: NOT_FOUND });
|
|
734
|
+
}
|
|
735
|
+
function normalizePath(path) {
|
|
736
|
+
const clean = String(path || "/").split("#")[0].split("?")[0] || "/";
|
|
737
|
+
return `/${clean.replace(/^\/+/, "").replace(/\/+$/, "")}`.replace(/^\/$/, "/");
|
|
738
|
+
}
|
|
739
|
+
function splitPath(path) {
|
|
740
|
+
return normalizePath(path).split("/").filter(Boolean).map(decodeURIComponent);
|
|
741
|
+
}
|
|
742
|
+
function routeScore(route) {
|
|
743
|
+
if (typeof route.score === "number") return route.score;
|
|
744
|
+
return route.segments.reduce((score, segment) => {
|
|
745
|
+
if (segment.kind === "static") return score + 10;
|
|
746
|
+
if (segment.kind === "dynamic") return score + 5;
|
|
747
|
+
return score + (segment.optional ? 1 : 2);
|
|
748
|
+
}, route.segments.length);
|
|
749
|
+
}
|
|
750
|
+
function matchRoute(route, path) {
|
|
751
|
+
const parts = splitPath(path);
|
|
752
|
+
const params = {};
|
|
753
|
+
let index = 0;
|
|
754
|
+
for (const segment of route.segments) {
|
|
755
|
+
if (segment.kind === "catchAll") {
|
|
756
|
+
const rest = parts.slice(index);
|
|
757
|
+
if (!segment.optional && rest.length === 0) return null;
|
|
758
|
+
params[segment.name] = rest;
|
|
759
|
+
index = parts.length;
|
|
760
|
+
break;
|
|
761
|
+
}
|
|
762
|
+
const value = parts[index];
|
|
763
|
+
if (value === void 0) return null;
|
|
764
|
+
if (segment.kind === "static") {
|
|
765
|
+
if (value !== segment.value) return null;
|
|
766
|
+
} else {
|
|
767
|
+
params[segment.name] = value;
|
|
768
|
+
}
|
|
769
|
+
index += 1;
|
|
770
|
+
}
|
|
771
|
+
return index === parts.length ? params : null;
|
|
772
|
+
}
|
|
773
|
+
function currentPluginPath(pluginId, routePath) {
|
|
774
|
+
if (routePath) return normalizePath(routePath);
|
|
775
|
+
if (typeof window === "undefined") return "/";
|
|
776
|
+
const path = window.location.pathname;
|
|
777
|
+
if (pluginId) {
|
|
778
|
+
const prefix = `/apps/${pluginId}`;
|
|
779
|
+
if (path === prefix) return "/";
|
|
780
|
+
if (path.startsWith(`${prefix}/`)) return normalizePath(path.slice(prefix.length));
|
|
781
|
+
}
|
|
782
|
+
return normalizePath(path);
|
|
783
|
+
}
|
|
784
|
+
function currentSearchParams() {
|
|
785
|
+
if (typeof window === "undefined") return new URLSearchParams();
|
|
786
|
+
return new URLSearchParams(window.location.search);
|
|
787
|
+
}
|
|
788
|
+
var PaletteRouteErrorBoundary = class extends import_react4.Component {
|
|
789
|
+
constructor() {
|
|
790
|
+
super(...arguments);
|
|
791
|
+
this.state = { error: null };
|
|
792
|
+
this.reset = () => this.setState({ error: null });
|
|
793
|
+
}
|
|
794
|
+
static getDerivedStateFromError(error) {
|
|
795
|
+
return { error };
|
|
796
|
+
}
|
|
797
|
+
componentDidCatch(_error, _info) {
|
|
798
|
+
}
|
|
799
|
+
render() {
|
|
800
|
+
const error = this.state.error;
|
|
801
|
+
if (!error) return this.props.children;
|
|
802
|
+
if (error.code === NOT_FOUND && this.props.notFound) {
|
|
803
|
+
return (0, import_react4.createElement)(this.props.notFound);
|
|
804
|
+
}
|
|
805
|
+
if (this.props.fallback) {
|
|
806
|
+
return (0, import_react4.createElement)(this.props.fallback, { error, reset: this.reset });
|
|
807
|
+
}
|
|
808
|
+
throw error;
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
function renderRoute(route) {
|
|
812
|
+
const page = (0, import_react4.createElement)(route.page);
|
|
813
|
+
const wrapped = (route.layouts || []).reduceRight(
|
|
814
|
+
(children, Layout) => (0, import_react4.createElement)(Layout, null, children),
|
|
815
|
+
page
|
|
816
|
+
);
|
|
817
|
+
return (0, import_react4.createElement)(
|
|
818
|
+
PaletteRouteErrorBoundary,
|
|
819
|
+
{ fallback: route.error, notFound: route.notFound },
|
|
820
|
+
wrapped
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
function PaletteAppRouter({
|
|
824
|
+
routes,
|
|
825
|
+
notFound: NotFound
|
|
826
|
+
}) {
|
|
827
|
+
const platform = usePlatform();
|
|
828
|
+
const [location, setLocation] = (0, import_react4.useState)(() => ({
|
|
829
|
+
pathname: currentPluginPath(platform.pluginId, platform.routePath),
|
|
830
|
+
searchParams: currentSearchParams()
|
|
831
|
+
}));
|
|
832
|
+
(0, import_react4.useEffect)(() => {
|
|
833
|
+
setLocation({
|
|
834
|
+
pathname: currentPluginPath(platform.pluginId, platform.routePath),
|
|
835
|
+
searchParams: currentSearchParams()
|
|
836
|
+
});
|
|
837
|
+
}, [platform.pluginId, platform.routePath]);
|
|
838
|
+
(0, import_react4.useEffect)(() => {
|
|
839
|
+
const sync = () => setLocation({
|
|
840
|
+
pathname: currentPluginPath(platform.pluginId, platform.routePath),
|
|
841
|
+
searchParams: currentSearchParams()
|
|
842
|
+
});
|
|
843
|
+
window.addEventListener("popstate", sync);
|
|
844
|
+
return () => window.removeEventListener("popstate", sync);
|
|
845
|
+
}, [platform.pluginId, platform.routePath]);
|
|
846
|
+
const sortedRoutes = (0, import_react4.useMemo)(
|
|
847
|
+
() => [...routes].sort((a, b) => routeScore(b) - routeScore(a)),
|
|
848
|
+
[routes]
|
|
849
|
+
);
|
|
850
|
+
const matched = (0, import_react4.useMemo)(() => {
|
|
851
|
+
for (const route of sortedRoutes) {
|
|
852
|
+
const params = matchRoute(route, location.pathname);
|
|
853
|
+
if (params) return { route, params };
|
|
854
|
+
}
|
|
855
|
+
return null;
|
|
856
|
+
}, [location.pathname, sortedRoutes]);
|
|
857
|
+
const navigate = (0, import_react4.useCallback)((target, replace = false) => {
|
|
858
|
+
const [pathPart, queryPart = ""] = String(target || "/").split("?");
|
|
859
|
+
const pathname = normalizePath(pathPart);
|
|
860
|
+
const next = `${pathname}${queryPart ? `?${queryPart}` : ""}`;
|
|
861
|
+
setLocation({ pathname, searchParams: new URLSearchParams(queryPart) });
|
|
862
|
+
const currentPath = typeof window === "undefined" ? "" : window.location.pathname;
|
|
863
|
+
const inPalettePath = platform.pluginId && (currentPath.startsWith(`/apps/${platform.pluginId}`) || platform.routePath !== void 0);
|
|
864
|
+
const osPath = inPalettePath && platform.pluginId ? `/apps/${platform.pluginId}${pathname === "/" ? "" : pathname}${queryPart ? `?${queryPart}` : ""}` : next;
|
|
865
|
+
if (replace && typeof window !== "undefined") window.history.replaceState(null, "", osPath);
|
|
866
|
+
else platform.navigate(osPath);
|
|
867
|
+
}, [platform]);
|
|
868
|
+
const state = (0, import_react4.useMemo)(() => ({
|
|
869
|
+
pathname: location.pathname,
|
|
870
|
+
searchParams: location.searchParams,
|
|
871
|
+
params: matched?.params || {},
|
|
872
|
+
push: (path) => navigate(path, false),
|
|
873
|
+
replace: (path) => navigate(path, true)
|
|
874
|
+
}), [location.pathname, location.searchParams, matched?.params, navigate]);
|
|
875
|
+
const content = matched ? renderRoute(matched.route) : NotFound ? (0, import_react4.createElement)(NotFound) : (0, import_react4.createElement)("div", null, "Page not found");
|
|
876
|
+
return (0, import_react4.createElement)(RouterCtx.Provider, { value: state }, content);
|
|
877
|
+
}
|
|
878
|
+
function useRouterState() {
|
|
879
|
+
const value = (0, import_react4.useContext)(RouterCtx);
|
|
880
|
+
if (!value) throw new Error("Palette app router hooks must be used inside PaletteAppRouter");
|
|
881
|
+
return value;
|
|
882
|
+
}
|
|
883
|
+
function useRouter() {
|
|
884
|
+
const { push, replace } = useRouterState();
|
|
885
|
+
return { push, replace, back: () => window.history.back(), forward: () => window.history.forward() };
|
|
886
|
+
}
|
|
887
|
+
function usePathname() {
|
|
888
|
+
return useRouterState().pathname;
|
|
889
|
+
}
|
|
890
|
+
function useSearchParams() {
|
|
891
|
+
return useRouterState().searchParams;
|
|
892
|
+
}
|
|
893
|
+
function useParams() {
|
|
894
|
+
return useRouterState().params;
|
|
895
|
+
}
|
|
896
|
+
function Link({
|
|
897
|
+
href,
|
|
898
|
+
replace,
|
|
899
|
+
onClick,
|
|
900
|
+
children,
|
|
901
|
+
...props
|
|
902
|
+
}) {
|
|
903
|
+
const router = useRouter();
|
|
904
|
+
return (0, import_react4.createElement)(
|
|
905
|
+
"a",
|
|
906
|
+
{
|
|
907
|
+
...props,
|
|
908
|
+
href,
|
|
909
|
+
onClick: (event) => {
|
|
910
|
+
onClick?.(event);
|
|
911
|
+
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
912
|
+
event.preventDefault();
|
|
913
|
+
if (replace) router.replace(href);
|
|
914
|
+
else router.push(href);
|
|
915
|
+
}
|
|
916
|
+
},
|
|
917
|
+
children
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/hooks/use-plugin-tasks.ts
|
|
922
|
+
var import_react5 = require("react");
|
|
552
923
|
function usePluginTasks(agentId) {
|
|
553
924
|
const { apiFetch: apiFetch2 } = usePlatform();
|
|
554
|
-
const [tasks, setTasks] = (0,
|
|
555
|
-
const [stats, setStats] = (0,
|
|
556
|
-
const [loading, setLoading] = (0,
|
|
557
|
-
const fetchTasks = (0,
|
|
925
|
+
const [tasks, setTasks] = (0, import_react5.useState)([]);
|
|
926
|
+
const [stats, setStats] = (0, import_react5.useState)(null);
|
|
927
|
+
const [loading, setLoading] = (0, import_react5.useState)(true);
|
|
928
|
+
const fetchTasks = (0, import_react5.useCallback)(async () => {
|
|
558
929
|
try {
|
|
559
930
|
const params = new URLSearchParams();
|
|
560
931
|
if (agentId) params.set("agent_id", String(agentId));
|
|
@@ -563,18 +934,18 @@ function usePluginTasks(agentId) {
|
|
|
563
934
|
} catch {
|
|
564
935
|
}
|
|
565
936
|
}, [apiFetch2, agentId]);
|
|
566
|
-
const fetchStats = (0,
|
|
937
|
+
const fetchStats = (0, import_react5.useCallback)(async () => {
|
|
567
938
|
try {
|
|
568
939
|
const res = await apiFetch2("/api/v1/tasks/stats");
|
|
569
940
|
setStats(await res.json());
|
|
570
941
|
} catch {
|
|
571
942
|
}
|
|
572
943
|
}, [apiFetch2]);
|
|
573
|
-
(0,
|
|
944
|
+
(0, import_react5.useEffect)(() => {
|
|
574
945
|
setLoading(true);
|
|
575
946
|
Promise.all([fetchTasks(), fetchStats()]).finally(() => setLoading(false));
|
|
576
947
|
}, [fetchTasks, fetchStats]);
|
|
577
|
-
const createTask = (0,
|
|
948
|
+
const createTask = (0, import_react5.useCallback)(async (payload) => {
|
|
578
949
|
const res = await apiFetch2("/api/v1/tasks", {
|
|
579
950
|
method: "POST",
|
|
580
951
|
body: JSON.stringify(payload)
|
|
@@ -583,7 +954,7 @@ function usePluginTasks(agentId) {
|
|
|
583
954
|
await Promise.all([fetchTasks(), fetchStats()]);
|
|
584
955
|
return task;
|
|
585
956
|
}, [apiFetch2, fetchTasks, fetchStats]);
|
|
586
|
-
const updateTask = (0,
|
|
957
|
+
const updateTask = (0, import_react5.useCallback)(async (taskId, payload) => {
|
|
587
958
|
const res = await apiFetch2(`/api/v1/tasks/${taskId}`, {
|
|
588
959
|
method: "PATCH",
|
|
589
960
|
body: JSON.stringify(payload)
|
|
@@ -592,7 +963,7 @@ function usePluginTasks(agentId) {
|
|
|
592
963
|
await Promise.all([fetchTasks(), fetchStats()]);
|
|
593
964
|
return task;
|
|
594
965
|
}, [apiFetch2, fetchTasks, fetchStats]);
|
|
595
|
-
const deleteTask = (0,
|
|
966
|
+
const deleteTask = (0, import_react5.useCallback)(async (taskId) => {
|
|
596
967
|
await apiFetch2(`/api/v1/tasks/${taskId}`, { method: "DELETE" });
|
|
597
968
|
await Promise.all([fetchTasks(), fetchStats()]);
|
|
598
969
|
}, [apiFetch2, fetchTasks, fetchStats]);
|
|
@@ -600,23 +971,23 @@ function usePluginTasks(agentId) {
|
|
|
600
971
|
}
|
|
601
972
|
|
|
602
973
|
// src/hooks/use-plugin-data-rooms.ts
|
|
603
|
-
var
|
|
974
|
+
var import_react6 = require("react");
|
|
604
975
|
function usePluginDataRooms() {
|
|
605
976
|
const { apiFetch: apiFetch2 } = usePlatform();
|
|
606
|
-
const [rooms, setRooms] = (0,
|
|
607
|
-
const [loading, setLoading] = (0,
|
|
608
|
-
const fetchRooms = (0,
|
|
977
|
+
const [rooms, setRooms] = (0, import_react6.useState)([]);
|
|
978
|
+
const [loading, setLoading] = (0, import_react6.useState)(true);
|
|
979
|
+
const fetchRooms = (0, import_react6.useCallback)(async () => {
|
|
609
980
|
try {
|
|
610
981
|
const res = await apiFetch2("/api/v1/data-rooms");
|
|
611
982
|
setRooms(await res.json());
|
|
612
983
|
} catch {
|
|
613
984
|
}
|
|
614
985
|
}, [apiFetch2]);
|
|
615
|
-
(0,
|
|
986
|
+
(0, import_react6.useEffect)(() => {
|
|
616
987
|
setLoading(true);
|
|
617
988
|
fetchRooms().finally(() => setLoading(false));
|
|
618
989
|
}, [fetchRooms]);
|
|
619
|
-
const fetchFolder = (0,
|
|
990
|
+
const fetchFolder = (0, import_react6.useCallback)(async (roomId, folderId) => {
|
|
620
991
|
const path = folderId ? `/api/v1/data-rooms/${roomId}/folders/${folderId}` : `/api/v1/data-rooms/${roomId}`;
|
|
621
992
|
const res = await apiFetch2(path);
|
|
622
993
|
return res.json();
|
|
@@ -625,19 +996,19 @@ function usePluginDataRooms() {
|
|
|
625
996
|
}
|
|
626
997
|
|
|
627
998
|
// src/hooks/use-plugin-chat.ts
|
|
628
|
-
var
|
|
999
|
+
var import_react7 = require("react");
|
|
629
1000
|
function usePluginChat(agentId) {
|
|
630
1001
|
const { apiFetch: apiFetch2 } = usePlatform();
|
|
631
|
-
const [threads, setThreads] = (0,
|
|
632
|
-
const [messages, setMessages] = (0,
|
|
633
|
-
const [streaming, setStreaming] = (0,
|
|
634
|
-
const [activeThreadId, setActiveThreadId] = (0,
|
|
635
|
-
const abortRef = (0,
|
|
636
|
-
const fetchThreads = (0,
|
|
1002
|
+
const [threads, setThreads] = (0, import_react7.useState)([]);
|
|
1003
|
+
const [messages, setMessages] = (0, import_react7.useState)([]);
|
|
1004
|
+
const [streaming, setStreaming] = (0, import_react7.useState)(false);
|
|
1005
|
+
const [activeThreadId, setActiveThreadId] = (0, import_react7.useState)(null);
|
|
1006
|
+
const abortRef = (0, import_react7.useRef)(null);
|
|
1007
|
+
const fetchThreads = (0, import_react7.useCallback)(async () => {
|
|
637
1008
|
const res = await apiFetch2(`/api/v1/chat/${agentId}/threads`);
|
|
638
1009
|
setThreads(await res.json());
|
|
639
1010
|
}, [apiFetch2, agentId]);
|
|
640
|
-
const createThread = (0,
|
|
1011
|
+
const createThread = (0, import_react7.useCallback)(async () => {
|
|
641
1012
|
const res = await apiFetch2(`/api/v1/chat/${agentId}/threads`, { method: "POST" });
|
|
642
1013
|
const thread = await res.json();
|
|
643
1014
|
setActiveThreadId(thread.id);
|
|
@@ -645,13 +1016,13 @@ function usePluginChat(agentId) {
|
|
|
645
1016
|
await fetchThreads();
|
|
646
1017
|
return thread;
|
|
647
1018
|
}, [apiFetch2, agentId, fetchThreads]);
|
|
648
|
-
const fetchMessages = (0,
|
|
1019
|
+
const fetchMessages = (0, import_react7.useCallback)(async (threadId) => {
|
|
649
1020
|
const res = await apiFetch2(`/api/v1/chat/threads/${threadId}/messages`);
|
|
650
1021
|
const msgs = await res.json();
|
|
651
1022
|
setMessages(msgs);
|
|
652
1023
|
setActiveThreadId(threadId);
|
|
653
1024
|
}, [apiFetch2]);
|
|
654
|
-
const sendMessage = (0,
|
|
1025
|
+
const sendMessage = (0, import_react7.useCallback)(async (threadId, content) => {
|
|
655
1026
|
setStreaming(true);
|
|
656
1027
|
abortRef.current = new AbortController();
|
|
657
1028
|
const userMsg = {
|
|
@@ -719,7 +1090,7 @@ function usePluginChat(agentId) {
|
|
|
719
1090
|
abortRef.current = null;
|
|
720
1091
|
}
|
|
721
1092
|
}, []);
|
|
722
|
-
const stopStreaming = (0,
|
|
1093
|
+
const stopStreaming = (0, import_react7.useCallback)(() => {
|
|
723
1094
|
abortRef.current?.abort();
|
|
724
1095
|
}, []);
|
|
725
1096
|
return {
|
|
@@ -737,8 +1108,10 @@ function usePluginChat(agentId) {
|
|
|
737
1108
|
// Annotate the CommonJS export names for ESM import in node:
|
|
738
1109
|
0 && (module.exports = {
|
|
739
1110
|
DataRoomClient,
|
|
1111
|
+
Link,
|
|
740
1112
|
OrganizationClient,
|
|
741
1113
|
PaletteApiError,
|
|
1114
|
+
PaletteAppRouter,
|
|
742
1115
|
PlatformCtx,
|
|
743
1116
|
PluginProvider,
|
|
744
1117
|
StorageClient,
|
|
@@ -758,14 +1131,19 @@ function usePluginChat(agentId) {
|
|
|
758
1131
|
isPaletteApiError,
|
|
759
1132
|
isSandboxRuntime,
|
|
760
1133
|
normalizePaletteLanguage,
|
|
1134
|
+
notFound,
|
|
761
1135
|
setBaseUrl,
|
|
762
1136
|
translate,
|
|
763
1137
|
updateInstallConfig,
|
|
764
1138
|
uploadToSignedUrl,
|
|
1139
|
+
useParams,
|
|
1140
|
+
usePathname,
|
|
765
1141
|
usePlatform,
|
|
766
1142
|
usePluginChat,
|
|
767
1143
|
usePluginDataRooms,
|
|
768
1144
|
usePluginTasks,
|
|
769
1145
|
usePluginTranslations,
|
|
1146
|
+
useRouter,
|
|
1147
|
+
useSearchParams,
|
|
770
1148
|
withPluginProvider
|
|
771
1149
|
});
|