@relayfile/file-observer 0.1.12 → 0.1.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayfile/file-observer",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "RelayFile observer dashboard for browsing synced workspace files and metadata",
5
5
  "files": [
6
6
  "src",
package/src/app/page.tsx CHANGED
@@ -130,6 +130,12 @@ const PUBLIC_TOKEN = process.env.NEXT_PUBLIC_RELAYFILE_TOKEN ?? '';
130
130
  const WORKSPACE_ENV =
131
131
  process.env.NEXT_PUBLIC_RELAYFILE_WORKSPACE_IDS ?? process.env.NEXT_PUBLIC_RELAYFILE_WORKSPACE_ID ?? '';
132
132
 
133
+ interface ObserverConfig {
134
+ baseUrl: string;
135
+ token: string;
136
+ workspaceIds: string[];
137
+ }
138
+
133
139
  function parseWorkspaceIds(raw: string): string[] {
134
140
  return Array.from(
135
141
  new Set(
@@ -141,6 +147,40 @@ function parseWorkspaceIds(raw: string): string[] {
141
147
  );
142
148
  }
143
149
 
150
+ function readParam(params: URLSearchParams, names: string[]): string {
151
+ for (const name of names) {
152
+ const value = params.get(name)?.trim();
153
+ if (value) {
154
+ return value;
155
+ }
156
+ }
157
+ return '';
158
+ }
159
+
160
+ function readRuntimeObserverConfig(): Partial<ObserverConfig> {
161
+ if (typeof window === 'undefined') {
162
+ return {};
163
+ }
164
+ const hash = window.location.hash.replace(/^#\/?/, '');
165
+ const hashParams = new URLSearchParams(hash);
166
+ const searchParams = new URLSearchParams(window.location.search);
167
+ const read = (names: string[]) => readParam(hashParams, names) || readParam(searchParams, names);
168
+ const workspaceRaw = read(['workspaceIds', 'workspaceId', 'workspace', 'wks']);
169
+ const config: Partial<ObserverConfig> = {};
170
+ const baseUrl = read(['baseUrl', 'server', 'url']);
171
+ const token = read(['token', 'relayfileToken']);
172
+ if (baseUrl) {
173
+ config.baseUrl = baseUrl;
174
+ }
175
+ if (token) {
176
+ config.token = token;
177
+ }
178
+ if (workspaceRaw) {
179
+ config.workspaceIds = parseWorkspaceIds(workspaceRaw);
180
+ }
181
+ return config;
182
+ }
183
+
144
184
  function buildQuery(params: Record<string, string | number | undefined>): string {
145
185
  const query = new URLSearchParams();
146
186
  for (const [key, value] of Object.entries(params)) {
@@ -398,9 +438,21 @@ function ErrorBanner({
398
438
  }
399
439
 
400
440
  export default function Page() {
401
- const workspaceIds = useMemo(() => parseWorkspaceIds(WORKSPACE_ENV), []);
402
- const configReady = Boolean(DEFAULT_BASE_URL && PUBLIC_TOKEN && workspaceIds.length > 0);
403
- const client = useMemo(() => createRelayFileClient(DEFAULT_BASE_URL, PUBLIC_TOKEN), []);
441
+ const defaultConfig = useMemo<ObserverConfig>(
442
+ () => ({
443
+ baseUrl: DEFAULT_BASE_URL,
444
+ token: PUBLIC_TOKEN,
445
+ workspaceIds: parseWorkspaceIds(WORKSPACE_ENV)
446
+ }),
447
+ []
448
+ );
449
+ const [observerConfig, setObserverConfig] = useState<ObserverConfig>(defaultConfig);
450
+ const workspaceIds = observerConfig.workspaceIds;
451
+ const configReady = Boolean(observerConfig.baseUrl && observerConfig.token && workspaceIds.length > 0);
452
+ const client = useMemo(
453
+ () => createRelayFileClient(observerConfig.baseUrl, observerConfig.token),
454
+ [observerConfig.baseUrl, observerConfig.token]
455
+ );
404
456
  const [workspaceId, setWorkspaceId] = useState<string>(workspaceIds[0] ?? '');
405
457
  const [selectedEntry, setSelectedEntry] = useState<SelectedEntry | null>(null);
406
458
  const [fullViewEntry, setFullViewEntry] = useState<SelectedEntry | null>(null);
@@ -434,6 +486,30 @@ export default function Page() {
434
486
 
435
487
  const activeSearch = deferredSearch.trim();
436
488
 
489
+ useEffect(() => {
490
+ const runtimeConfig = readRuntimeObserverConfig();
491
+ if (!runtimeConfig.baseUrl && !runtimeConfig.token && !runtimeConfig.workspaceIds) {
492
+ return;
493
+ }
494
+ setObserverConfig((current) => ({
495
+ baseUrl: runtimeConfig.baseUrl ?? current.baseUrl,
496
+ token: runtimeConfig.token ?? current.token,
497
+ workspaceIds: runtimeConfig.workspaceIds?.length ? runtimeConfig.workspaceIds : current.workspaceIds
498
+ }));
499
+ }, []);
500
+
501
+ useEffect(() => {
502
+ if (workspaceIds.length === 0) {
503
+ if (workspaceId) {
504
+ setWorkspaceId('');
505
+ }
506
+ return;
507
+ }
508
+ if (!workspaceId || !workspaceIds.includes(workspaceId)) {
509
+ setWorkspaceId(workspaceIds[0] ?? '');
510
+ }
511
+ }, [workspaceId, workspaceIds]);
512
+
437
513
  useEffect(() => {
438
514
  treeCacheRef.current = treeCache;
439
515
  }, [treeCache]);
@@ -1,10 +1,5 @@
1
1
  name = "relayfile-file-observer"
2
2
  compatibility_date = "2024-12-01"
3
3
 
4
- routes = [
5
- { pattern = "files.relayfile.dev/*", zone_name = "relayfile.dev" },
6
- { pattern = "staging-files.relayfile.dev/*", zone_name = "relayfile.dev" },
7
- ]
8
-
9
- [vars]
10
- FILE_OBSERVER_ORIGIN = "https://relayfile-file-observer.pages.dev"
4
+ # Public routing is handled by the AgentRelay router:
5
+ # https://agentrelay.com/observer/file -> https://relayfile-file-observer.pages.dev