@cancia/astro 0.9.0 → 0.11.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.
@@ -1,15 +1,15 @@
1
1
  import {
2
- detectImageType,
2
+ detectUploadType,
3
3
  isValidSite
4
- } from "./chunk-5IPHDIC6.js";
4
+ } from "./chunk-RHFTQW4W.js";
5
5
  import {
6
- createGitBackedAdapter,
7
- createSqliteAdapterV2
8
- } from "./chunk-MXVOJRAM.js";
6
+ createGitBackedAdapter
7
+ } from "./chunk-XINNLVZP.js";
9
8
  import {
10
9
  createJsonFileAdapter,
11
- createJsonFileAdapterV2
12
- } from "./chunk-2NVZWZPE.js";
10
+ createJsonFileAdapterV2,
11
+ createSqliteAdapterV2
12
+ } from "./chunk-S5YLB6P3.js";
13
13
 
14
14
  // src/routes/upload.ts
15
15
  import { writeFile, mkdir } from "fs/promises";
@@ -51,9 +51,9 @@ function makeUploadRoute(uploadHandler, secret, maxMB = 10) {
51
51
  return new Response(JSON.stringify({ error: `File too large (max ${maxMB}MB)` }), { status: 413 });
52
52
  }
53
53
  const buf = new Uint8Array(await file.arrayBuffer());
54
- const detected = detectImageType(buf);
54
+ const detected = detectUploadType(buf);
55
55
  if (!detected) {
56
- return new Response(JSON.stringify({ error: "File type not allowed" }), { status: 415 });
56
+ return new Response(JSON.stringify({ error: "That file type is not supported. Use a JPEG, PNG, GIF, WebP, AVIF or PDF." }), { status: 415 });
57
57
  }
58
58
  const url = await uploadHandler(file, site, detected);
59
59
  return new Response(JSON.stringify({ url }), {
package/dist/content.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import "./chunk-FOSOWSXV.js";
2
2
  import "./chunk-CJDIVWO3.js";
3
+ import "./chunk-XINNLVZP.js";
4
+ import "./chunk-U7V53JX7.js";
3
5
  import {
4
6
  createSqliteAdapterV2
5
- } from "./chunk-MXVOJRAM.js";
6
- import "./chunk-U7V53JX7.js";
7
- import "./chunk-2NVZWZPE.js";
7
+ } from "./chunk-S5YLB6P3.js";
8
8
  import "./chunk-7IA5B5CF.js";
9
9
 
10
10
  // src/content.ts
@@ -20,17 +20,17 @@ function isSafeHref(href) {
20
20
  return true;
21
21
  }
22
22
  function parseLink(raw, fallback) {
23
- if (!raw) return fallback;
23
+ if (raw === void 0) return fallback;
24
+ if (raw === "") return { label: "", href: "" };
24
25
  const trimmed = raw.trim();
25
26
  if (trimmed.startsWith("{")) {
26
27
  try {
27
28
  const p = JSON.parse(trimmed);
28
29
  if (p && typeof p === "object") {
29
- const href = String(p.href ?? "");
30
- return {
31
- label: String(p.label ?? "") || fallback.label,
32
- href: href && isSafeHref(href) ? href : fallback.href
33
- };
30
+ const label = p.label === void 0 ? fallback.label : String(p.label);
31
+ const rawHref = p.href === void 0 ? void 0 : String(p.href);
32
+ const href = rawHref === void 0 ? fallback.href : rawHref === "" ? "" : isSafeHref(rawHref) ? rawHref : fallback.href;
33
+ return { label, href };
34
34
  }
35
35
  } catch {
36
36
  }
@@ -4,7 +4,7 @@ import {
4
4
  } from "../chunk-VGRG5DN7.js";
5
5
  import {
6
6
  makeListsRoutes
7
- } from "../chunk-DIV2FFYX.js";
7
+ } from "../chunk-GD37XVES.js";
8
8
  import "../chunk-X6ZFFGIA.js";
9
9
  import "../chunk-VL6FO446.js";
10
10
  import "../chunk-7IA5B5CF.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  makeSchemasRoute
3
- } from "../chunk-HQIGNRIU.js";
3
+ } from "../chunk-T2GDBQJ7.js";
4
4
  import "../chunk-VL6FO446.js";
5
- import "../chunk-WVHTCFE6.js";
5
+ import "../chunk-QQEUCOXQ.js";
6
6
  import "../chunk-KHCFVVYV.js";
7
7
 
8
8
  // src/endpoints/schemas.ts
@@ -1,7 +1,7 @@
1
1
  import {
2
- detectImageType,
2
+ detectUploadType,
3
3
  isValidSite
4
- } from "../chunk-5IPHDIC6.js";
4
+ } from "../chunk-RHFTQW4W.js";
5
5
 
6
6
  // src/endpoints/upload.ts
7
7
  import { getCanciaRuntime } from "virtual:cancia/runtime";
@@ -28,9 +28,9 @@ async function POST({ request }) {
28
28
  { status: 413 }
29
29
  );
30
30
  const buf = new Uint8Array(await file.arrayBuffer());
31
- const detected = detectImageType(buf);
31
+ const detected = detectUploadType(buf);
32
32
  if (!detected)
33
- return new Response(JSON.stringify({ error: "File type not allowed" }), { status: 415 });
33
+ return new Response(JSON.stringify({ error: "That file type is not supported. Use a JPEG, PNG, GIF, WebP, AVIF or PDF." }), { status: 415 });
34
34
  const url = await uploadHandler(file, site, detected);
35
35
  return new Response(JSON.stringify({ url }), {
36
36
  headers: { "Content-Type": "application/json" }
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeSchemasRoute
3
- } from "./chunk-HQIGNRIU.js";
3
+ } from "./chunk-T2GDBQJ7.js";
4
4
  import {
5
5
  runPublish
6
6
  } from "./chunk-5RCLBWRH.js";
@@ -10,31 +10,31 @@ import {
10
10
  } from "./chunk-GJIX7MWC.js";
11
11
  import {
12
12
  makeListsRoutes
13
- } from "./chunk-DIV2FFYX.js";
13
+ } from "./chunk-GD37XVES.js";
14
14
  import {
15
15
  makeLocalUploadHandler,
16
16
  makeR2UploadHandler,
17
17
  makeUploadRoute,
18
18
  setCanciaRuntime
19
- } from "./chunk-LJSSPOSW.js";
20
- import "./chunk-5IPHDIC6.js";
19
+ } from "./chunk-ZPXMPLQU.js";
20
+ import "./chunk-RHFTQW4W.js";
21
21
  import {
22
22
  createSQLiteAdapter
23
23
  } from "./chunk-CJDIVWO3.js";
24
24
  import {
25
- closeSqliteAdapterV2,
26
- createGitBackedAdapter,
27
- createSqliteAdapterV2
28
- } from "./chunk-MXVOJRAM.js";
25
+ createGitBackedAdapter
26
+ } from "./chunk-XINNLVZP.js";
29
27
  import "./chunk-U7V53JX7.js";
30
28
  import "./chunk-VL6FO446.js";
31
29
  import {
32
30
  canciaLoader
33
- } from "./chunk-GBTFXQEA.js";
31
+ } from "./chunk-TUZNTXZR.js";
34
32
  import {
33
+ closeSqliteAdapterV2,
35
34
  createJsonFileAdapter,
36
- createJsonFileAdapterV2
37
- } from "./chunk-2NVZWZPE.js";
35
+ createJsonFileAdapterV2,
36
+ createSqliteAdapterV2
37
+ } from "./chunk-S5YLB6P3.js";
38
38
  import {
39
39
  RevConflictError
40
40
  } from "./chunk-7IA5B5CF.js";
@@ -43,7 +43,7 @@ import {
43
43
  defineList,
44
44
  describeList,
45
45
  z
46
- } from "./chunk-WVHTCFE6.js";
46
+ } from "./chunk-QQEUCOXQ.js";
47
47
  import "./chunk-KHCFVVYV.js";
48
48
 
49
49
  // src/integration.ts
@@ -13,9 +13,29 @@ interface CanciaLoaderOptions {
13
13
  */
14
14
  site: string;
15
15
  /**
16
- * Custom storage adapter. Defaults to the JSON-file v2 adapter rooted at
17
- * `process.cwd()` — which is the project root during Astro's content sync.
18
- * Override to point at a different location (testing, monorepos, etc.).
16
+ * Where this site's content lives MIRROR THE INTEGRATION'S `db` OPTION.
17
+ *
18
+ * cancia({ db: { kind: "sqlite" } }) // astro.config.mjs
19
+ * canciaLoader({ …, db: { kind: "sqlite" } }) // content.config.ts
20
+ *
21
+ * It has to be repeated because `content.config.ts` is evaluated by Astro
22
+ * BEFORE the integration's hooks run, so the loader cannot read the baked
23
+ * config the way the SSR runtime does.
24
+ *
25
+ * Omitting it on a sqlite-backed site is the bug this option exists to make
26
+ * visible: the loader used to hardcode the JSON-file adapter, so it read an
27
+ * empty directory and `getCollection()` returned nothing — silently, because
28
+ * "no entries" is a legitimate state. A page using the common
29
+ * `entries.length > 0 ? entries : seeded` fallback then rendered its
30
+ * hardcoded seed array and looked entirely correct.
31
+ */
32
+ db?: {
33
+ kind: "sqlite" | "json-file";
34
+ path?: string;
35
+ };
36
+ /**
37
+ * Custom storage adapter. Wins over `db` — for tests, monorepos, or a
38
+ * backend Cancia does not know about.
19
39
  */
20
40
  storage?: CanciaStorageV2;
21
41
  /**
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  canciaLoader
3
- } from "../chunk-GBTFXQEA.js";
4
- import "../chunk-2NVZWZPE.js";
3
+ } from "../chunk-TUZNTXZR.js";
4
+ import "../chunk-S5YLB6P3.js";
5
5
  import "../chunk-7IA5B5CF.js";
6
- import "../chunk-WVHTCFE6.js";
6
+ import "../chunk-QQEUCOXQ.js";
7
7
  import "../chunk-KHCFVVYV.js";
8
8
  export {
9
9
  canciaLoader
package/dist/runtime.js CHANGED
@@ -3,11 +3,11 @@ import {
3
3
  getCanciaRuntime,
4
4
  setBakedConfig,
5
5
  setCanciaRuntime
6
- } from "./chunk-LJSSPOSW.js";
7
- import "./chunk-5IPHDIC6.js";
8
- import "./chunk-MXVOJRAM.js";
6
+ } from "./chunk-ZPXMPLQU.js";
7
+ import "./chunk-RHFTQW4W.js";
8
+ import "./chunk-XINNLVZP.js";
9
9
  import "./chunk-U7V53JX7.js";
10
- import "./chunk-2NVZWZPE.js";
10
+ import "./chunk-S5YLB6P3.js";
11
11
  import "./chunk-7IA5B5CF.js";
12
12
  export {
13
13
  __resetRuntimeForTests,
@@ -16,7 +16,7 @@ export { P as PT_DECORATORS, a as PT_LIST_ITEMS, b as PT_STYLES, c as PortableTe
16
16
  * z.boolean() → "checkbox"
17
17
  * z.enum([...]) → "select"
18
18
  */
19
- type FieldWidget = "text" | "textarea" | "url" | "email" | "datetime" | "number" | "checkbox" | "select" | "image" | "slug" | "array" | "object" | "reference" | "richtext" | "link";
19
+ type FieldWidget = "text" | "textarea" | "url" | "email" | "datetime" | "number" | "checkbox" | "select" | "image" | "file" | "slug" | "array" | "object" | "reference" | "richtext" | "link";
20
20
  /**
21
21
  * Fields common to every widget's metadata. All optional.
22
22
  */
@@ -49,6 +49,8 @@ type FieldMeta = (FieldMetaBase & {
49
49
  }) | (FieldMetaBase & {
50
50
  widget: "image";
51
51
  alt?: boolean;
52
+ }) | (FieldMetaBase & {
53
+ widget: "file";
52
54
  }) | (FieldMetaBase & {
53
55
  widget: "slug";
54
56
  source?: string;
@@ -204,6 +206,17 @@ declare const defineField: {
204
206
  image: (o?: FieldMetaBase & {
205
207
  alt?: boolean;
206
208
  }) => z.ZodString;
209
+ /**
210
+ * An uploaded document — a PDF today.
211
+ *
212
+ * Stores a URL exactly as `image` does, because the upload path is the same:
213
+ * the file goes to the configured store (R2, or public/uploads) and what
214
+ * comes back is a plain URL. A separate widget rather than reusing `image`
215
+ * so the editor renders a filename and a download affordance instead of a
216
+ * thumbnail, and so an `image` field cannot silently accept a PDF and
217
+ * render a broken <img>.
218
+ */
219
+ file: (o?: FieldMetaBase) => z.ZodString;
207
220
  select: (o: FieldMetaBase & {
208
221
  options: string[];
209
222
  }) => z.ZodEnum<{
@@ -8,7 +8,7 @@ import {
8
8
  serializeLinkValue,
9
9
  slugify,
10
10
  z
11
- } from "../chunk-WVHTCFE6.js";
11
+ } from "../chunk-QQEUCOXQ.js";
12
12
  import {
13
13
  PT_DECORATORS,
14
14
  PT_LIST_ITEMS,
@@ -3,19 +3,19 @@ import {
3
3
  createSQLiteAdapter
4
4
  } from "../chunk-CJDIVWO3.js";
5
5
  import {
6
- closeSqliteAdapterV2,
7
- createGitBackedAdapter,
8
- createSqliteAdapterV2
9
- } from "../chunk-MXVOJRAM.js";
6
+ createGitBackedAdapter
7
+ } from "../chunk-XINNLVZP.js";
10
8
  import {
11
9
  createGitHubClient
12
10
  } from "../chunk-U7V53JX7.js";
13
11
  import {
14
12
  canonicalize,
13
+ closeSqliteAdapterV2,
15
14
  createJsonFileAdapter,
16
15
  createJsonFileAdapterV2,
16
+ createSqliteAdapterV2,
17
17
  hashRev
18
- } from "../chunk-2NVZWZPE.js";
18
+ } from "../chunk-S5YLB6P3.js";
19
19
  import {
20
20
  RevConflictError
21
21
  } from "../chunk-7IA5B5CF.js";
@@ -44,11 +44,10 @@ function __canciaLink(cms, key, labelFallback, hrefFallback) {
44
44
  if (trimmed.startsWith("{")) {
45
45
  try {
46
46
  const parsed = JSON.parse(trimmed);
47
- const href = String(parsed.href ?? "");
48
- return {
49
- label: String(parsed.label ?? "") || labelFallback,
50
- href: href && isSafeHref(href) ? href : hrefFallback
51
- };
47
+ const label = parsed.label === void 0 ? labelFallback : String(parsed.label);
48
+ const rawHref = parsed.href === void 0 ? void 0 : String(parsed.href);
49
+ const href = rawHref === void 0 ? hrefFallback : rawHref === "" ? "" : isSafeHref(rawHref) ? rawHref : hrefFallback;
50
+ return { label, href };
52
51
  } catch {
53
52
  return fallback;
54
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cancia/astro",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Astro integration for Cancia CMS — inline editing with zero separate server",
5
5
  "license": "MIT",
6
6
  "repository": {