@cancia/astro 0.5.1 → 0.6.0

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.
File without changes
@@ -0,0 +1,60 @@
1
+ /** Flat content map as returned by /api/cancia/content and kv.getAll: "key.lang" → value. */
2
+ type ContentMap = Record<string, string>;
3
+ /** A translator: `(key, fallback) => cms[`${key}.${lang}`] ?? fallback`. */
4
+ type Translate = (key: string, fallback: string) => string;
5
+ interface ContentReaderOptions {
6
+ /** Site id (the `?site=` query param and the storage `site` column). */
7
+ site: string;
8
+ /**
9
+ * Build-time content API base. Default: `process.env.CANCIA_CONTENT_URL`.
10
+ * When set (non-empty), `getCMS()` FETCHES from
11
+ * `${url}/api/cancia/content?site=<site>` instead of reading the DB directly.
12
+ * This is how a static build on a runtime-only volume gets live content.
13
+ */
14
+ url?: string;
15
+ /**
16
+ * Bearer token for the fetch. Default: `process.env.CANCIA_TOKEN`. Required by
17
+ * a non-public site (036 fail-closed) — without it the fetch 401s and the
18
+ * reader falls back to the direct DB read.
19
+ */
20
+ token?: string;
21
+ /**
22
+ * Direct-DB fallback path. Default:
23
+ * `process.env.CANCIA_DB_PATH ?? "<cwd>/cancia.db"`.
24
+ * Ignored when a `readDb` override is supplied.
25
+ */
26
+ dbPath?: string;
27
+ /** Default language for `makeT`/`get`. Default: `"en"`. */
28
+ lang?: string;
29
+ /** Injectable fetch (tests). Default: global `fetch`. */
30
+ fetch?: typeof fetch;
31
+ /**
32
+ * Optional DB-read override. Lets a non-sqlite project (e.g. json-file
33
+ * storage) supply its own fallback WITHOUT this reader importing every
34
+ * adapter. Default: read via `createSqliteAdapterV2({ dbPath })` (the
35
+ * recommended backend).
36
+ */
37
+ readDb?: () => Promise<ContentMap>;
38
+ }
39
+ interface ContentReader {
40
+ /**
41
+ * Read all content for the site as a flat `"key.lang" → value` map.
42
+ * Chain: fetch (when `url` set) → direct DB read → `{}`. NEVER throws.
43
+ */
44
+ getCMS(): Promise<ContentMap>;
45
+ /** Build a translator over a content map for the reader's `lang`. */
46
+ makeT(cms: ContentMap): Translate;
47
+ /** Sugar: `const { t, cms } = await reader.get()` in a page's frontmatter. */
48
+ get(): Promise<{
49
+ t: Translate;
50
+ cms: ContentMap;
51
+ }>;
52
+ }
53
+ /**
54
+ * Create a content reader. Reads are transport-agnostic (network OR local file)
55
+ * and never throw — a static build reads content the same way whether it's a
56
+ * local DB, the site's own API, or a future hosted Cancia DB.
57
+ */
58
+ declare function createContentReader(opts: ContentReaderOptions): ContentReader;
59
+
60
+ export { type ContentMap, type ContentReader, type ContentReaderOptions, type Translate, createContentReader };
@@ -0,0 +1,52 @@
1
+ import "./chunk-FOSOWSXV.js";
2
+ import "./chunk-CJDIVWO3.js";
3
+ import {
4
+ createSqliteAdapterV2
5
+ } from "./chunk-GNWD7EL2.js";
6
+ import "./chunk-U7V53JX7.js";
7
+ import "./chunk-L2VKQJPY.js";
8
+ import "./chunk-7IA5B5CF.js";
9
+
10
+ // src/content.ts
11
+ function createContentReader(opts) {
12
+ const site = opts.site;
13
+ const lang = opts.lang ?? "en";
14
+ const url = opts.url ?? process.env.CANCIA_CONTENT_URL;
15
+ const token = opts.token ?? process.env.CANCIA_TOKEN;
16
+ const fetchImpl = opts.fetch ?? globalThis.fetch;
17
+ function readDb() {
18
+ if (opts.readDb) return opts.readDb();
19
+ const dbPath = opts.dbPath ?? process.env.CANCIA_DB_PATH ?? `${process.cwd()}/cancia.db`;
20
+ return createSqliteAdapterV2({ dbPath }).kv.getAll(site);
21
+ }
22
+ async function fetchFromApi(base) {
23
+ const endpoint = `${base.replace(/\/+$/, "")}/api/cancia/content?site=${encodeURIComponent(site)}`;
24
+ const res = await fetchImpl(endpoint, {
25
+ headers: token ? { Authorization: `Bearer ${token}` } : {}
26
+ });
27
+ if (!res.ok) throw new Error(`Content fetch failed: ${res.status}`);
28
+ return await res.json();
29
+ }
30
+ async function getCMS() {
31
+ try {
32
+ return url ? await fetchFromApi(url) : await readDb();
33
+ } catch {
34
+ try {
35
+ return await readDb();
36
+ } catch {
37
+ return {};
38
+ }
39
+ }
40
+ }
41
+ function makeT(cms) {
42
+ return (key, fallback) => cms[`${key}.${lang}`] ?? fallback;
43
+ }
44
+ async function get() {
45
+ const cms = await getCMS();
46
+ return { t: makeT(cms), cms };
47
+ }
48
+ return { getCMS, makeT, get };
49
+ }
50
+ export {
51
+ createContentReader
52
+ };
@@ -1,13 +1,13 @@
1
- import {
2
- makeListsRoutes
3
- } from "../chunk-22DJVJBR.js";
4
- import "../chunk-NG5GJME5.js";
5
- import "../chunk-7IA5B5CF.js";
6
1
  import {
7
2
  extractRoute,
8
3
  invalidateOnSave
9
4
  } from "../chunk-VGRG5DN7.js";
5
+ import {
6
+ makeListsRoutes
7
+ } from "../chunk-22DJVJBR.js";
8
+ import "../chunk-NG5GJME5.js";
10
9
  import "../chunk-X6ZFFGIA.js";
10
+ import "../chunk-7IA5B5CF.js";
11
11
 
12
12
  // src/endpoints/lists.ts
13
13
  import { getCanciaRuntime } from "virtual:cancia/runtime";
@@ -1,3 +1,4 @@
1
+ import "../chunk-FOSOWSXV.js";
1
2
  import {
2
3
  createSQLiteAdapter
3
4
  } from "../chunk-CJDIVWO3.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cancia/astro",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Astro integration for Cancia CMS — inline editing with zero separate server",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -32,6 +32,10 @@
32
32
  "types": "./dist/cache.d.ts",
33
33
  "import": "./dist/cache.js"
34
34
  },
35
+ "./content": {
36
+ "types": "./dist/content.d.ts",
37
+ "import": "./dist/content.js"
38
+ },
35
39
  "./richtext": {
36
40
  "types": "./dist/richtext/index.d.ts",
37
41
  "import": "./dist/richtext/index.js"