@cancia/astro 0.5.0 → 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.
- package/dist/{chunk-YZH7QWZV.js → chunk-AGNPUTKS.js} +12 -1
- package/dist/chunk-FOSOWSXV.js +0 -0
- package/dist/content.d.ts +60 -0
- package/dist/content.js +52 -0
- package/dist/endpoints/lists.js +5 -5
- package/dist/index.js +1 -1
- package/dist/runtime.d.ts +9 -1
- package/dist/runtime.js +3 -1
- package/dist/storage/index.js +1 -0
- package/package.json +5 -1
|
@@ -166,10 +166,20 @@ function setBakedConfig(config) {
|
|
|
166
166
|
function setCanciaRuntime(runtime) {
|
|
167
167
|
_runtime = runtime;
|
|
168
168
|
}
|
|
169
|
+
function __resetRuntimeForTests() {
|
|
170
|
+
_runtime = null;
|
|
171
|
+
_bakedConfig = null;
|
|
172
|
+
}
|
|
169
173
|
function buildRuntimeFromBaked(baked) {
|
|
170
174
|
const projectRoot = baked.projectRoot || process.cwd();
|
|
171
175
|
const token = process.env.CANCIA_TOKEN?.trim() || "";
|
|
172
|
-
const
|
|
176
|
+
const isPublic = baked.public === true;
|
|
177
|
+
if (!isPublic && !token) {
|
|
178
|
+
throw new Error(
|
|
179
|
+
"[cancia] CANCIA_TOKEN is not set but this site is not public \u2014 refusing to start to avoid serving an open, unauthenticated mutation API. Set CANCIA_TOKEN in the deployed process, or set public:true if anonymous editing is intended."
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
const secret = isPublic ? void 0 : token;
|
|
173
183
|
const redeployHook = baked.redeployHook || void 0;
|
|
174
184
|
const deployHook = redeployHook || process.env.CANCIA_DEPLOY_HOOK || void 0;
|
|
175
185
|
const deployHookToken = process.env.CANCIA_DEPLOY_HOOK_TOKEN || void 0;
|
|
@@ -261,5 +271,6 @@ export {
|
|
|
261
271
|
makeR2UploadHandler,
|
|
262
272
|
setBakedConfig,
|
|
263
273
|
setCanciaRuntime,
|
|
274
|
+
__resetRuntimeForTests,
|
|
264
275
|
getCanciaRuntime
|
|
265
276
|
};
|
|
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 };
|
package/dist/content.js
ADDED
|
@@ -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
|
+
};
|
package/dist/endpoints/lists.js
CHANGED
|
@@ -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";
|
package/dist/index.js
CHANGED
package/dist/runtime.d.ts
CHANGED
|
@@ -146,6 +146,14 @@ declare function setBakedConfig(config: BakedConfig): void;
|
|
|
146
146
|
* to lazy init instead.
|
|
147
147
|
*/
|
|
148
148
|
declare function setCanciaRuntime(runtime: CanciaRuntime): void;
|
|
149
|
+
/**
|
|
150
|
+
* TEST-ONLY: clear both module singletons so the next getCanciaRuntime() rebuilds
|
|
151
|
+
* from scratch. Production never calls this — the virtual module supplies baked
|
|
152
|
+
* config exactly once and endpoints share the built runtime for the process
|
|
153
|
+
* lifetime. Needed only because a mocked virtual:cancia/runtime module survives
|
|
154
|
+
* vitest's vi.resetModules() (its singletons would otherwise leak across cases).
|
|
155
|
+
*/
|
|
156
|
+
declare function __resetRuntimeForTests(): void;
|
|
149
157
|
declare function getCanciaRuntime(): CanciaRuntime;
|
|
150
158
|
|
|
151
|
-
export { type BakedConfig, type BakedR2Config, type BakedStorageDescriptor, type CanciaRuntime, type PublishMode, getCanciaRuntime, setBakedConfig, setCanciaRuntime };
|
|
159
|
+
export { type BakedConfig, type BakedR2Config, type BakedStorageDescriptor, type CanciaRuntime, type PublishMode, __resetRuntimeForTests, getCanciaRuntime, setBakedConfig, setCanciaRuntime };
|
package/dist/runtime.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
__resetRuntimeForTests,
|
|
2
3
|
getCanciaRuntime,
|
|
3
4
|
setBakedConfig,
|
|
4
5
|
setCanciaRuntime
|
|
5
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-AGNPUTKS.js";
|
|
6
7
|
import "./chunk-5IPHDIC6.js";
|
|
7
8
|
import "./chunk-GNWD7EL2.js";
|
|
8
9
|
import "./chunk-U7V53JX7.js";
|
|
9
10
|
import "./chunk-L2VKQJPY.js";
|
|
10
11
|
import "./chunk-7IA5B5CF.js";
|
|
11
12
|
export {
|
|
13
|
+
__resetRuntimeForTests,
|
|
12
14
|
getCanciaRuntime,
|
|
13
15
|
setBakedConfig,
|
|
14
16
|
setCanciaRuntime
|
package/dist/storage/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cancia/astro",
|
|
3
|
-
"version": "0.
|
|
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"
|