@nuxtjs/sanity
Version:
Sanity integration for Nuxt
90 lines (89 loc) • 3.87 kB
JavaScript
import { createCompatibilityActors, isMaybePresentation, isMaybePreviewWindow } from "@sanity/presentation-comlink";
import { createNode, createNodeMachine } from "@sanity/comlink";
import { onScopeDispose, watch } from "vue";
import { defineNuxtPlugin, refreshNuxtData } from "#imports";
import { useSanityConfig, useSanityVisualEditingState, useSanity, useIsSanityPresentationTool, useSanityPreviewEnvironment, useSanityPerspective } from "../composables/index.js";
export default defineNuxtPlugin(() => {
const { liveContent, visualEditing } = useSanityConfig();
if (!import.meta.client || !liveContent) return;
const visualEditingState = useSanityVisualEditingState();
const sanity = useSanity();
const { browserToken } = liveContent;
const liveClient = sanity.client.withConfig({
ignoreBrowserTokenWarning: true,
token: browserToken,
useCdn: false
});
const includeDrafts = !!(browserToken && visualEditingState?.enabled);
const tag = "nuxt-loader.live";
const _inPresentation = useIsSanityPresentationTool();
watch(_inPresentation, (inPresentation, _wasInPresentation, onCleanup) => {
if (inPresentation === false || inPresentation === true && visualEditing?.mode !== "live-visual-editing") {
const { unsubscribe } = liveClient.live.events({ includeDrafts, tag }).subscribe({
next: (event) => {
if (import.meta.dev && event.type === "welcome") {
console.info(
"Sanity is live with",
(typeof browserToken === "string" && visualEditingState?.enabled ? browserToken : void 0) ? "automatic revalidation for draft content changes as well as published content" : visualEditingState?.enabled ? "automatic revalidation for only published content. Provide a `browserToken` to `defineLive` to support draft content outside of Presentation Tool." : "automatic revalidation of published content"
);
} else if (event.type === "message") {
const tags = event.tags.map((tag2) => `sanity:${tag2}`);
sanity.liveStore?.notify(tags, event.id);
} else if (event.type === "restart") {
refreshNuxtData();
}
},
error: () => {
console.error("Live event error");
}
});
onCleanup(() => {
unsubscribe();
});
}
}, { immediate: true });
const environment = useSanityPreviewEnvironment();
if (!isMaybePresentation()) {
if (visualEditingState?.enabled && browserToken) {
environment.value = "live";
} else if (visualEditingState?.enabled) {
environment.value = "static";
} else {
environment.value = "unknown";
}
}
if (isMaybePresentation()) {
const timeout = setTimeout(() => {
environment.value = "live";
}, 5e3);
const comlink = createNode(
{ name: "loaders", connectTo: "presentation" },
createNodeMachine().provide({
actors: createCompatibilityActors()
})
);
comlink.on("loader/perspective", (data) => {
const perspective = useSanityPerspective();
if (perspective.value !== data.perspective) {
perspective.value = data.perspective;
}
});
comlink.onStatus(() => {
clearTimeout(timeout);
environment.value = isMaybePreviewWindow() ? "presentation-window" : "presentation-iframe";
}, "connected");
comlink.start();
onScopeDispose(comlink.stop);
}
const focusThrottleInterval = 5e3;
let nextFocusRevalidatedAt = 0;
const callback = () => {
const now = Date.now();
if (now > nextFocusRevalidatedAt && document.visibilityState !== "hidden") {
refreshNuxtData();
nextFocusRevalidatedAt = now + focusThrottleInterval;
}
};
document.addEventListener("visibilitychange", callback, { passive: true });
window.addEventListener("focus", callback, { passive: true });
});