Completion for non-federation federation links
This commit is contained in:
parent
b043ffaee0
commit
75bdd6390b
@ -16,6 +16,8 @@ import { applyQuery } from "$sb/lib/query.ts";
|
|||||||
import { invokeFunction } from "$sb/silverbullet-syscall/system.ts";
|
import { invokeFunction } from "$sb/silverbullet-syscall/system.ts";
|
||||||
import type { Message } from "$sb/types.ts";
|
import type { Message } from "$sb/types.ts";
|
||||||
import { sleep } from "../../common/async_util.ts";
|
import { sleep } from "../../common/async_util.ts";
|
||||||
|
import { cacheFileListing } from "../federation/federation.ts";
|
||||||
|
import type { PageMeta } from "../../web/types.ts";
|
||||||
|
|
||||||
// Key space:
|
// Key space:
|
||||||
// meta: => metaJson
|
// meta: => metaJson
|
||||||
@ -95,7 +97,28 @@ export async function pageComplete(completeEvent: CompleteEvent) {
|
|||||||
if (!match) {
|
if (!match) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const allPages = await space.listPages();
|
let allPages: PageMeta[] = await space.listPages();
|
||||||
|
const prefix = match[1];
|
||||||
|
if (prefix.startsWith("!")) {
|
||||||
|
// Federation prefix, let's first see if we're matching anything from federation that is locally synced
|
||||||
|
const prefixMatches = allPages.filter((pageMeta) =>
|
||||||
|
pageMeta.name.startsWith(prefix)
|
||||||
|
);
|
||||||
|
if (prefixMatches.length === 0) {
|
||||||
|
// Ok, nothing synced in via federation, let's see if this URI is complete enough to try to fetch index.json
|
||||||
|
if (prefix.includes("/")) {
|
||||||
|
// Yep
|
||||||
|
const domain = prefix.split("/")[0];
|
||||||
|
// Cached listing
|
||||||
|
allPages = (await cacheFileListing(domain)).filter((fm) =>
|
||||||
|
fm.name.endsWith(".md")
|
||||||
|
).map((fm) => ({
|
||||||
|
...fm,
|
||||||
|
name: fm.name.slice(0, -3),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
from: completeEvent.pos - match[1].length,
|
from: completeEvent.pos - match[1].length,
|
||||||
options: allPages.map((pageMeta) => {
|
options: allPages.map((pageMeta) => {
|
||||||
|
@ -43,18 +43,31 @@ export async function listFiles(): Promise<FileMeta[]> {
|
|||||||
// Fetch them all in parallel
|
// Fetch them all in parallel
|
||||||
try {
|
try {
|
||||||
await Promise.all((await readFederationConfigs()).map(async (config) => {
|
await Promise.all((await readFederationConfigs()).map(async (config) => {
|
||||||
|
const items = await cacheFileListing(config.uri);
|
||||||
|
fileMetas = fileMetas.concat(items);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// console.log("All of em: ", fileMetas);
|
||||||
|
return fileMetas;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error("Error listing federation files", e);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cacheFileListing(uri: string): Promise<FileMeta[]> {
|
||||||
const cachedListing = await store.get(
|
const cachedListing = await store.get(
|
||||||
`${fileListingPrefixCacheKey}${config.uri}`,
|
`${fileListingPrefixCacheKey}${uri}`,
|
||||||
) as FileListingCacheEntry;
|
) as FileListingCacheEntry;
|
||||||
if (
|
if (
|
||||||
cachedListing &&
|
cachedListing &&
|
||||||
cachedListing.lastUpdated > Date.now() - listingCacheTimeout
|
cachedListing.lastUpdated > Date.now() - listingCacheTimeout
|
||||||
) {
|
) {
|
||||||
fileMetas = fileMetas.concat(cachedListing.items);
|
// console.info("Using cached listing", cachedListing);
|
||||||
return;
|
return cachedListing.items;
|
||||||
}
|
}
|
||||||
console.log("Fetching listing from federated", config);
|
console.log("Fetching listing from federated", uri);
|
||||||
const uriParts = config.uri.split("/");
|
const uriParts = uri.split("/");
|
||||||
const rootUri = uriParts[0];
|
const rootUri = uriParts[0];
|
||||||
const prefix = uriParts.slice(1).join("/");
|
const prefix = uriParts.slice(1).join("/");
|
||||||
const indexUrl = `${federatedPathToUrl(rootUri)}/index.json`;
|
const indexUrl = `${federatedPathToUrl(rootUri)}/index.json`;
|
||||||
@ -69,6 +82,7 @@ export async function listFiles(): Promise<FileMeta[]> {
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
|
"Cache-Control": "no-cache",
|
||||||
},
|
},
|
||||||
signal: fetchController.signal,
|
signal: fetchController.signal,
|
||||||
});
|
});
|
||||||
@ -82,29 +96,22 @@ export async function listFiles(): Promise<FileMeta[]> {
|
|||||||
meta.name.startsWith(prefix)
|
meta.name.startsWith(prefix)
|
||||||
).map((meta: FileMeta) => ({
|
).map((meta: FileMeta) => ({
|
||||||
...meta,
|
...meta,
|
||||||
perm: config.perm || "ro",
|
perm: "ro",
|
||||||
name: `${rootUri}/${meta.name}`,
|
name: `${rootUri}/${meta.name}`,
|
||||||
}));
|
}));
|
||||||
await store.set(`${fileListingPrefixCacheKey}${config.uri}`, {
|
await store.set(`${fileListingPrefixCacheKey}${uri}`, {
|
||||||
items,
|
items,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
} as FileListingCacheEntry);
|
} as FileListingCacheEntry);
|
||||||
fileMetas = fileMetas.concat(items);
|
return items;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error("Failed to process", indexUrl, e);
|
console.error("Failed to process", indexUrl, e);
|
||||||
if (cachedListing) {
|
if (cachedListing) {
|
||||||
console.info("Using cached listing");
|
console.info("Using cached listing");
|
||||||
fileMetas = fileMetas.concat(cachedListing.items);
|
return cachedListing.items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
|
||||||
|
|
||||||
// console.log("All of em: ", fileMetas);
|
|
||||||
return fileMetas;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.error("Error listing federation files", e);
|
|
||||||
return [];
|
return [];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readFile(
|
export async function readFile(
|
||||||
|
Loading…
Reference in New Issue
Block a user