@snapsite/cms-core
v0.1.1
Published
Typed data layer, Zod schemas, Supabase client factories, and safeQuery wrapper for the @snapsite headless CMS.
Maintainers
Readme
@snapsite/cms-core
Typed data layer, Zod schemas, Supabase client factories, and safeQuery
wrapper for the SnapSite headless CMS. Used by @snapsite/cms-editor (in-page
editor), @snapsite/cms-bake (static-site baker), and the dashboard.
Install
pnpm add @snapsite/cms-core @supabase/supabase-js zod@supabase/supabase-js and zod are direct dependencies — pinned ranges are
declared in this package.
What's in the box
// Client factories
import {
createAnonymousClient,
createAuthenticatedClient,
type CmsClient,
} from "@snapsite/cms-core";
// Data layer (each function returns a SafeResult<T>)
import {
// content
getContent, getAllContentForSite, upsertContent,
// sections
listSections, insertSection, updateSection, publishSection,
deleteSection, reorderSection,
// media
uploadMedia, listMedia, getPublicUrl, softDeleteMedia,
// auth
getCurrentUser, getUserSites, signInWithPassword, signInWithMagicLink, signOut,
// cross-domain editor handoff (Prompt 6)
createEditorHandoffToken, exchangeEditorHandoffToken,
// static-rebuild pipeline (Prompt 8)
fireRebuildTriggerSafe, getRebuildStatus, triggerRebuildManually,
// admin error log (Prompt 9b)
listCmsErrors, getCurrentUserIsAdmin, listAdmins, addAdmin, removeAdmin,
} from "@snapsite/cms-core";safeQuery and the reporter pipeline
Every data-layer call routes through safeQuery, which wraps Supabase's
PostgREST/RPC envelope into a discriminated union, applies a timeout (5s
default), retries transient errors once, and forwards terminal failures to
an installable sink:
import {
safeQuery,
setErrorReporter,
combineErrorReporters,
createSupabaseErrorReporter,
createSentryReporter,
setReporterDedupWindowMs,
} from "@snapsite/cms-core";
import * as Sentry from "@sentry/browser";
// One-time at app boot
setErrorReporter(
combineErrorReporters(
createSupabaseErrorReporter(client), // writes to public.cms_errors
createSentryReporter(Sentry.captureException),
),
);
setReporterDedupWindowMs(60_000); // suppress duplicates within 60s
// Every data-layer call surfaces ok / error consistently
const res = await getContent(client, siteId, "/home/heading");
if (res.ok) {
console.log(res.data);
} else {
// Already logged + reported. Inspect res.error for UX-level handling.
console.warn(res.error.message);
}The reporter contract is best-effort: a sink that throws or rejects is
isolated via console.warn so it can't recurse back into safeQuery.
Image processing (subpath import)
import {
resizeImage,
DEFAULT_RESIZE_OPTIONS,
ImageProcessingError,
} from "@snapsite/cms-core/image-processing";Browser-only — relies on <canvas> and URL.createObjectURL. Imported as a
subpath so Node consumers (@snapsite/cms-bake) don't pull in DOM types.
Types
All Supabase rows are re-exported as typed aliases:
import type {
Site, SiteUser, ContentRow, Section, MediaAsset,
RebuildQueueRow, RebuildStatus,
Admin, CmsErrorRow,
AuthUser, JsonValue, SafeResult, Uuid, Iso8601,
} from "@snapsite/cms-core";Stability
Public API surface is stable from 0.1.0 onward — see
docs/api-surface.md
for the full export list with stability markers.
License
MIT
