@jant/core 0.2.15 → 0.2.17
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/app.d.ts +4 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +13 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/config.d.ts +49 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +79 -0
- package/dist/routes/dash/collections.d.ts.map +1 -1
- package/dist/routes/dash/collections.js +5 -4
- package/dist/routes/dash/index.d.ts.map +1 -1
- package/dist/routes/dash/index.js +2 -1
- package/dist/routes/dash/media.d.ts.map +1 -1
- package/dist/routes/dash/media.js +3 -2
- package/dist/routes/dash/pages.d.ts.map +1 -1
- package/dist/routes/dash/pages.js +5 -4
- package/dist/routes/dash/posts.d.ts.map +1 -1
- package/dist/routes/dash/posts.js +5 -4
- package/dist/routes/dash/redirects.d.ts.map +1 -1
- package/dist/routes/dash/redirects.js +3 -2
- package/dist/routes/dash/settings.d.ts.map +1 -1
- package/dist/routes/dash/settings.js +4 -4
- package/dist/routes/pages/archive.d.ts.map +1 -1
- package/dist/routes/pages/archive.js +2 -1
- package/dist/routes/pages/collection.d.ts.map +1 -1
- package/dist/routes/pages/collection.js +2 -1
- package/dist/routes/pages/home.d.ts.map +1 -1
- package/dist/routes/pages/home.js +2 -1
- package/dist/routes/pages/page.d.ts.map +1 -1
- package/dist/routes/pages/page.js +2 -1
- package/dist/routes/pages/post.d.ts.map +1 -1
- package/dist/routes/pages/post.js +2 -1
- package/dist/routes/pages/search.d.ts.map +1 -1
- package/dist/routes/pages/search.js +2 -1
- package/dist/types.d.ts +11 -31
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/app.tsx +14 -4
- package/src/index.ts +0 -2
- package/src/lib/config.ts +94 -0
- package/src/routes/dash/collections.tsx +5 -4
- package/src/routes/dash/index.tsx +2 -1
- package/src/routes/dash/media.tsx +3 -2
- package/src/routes/dash/pages.tsx +5 -4
- package/src/routes/dash/posts.tsx +5 -4
- package/src/routes/dash/redirects.tsx +3 -2
- package/src/routes/dash/settings.tsx +8 -4
- package/src/routes/pages/archive.tsx +2 -1
- package/src/routes/pages/collection.tsx +2 -1
- package/src/routes/pages/home.tsx +2 -1
- package/src/routes/pages/page.tsx +2 -1
- package/src/routes/pages/post.tsx +2 -1
- package/src/routes/pages/search.tsx +2 -1
- package/src/types.ts +12 -33
package/dist/app.d.ts
CHANGED
|
@@ -20,12 +20,15 @@ export type App = Hono<{
|
|
|
20
20
|
* @param config - Optional configuration
|
|
21
21
|
* @returns Hono app instance
|
|
22
22
|
*
|
|
23
|
+
* Site settings (name, description, language) should be configured via
|
|
24
|
+
* environment variables (SITE_NAME, SITE_DESCRIPTION, SITE_LANGUAGE).
|
|
25
|
+
* They can also be set in the dashboard, which stores them in the database.
|
|
26
|
+
*
|
|
23
27
|
* @example
|
|
24
28
|
* ```typescript
|
|
25
29
|
* import { createApp } from "@jant/core";
|
|
26
30
|
*
|
|
27
31
|
* export default createApp({
|
|
28
|
-
* site: { name: "My Blog" },
|
|
29
32
|
* theme: { components: { PostCard: MyPostCard } },
|
|
30
33
|
* });
|
|
31
34
|
* ```
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AAGlD,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoCvD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AAExE
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AAGlD,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoCvD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AAExE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,MAAM,GAAE,UAAe,GAAG,GAAG,CA2dtD"}
|
package/dist/app.js
CHANGED
|
@@ -40,12 +40,15 @@ import { sse } from "./lib/sse.js";
|
|
|
40
40
|
* @param config - Optional configuration
|
|
41
41
|
* @returns Hono app instance
|
|
42
42
|
*
|
|
43
|
+
* Site settings (name, description, language) should be configured via
|
|
44
|
+
* environment variables (SITE_NAME, SITE_DESCRIPTION, SITE_LANGUAGE).
|
|
45
|
+
* They can also be set in the dashboard, which stores them in the database.
|
|
46
|
+
*
|
|
43
47
|
* @example
|
|
44
48
|
* ```typescript
|
|
45
49
|
* import { createApp } from "@jant/core";
|
|
46
50
|
*
|
|
47
51
|
* export default createApp({
|
|
48
|
-
* site: { name: "My Blog" },
|
|
49
52
|
* theme: { components: { PostCard: MyPostCard } },
|
|
50
53
|
* });
|
|
51
54
|
* ```
|
|
@@ -53,12 +56,18 @@ import { sse } from "./lib/sse.js";
|
|
|
53
56
|
const app = new Hono();
|
|
54
57
|
// Initialize services, auth, and config middleware
|
|
55
58
|
app.use("*", async (c, next)=>{
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
// Use withSession() to enable D1 Read Replication
|
|
60
|
+
// Automatically routes read queries to the nearest replica for lower latency
|
|
61
|
+
// See: https://developers.cloudflare.com/d1/best-practices/read-replication/
|
|
62
|
+
const session = c.env.DB.withSession();
|
|
63
|
+
// Note: Drizzle ORM doesn't officially support D1DatabaseSession yet (issue #2226)
|
|
64
|
+
// but it works at runtime. We use type assertion as a temporary workaround.
|
|
65
|
+
const db = createDatabase(session);
|
|
66
|
+
const services = createServices(db, session);
|
|
58
67
|
c.set("services", services);
|
|
59
68
|
c.set("config", config);
|
|
60
69
|
if (c.env.AUTH_SECRET) {
|
|
61
|
-
const auth = createAuth(
|
|
70
|
+
const auth = createAuth(session, {
|
|
62
71
|
secret: c.env.AUTH_SECRET,
|
|
63
72
|
baseURL: c.env.SITE_URL
|
|
64
73
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export { createApp } from "./app.js";
|
|
7
7
|
export type { App, AppVariables } from "./app.js";
|
|
8
|
-
export type { PostType, Visibility, Bindings, Post, Media, Collection, PostCollection, Redirect, Setting, CreatePost, UpdatePost, JantConfig, JantTheme,
|
|
8
|
+
export type { PostType, Visibility, Bindings, Post, Media, Collection, PostCollection, Redirect, Setting, CreatePost, UpdatePost, JantConfig, JantTheme, ThemeComponents, } from "./types.js";
|
|
9
9
|
export { POST_TYPES, VISIBILITY_LEVELS } from "./types.js";
|
|
10
10
|
export * as time from "./lib/time.js";
|
|
11
11
|
export * as sqid from "./lib/sqid.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGlD,YAAY,EACV,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,OAAO,EACP,UAAU,EACV,UAAU,EACV,UAAU,EACV,SAAS,EACT,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGlD,YAAY,EACV,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,OAAO,EACP,UAAU,EACV,UAAU,EACV,UAAU,EACV,SAAS,EACT,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG3D,OAAO,KAAK,IAAI,MAAM,eAAe,CAAC;AACtC,OAAO,KAAK,IAAI,MAAM,eAAe,CAAC;AACtC,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAC;;AAG9C,wBAA4B"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Configuration Helpers
|
|
3
|
+
*
|
|
4
|
+
* Configuration priority: Environment Variables > Database > Default Values
|
|
5
|
+
*
|
|
6
|
+
* This follows the 12-factor app methodology where configuration is stored
|
|
7
|
+
* in environment variables, while allowing runtime overrides via database.
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from "hono";
|
|
10
|
+
/**
|
|
11
|
+
* Get site name with fallback chain: ENV > DB > Default
|
|
12
|
+
*
|
|
13
|
+
* @param c - Hono context
|
|
14
|
+
* @returns Site name
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const siteName = await getSiteName(c);
|
|
19
|
+
* // Returns: c.env.SITE_NAME ?? (DB: SITE_NAME) ?? "Jant"
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function getSiteName(c: Context): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Get site description with fallback chain: ENV > DB > Default
|
|
25
|
+
*
|
|
26
|
+
* @param c - Hono context
|
|
27
|
+
* @returns Site description
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const description = await getSiteDescription(c);
|
|
32
|
+
* // Returns: c.env.SITE_DESCRIPTION ?? (DB: SITE_DESCRIPTION) ?? "A microblog powered by Jant"
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function getSiteDescription(c: Context): Promise<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Get site language with fallback chain: ENV > DB > Default
|
|
38
|
+
*
|
|
39
|
+
* @param c - Hono context
|
|
40
|
+
* @returns Site language code
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const lang = await getSiteLanguage(c);
|
|
45
|
+
* // Returns: c.env.SITE_LANGUAGE ?? (DB: SITE_LANGUAGE) ?? "en"
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function getSiteLanguage(c: Context): Promise<string>;
|
|
49
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAc7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAcpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAcjE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Configuration Helpers
|
|
3
|
+
*
|
|
4
|
+
* Configuration priority: Environment Variables > Database > Default Values
|
|
5
|
+
*
|
|
6
|
+
* This follows the 12-factor app methodology where configuration is stored
|
|
7
|
+
* in environment variables, while allowing runtime overrides via database.
|
|
8
|
+
*/ /**
|
|
9
|
+
* Get site name with fallback chain: ENV > DB > Default
|
|
10
|
+
*
|
|
11
|
+
* @param c - Hono context
|
|
12
|
+
* @returns Site name
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const siteName = await getSiteName(c);
|
|
17
|
+
* // Returns: c.env.SITE_NAME ?? (DB: SITE_NAME) ?? "Jant"
|
|
18
|
+
* ```
|
|
19
|
+
*/ export async function getSiteName(c) {
|
|
20
|
+
// 1. Check environment variable
|
|
21
|
+
if (c.env.SITE_NAME) {
|
|
22
|
+
return c.env.SITE_NAME;
|
|
23
|
+
}
|
|
24
|
+
// 2. Check database setting
|
|
25
|
+
const dbValue = await c.var.services.settings.get("SITE_NAME");
|
|
26
|
+
if (dbValue) {
|
|
27
|
+
return dbValue;
|
|
28
|
+
}
|
|
29
|
+
// 3. Default value
|
|
30
|
+
return "Jant";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get site description with fallback chain: ENV > DB > Default
|
|
34
|
+
*
|
|
35
|
+
* @param c - Hono context
|
|
36
|
+
* @returns Site description
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const description = await getSiteDescription(c);
|
|
41
|
+
* // Returns: c.env.SITE_DESCRIPTION ?? (DB: SITE_DESCRIPTION) ?? "A microblog powered by Jant"
|
|
42
|
+
* ```
|
|
43
|
+
*/ export async function getSiteDescription(c) {
|
|
44
|
+
// 1. Check environment variable
|
|
45
|
+
if (c.env.SITE_DESCRIPTION) {
|
|
46
|
+
return c.env.SITE_DESCRIPTION;
|
|
47
|
+
}
|
|
48
|
+
// 2. Check database setting
|
|
49
|
+
const dbValue = await c.var.services.settings.get("SITE_DESCRIPTION");
|
|
50
|
+
if (dbValue) {
|
|
51
|
+
return dbValue;
|
|
52
|
+
}
|
|
53
|
+
// 3. Default value
|
|
54
|
+
return "A microblog powered by Jant";
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get site language with fallback chain: ENV > DB > Default
|
|
58
|
+
*
|
|
59
|
+
* @param c - Hono context
|
|
60
|
+
* @returns Site language code
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const lang = await getSiteLanguage(c);
|
|
65
|
+
* // Returns: c.env.SITE_LANGUAGE ?? (DB: SITE_LANGUAGE) ?? "en"
|
|
66
|
+
* ```
|
|
67
|
+
*/ export async function getSiteLanguage(c) {
|
|
68
|
+
// 1. Check environment variable
|
|
69
|
+
if (c.env.SITE_LANGUAGE) {
|
|
70
|
+
return c.env.SITE_LANGUAGE;
|
|
71
|
+
}
|
|
72
|
+
// 2. Check database setting
|
|
73
|
+
const dbValue = await c.var.services.settings.get("SITE_LANGUAGE");
|
|
74
|
+
if (dbValue) {
|
|
75
|
+
return dbValue;
|
|
76
|
+
}
|
|
77
|
+
// 3. Default value
|
|
78
|
+
return "en";
|
|
79
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/collections.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/collections.tsx"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAYjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,iBAAiB,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Dashboard Collections Routes
|
|
4
5
|
*/ import { Hono } from "hono";
|
|
@@ -396,7 +397,7 @@ function EditCollectionContent({ collection }) {
|
|
|
396
397
|
}
|
|
397
398
|
// List collections
|
|
398
399
|
collectionsRoutes.get("/", async (c)=>{
|
|
399
|
-
const siteName = await c
|
|
400
|
+
const siteName = await getSiteName(c);
|
|
400
401
|
const collections = await c.var.services.collections.list();
|
|
401
402
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
402
403
|
c: c,
|
|
@@ -410,7 +411,7 @@ collectionsRoutes.get("/", async (c)=>{
|
|
|
410
411
|
});
|
|
411
412
|
// New collection form
|
|
412
413
|
collectionsRoutes.get("/new", async (c)=>{
|
|
413
|
-
const siteName = await c
|
|
414
|
+
const siteName = await getSiteName(c);
|
|
414
415
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
415
416
|
c: c,
|
|
416
417
|
title: "New Collection",
|
|
@@ -438,7 +439,7 @@ collectionsRoutes.get("/:id", async (c)=>{
|
|
|
438
439
|
const collection = await c.var.services.collections.getById(id);
|
|
439
440
|
if (!collection) return c.notFound();
|
|
440
441
|
const posts = await c.var.services.collections.getPosts(id);
|
|
441
|
-
const siteName = await c
|
|
442
|
+
const siteName = await getSiteName(c);
|
|
442
443
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
443
444
|
c: c,
|
|
444
445
|
title: collection.title,
|
|
@@ -456,7 +457,7 @@ collectionsRoutes.get("/:id/edit", async (c)=>{
|
|
|
456
457
|
if (isNaN(id)) return c.notFound();
|
|
457
458
|
const collection = await c.var.services.collections.getById(id);
|
|
458
459
|
if (!collection) return c.notFound();
|
|
459
|
-
const siteName = await c
|
|
460
|
+
const siteName = await getSiteName(c);
|
|
460
461
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
461
462
|
c: c,
|
|
462
463
|
title: `Edit: ${collection.title}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/index.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/index.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,eAAe,kDAAkB,CAAC"}
|
|
@@ -7,6 +7,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
|
7
7
|
import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
8
8
|
import { Trans as Trans_ } from "@jant/core/i18n";
|
|
9
9
|
import { DashLayout } from "../../theme/layouts/index.js";
|
|
10
|
+
import { getSiteName } from "../../lib/config.js";
|
|
10
11
|
export const dashIndexRoutes = new Hono();
|
|
11
12
|
/**
|
|
12
13
|
* Dashboard content component
|
|
@@ -97,7 +98,7 @@ export const dashIndexRoutes = new Hono();
|
|
|
97
98
|
});
|
|
98
99
|
}
|
|
99
100
|
dashIndexRoutes.get("/", async (c)=>{
|
|
100
|
-
const siteName = await c
|
|
101
|
+
const siteName = await getSiteName(c);
|
|
101
102
|
// Get some stats
|
|
102
103
|
const allPosts = await c.var.services.posts.list({
|
|
103
104
|
limit: 1000
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/media.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/media.tsx"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAS,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAOjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,WAAW,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Dashboard Media Routes
|
|
4
5
|
*
|
|
@@ -530,7 +531,7 @@ function processSSEEvent(event) {
|
|
|
530
531
|
// List media
|
|
531
532
|
mediaRoutes.get("/", async (c)=>{
|
|
532
533
|
const mediaList = await c.var.services.media.list(100);
|
|
533
|
-
const siteName = await c
|
|
534
|
+
const siteName = await getSiteName(c);
|
|
534
535
|
const r2PublicUrl = c.env.R2_PUBLIC_URL;
|
|
535
536
|
const imageTransformUrl = c.env.IMAGE_TRANSFORM_URL;
|
|
536
537
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
@@ -550,7 +551,7 @@ mediaRoutes.get("/:id", async (c)=>{
|
|
|
550
551
|
const id = c.req.param("id");
|
|
551
552
|
const media = await c.var.services.media.getById(id);
|
|
552
553
|
if (!media) return c.notFound();
|
|
553
|
-
const siteName = await c
|
|
554
|
+
const siteName = await getSiteName(c);
|
|
554
555
|
const r2PublicUrl = c.env.R2_PUBLIC_URL;
|
|
555
556
|
const imageTransformUrl = c.env.IMAGE_TRANSFORM_URL;
|
|
556
557
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/pages.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/pages.tsx"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAejD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,WAAW,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Dashboard Pages Routes
|
|
4
5
|
*
|
|
@@ -191,7 +192,7 @@ pagesRoutes.get("/", async (c)=>{
|
|
|
191
192
|
],
|
|
192
193
|
limit: 100
|
|
193
194
|
});
|
|
194
|
-
const siteName = await c
|
|
195
|
+
const siteName = await getSiteName(c);
|
|
195
196
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
196
197
|
c: c,
|
|
197
198
|
title: "Pages",
|
|
@@ -204,7 +205,7 @@ pagesRoutes.get("/", async (c)=>{
|
|
|
204
205
|
});
|
|
205
206
|
// New page form
|
|
206
207
|
pagesRoutes.get("/new", async (c)=>{
|
|
207
|
-
const siteName = await c
|
|
208
|
+
const siteName = await getSiteName(c);
|
|
208
209
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
209
210
|
c: c,
|
|
210
211
|
title: "New Page",
|
|
@@ -233,7 +234,7 @@ pagesRoutes.get("/:id", async (c)=>{
|
|
|
233
234
|
if (!id) return c.notFound();
|
|
234
235
|
const page = await c.var.services.posts.getById(id);
|
|
235
236
|
if (!page || page.type !== "page") return c.notFound();
|
|
236
|
-
const siteName = await c
|
|
237
|
+
const siteName = await getSiteName(c);
|
|
237
238
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
238
239
|
c: c,
|
|
239
240
|
title: page.title || "Page",
|
|
@@ -250,7 +251,7 @@ pagesRoutes.get("/:id/edit", async (c)=>{
|
|
|
250
251
|
if (!id) return c.notFound();
|
|
251
252
|
const page = await c.var.services.posts.getById(id);
|
|
252
253
|
if (!page || page.type !== "page") return c.notFound();
|
|
253
|
-
const siteName = await c
|
|
254
|
+
const siteName = await getSiteName(c);
|
|
254
255
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
255
256
|
c: c,
|
|
256
257
|
title: `Edit: ${page.title || "Page"}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posts.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/posts.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"posts.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/posts.tsx"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAWjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,WAAW,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Dashboard Posts Routes
|
|
4
5
|
*/ import { Hono } from "hono";
|
|
@@ -56,7 +57,7 @@ postsRoutes.get("/", async (c)=>{
|
|
|
56
57
|
"draft"
|
|
57
58
|
]
|
|
58
59
|
});
|
|
59
|
-
const siteName = await c
|
|
60
|
+
const siteName = await getSiteName(c);
|
|
60
61
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
61
62
|
c: c,
|
|
62
63
|
title: "Posts",
|
|
@@ -69,7 +70,7 @@ postsRoutes.get("/", async (c)=>{
|
|
|
69
70
|
});
|
|
70
71
|
// New post form
|
|
71
72
|
postsRoutes.get("/new", async (c)=>{
|
|
72
|
-
const siteName = await c
|
|
73
|
+
const siteName = await getSiteName(c);
|
|
73
74
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
74
75
|
c: c,
|
|
75
76
|
title: "New Post",
|
|
@@ -160,7 +161,7 @@ postsRoutes.get("/:id", async (c)=>{
|
|
|
160
161
|
if (!id) return c.notFound();
|
|
161
162
|
const post = await c.var.services.posts.getById(id);
|
|
162
163
|
if (!post) return c.notFound();
|
|
163
|
-
const siteName = await c
|
|
164
|
+
const siteName = await getSiteName(c);
|
|
164
165
|
const pageTitle = post.title || "Post";
|
|
165
166
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
166
167
|
c: c,
|
|
@@ -178,7 +179,7 @@ postsRoutes.get("/:id/edit", async (c)=>{
|
|
|
178
179
|
if (!id) return c.notFound();
|
|
179
180
|
const post = await c.var.services.posts.getById(id);
|
|
180
181
|
if (!post) return c.notFound();
|
|
181
|
-
const siteName = await c
|
|
182
|
+
const siteName = await getSiteName(c);
|
|
182
183
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
183
184
|
c: c,
|
|
184
185
|
title: `Edit: ${post.title || "Post"}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/redirects.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/redirects.tsx"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAUjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,eAAe,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Dashboard Redirects Routes
|
|
4
5
|
*/ import { Hono } from "hono";
|
|
@@ -196,7 +197,7 @@ function NewRedirectContent() {
|
|
|
196
197
|
}
|
|
197
198
|
// List redirects
|
|
198
199
|
redirectsRoutes.get("/", async (c)=>{
|
|
199
|
-
const siteName = await c
|
|
200
|
+
const siteName = await getSiteName(c);
|
|
200
201
|
const redirects = await c.var.services.redirects.list();
|
|
201
202
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
202
203
|
c: c,
|
|
@@ -210,7 +211,7 @@ redirectsRoutes.get("/", async (c)=>{
|
|
|
210
211
|
});
|
|
211
212
|
// New redirect form
|
|
212
213
|
redirectsRoutes.get("/new", async (c)=>{
|
|
213
|
-
const siteName = await c
|
|
214
|
+
const siteName = await getSiteName(c);
|
|
214
215
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
215
216
|
c: c,
|
|
216
217
|
title: "New Redirect",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/settings.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/settings.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AASjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,cAAc,kDAAkB,CAAC"}
|
|
@@ -5,6 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-
|
|
|
5
5
|
import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
6
6
|
import { DashLayout } from "../../theme/layouts/index.js";
|
|
7
7
|
import { sse } from "../../lib/sse.js";
|
|
8
|
+
import { getSiteName, getSiteDescription, getSiteLanguage } from "../../lib/config.js";
|
|
8
9
|
export const settingsRoutes = new Hono();
|
|
9
10
|
function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
10
11
|
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
@@ -241,10 +242,9 @@ function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
|
241
242
|
}
|
|
242
243
|
// Settings page
|
|
243
244
|
settingsRoutes.get("/", async (c)=>{
|
|
244
|
-
const
|
|
245
|
-
const
|
|
246
|
-
const
|
|
247
|
-
const siteLanguage = all["SITE_LANGUAGE"] ?? "en";
|
|
245
|
+
const siteName = await getSiteName(c);
|
|
246
|
+
const siteDescription = await getSiteDescription(c);
|
|
247
|
+
const siteLanguage = await getSiteLanguage(c);
|
|
248
248
|
const saved = c.req.query("saved") !== undefined;
|
|
249
249
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
250
250
|
c: c,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/archive.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/archive.tsx"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAOjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAI3D,eAAO,MAAM,aAAa,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Archive Page Route
|
|
4
5
|
*
|
|
@@ -208,7 +209,7 @@ archiveRoutes.get("/", async (c)=>{
|
|
|
208
209
|
// Parse cursor
|
|
209
210
|
const cursorParam = c.req.query("cursor");
|
|
210
211
|
const cursor = cursorParam ? parseInt(cursorParam, 10) : undefined;
|
|
211
|
-
const siteName = await c
|
|
212
|
+
const siteName = await getSiteName(c);
|
|
212
213
|
// Fetch one extra to check for more
|
|
213
214
|
const posts = await c.var.services.posts.list({
|
|
214
215
|
type,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/collection.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/collection.tsx"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,gBAAgB,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Collection Page Route
|
|
4
5
|
*/ import { Hono } from "hono";
|
|
@@ -80,7 +81,7 @@ collectionRoutes.get("/:path", async (c)=>{
|
|
|
80
81
|
const collection = await c.var.services.collections.getByPath(path);
|
|
81
82
|
if (!collection) return c.notFound();
|
|
82
83
|
const posts = await c.var.services.collections.getPosts(collection.id);
|
|
83
|
-
const siteName = await c
|
|
84
|
+
const siteName = await getSiteName(c);
|
|
84
85
|
return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
|
|
85
86
|
title: `${collection.title} - ${siteName}`,
|
|
86
87
|
description: collection.description ?? undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/home.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/home.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,UAAU,kDAAkB,CAAC"}
|
|
@@ -6,6 +6,7 @@ import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
|
6
6
|
import { BaseLayout } from "../../theme/layouts/index.js";
|
|
7
7
|
import * as sqid from "../../lib/sqid.js";
|
|
8
8
|
import * as time from "../../lib/time.js";
|
|
9
|
+
import { getSiteName } from "../../lib/config.js";
|
|
9
10
|
export const homeRoutes = new Hono();
|
|
10
11
|
function HomeContent({ siteName, posts }) {
|
|
11
12
|
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
@@ -103,7 +104,7 @@ homeRoutes.get("/", async (c)=>{
|
|
|
103
104
|
if (!isComplete) {
|
|
104
105
|
return c.redirect("/setup");
|
|
105
106
|
}
|
|
106
|
-
const siteName = await c
|
|
107
|
+
const siteName = await getSiteName(c);
|
|
107
108
|
const posts = await c.var.services.posts.list({
|
|
108
109
|
visibility: [
|
|
109
110
|
"featured",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/page.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/page.tsx"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,UAAU,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Custom Page Route
|
|
4
5
|
*
|
|
@@ -58,7 +59,7 @@ pageRoutes.get("/:path", async (c)=>{
|
|
|
58
59
|
if (page.visibility === "draft") {
|
|
59
60
|
return c.notFound();
|
|
60
61
|
}
|
|
61
|
-
const siteName = await c
|
|
62
|
+
const siteName = await getSiteName(c);
|
|
62
63
|
return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
|
|
63
64
|
title: `${page.title} - ${siteName}`,
|
|
64
65
|
description: page.content?.slice(0, 160),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/post.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/post.tsx"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,UAAU,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Single Post Page Route
|
|
4
5
|
*/ import { Hono } from "hono";
|
|
@@ -77,7 +78,7 @@ postRoutes.get("/:id", async (c)=>{
|
|
|
77
78
|
if (post.visibility === "draft") {
|
|
78
79
|
return c.notFound();
|
|
79
80
|
}
|
|
80
|
-
const siteName = await c
|
|
81
|
+
const siteName = await getSiteName(c);
|
|
81
82
|
const title = post.title || siteName;
|
|
82
83
|
return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
|
|
83
84
|
title: title,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/search.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/search.tsx"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAOjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAI3D,eAAO,MAAM,YAAY,kDAAkB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { getSiteName } from "../../lib/config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Search Page Route
|
|
4
5
|
*/ import { Hono } from "hono";
|
|
@@ -140,7 +141,7 @@ searchRoutes.get("/", async (c)=>{
|
|
|
140
141
|
const query = c.req.query("q") || "";
|
|
141
142
|
const pageParam = c.req.query("page");
|
|
142
143
|
const page = pageParam ? Math.max(1, parseInt(pageParam, 10) || 1) : 1;
|
|
143
|
-
const siteName = await c
|
|
144
|
+
const siteName = await getSiteName(c);
|
|
144
145
|
// Only search if there's a query
|
|
145
146
|
let results = [];
|
|
146
147
|
let error = null;
|
package/dist/types.d.ts
CHANGED
|
@@ -14,6 +14,9 @@ export interface Bindings {
|
|
|
14
14
|
IMAGE_TRANSFORM_URL?: string;
|
|
15
15
|
DEMO_EMAIL?: string;
|
|
16
16
|
DEMO_PASSWORD?: string;
|
|
17
|
+
SITE_NAME?: string;
|
|
18
|
+
SITE_DESCRIPTION?: string;
|
|
19
|
+
SITE_LANGUAGE?: string;
|
|
17
20
|
}
|
|
18
21
|
export interface Post {
|
|
19
22
|
id: number;
|
|
@@ -141,41 +144,18 @@ export interface JantTheme {
|
|
|
141
144
|
/** CSS variable overrides */
|
|
142
145
|
cssVariables?: Record<string, string>;
|
|
143
146
|
}
|
|
144
|
-
/**
|
|
145
|
-
* Site configuration
|
|
146
|
-
*/
|
|
147
|
-
export interface SiteConfig {
|
|
148
|
-
/** Site name */
|
|
149
|
-
name?: string;
|
|
150
|
-
/** Site description */
|
|
151
|
-
description?: string;
|
|
152
|
-
/** Default language */
|
|
153
|
-
language?: string;
|
|
154
|
-
/** Site URL (usually set via env) */
|
|
155
|
-
url?: string;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Feature toggles
|
|
159
|
-
*/
|
|
160
|
-
export interface FeatureConfig {
|
|
161
|
-
/** Enable search (default: true) */
|
|
162
|
-
search?: boolean;
|
|
163
|
-
/** Enable RSS feed (default: true) */
|
|
164
|
-
rss?: boolean;
|
|
165
|
-
/** Enable sitemap (default: true) */
|
|
166
|
-
sitemap?: boolean;
|
|
167
|
-
/** Enable i18n (default: true) */
|
|
168
|
-
i18n?: boolean;
|
|
169
|
-
}
|
|
170
147
|
/**
|
|
171
148
|
* Main Jant configuration
|
|
149
|
+
*
|
|
150
|
+
* Configuration Philosophy:
|
|
151
|
+
* - Use environment variables for runtime config (API keys, feature flags, site settings)
|
|
152
|
+
* - Use code config (this object) for compile-time customization (theme components)
|
|
153
|
+
*
|
|
154
|
+
* Site-level settings (name, description, language) are configured via
|
|
155
|
+
* environment variables, not here. See lib/config.ts for details.
|
|
172
156
|
*/
|
|
173
157
|
export interface JantConfig {
|
|
174
|
-
/**
|
|
175
|
-
site?: SiteConfig;
|
|
176
|
-
/** Theme configuration */
|
|
158
|
+
/** Theme configuration (components, CSS overrides) */
|
|
177
159
|
theme?: JantTheme;
|
|
178
|
-
/** Feature toggles */
|
|
179
|
-
features?: FeatureConfig;
|
|
180
160
|
}
|
|
181
161
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/app.tsx
CHANGED
|
@@ -59,12 +59,15 @@ export type App = Hono<{ Bindings: Bindings; Variables: AppVariables }>;
|
|
|
59
59
|
* @param config - Optional configuration
|
|
60
60
|
* @returns Hono app instance
|
|
61
61
|
*
|
|
62
|
+
* Site settings (name, description, language) should be configured via
|
|
63
|
+
* environment variables (SITE_NAME, SITE_DESCRIPTION, SITE_LANGUAGE).
|
|
64
|
+
* They can also be set in the dashboard, which stores them in the database.
|
|
65
|
+
*
|
|
62
66
|
* @example
|
|
63
67
|
* ```typescript
|
|
64
68
|
* import { createApp } from "@jant/core";
|
|
65
69
|
*
|
|
66
70
|
* export default createApp({
|
|
67
|
-
* site: { name: "My Blog" },
|
|
68
71
|
* theme: { components: { PostCard: MyPostCard } },
|
|
69
72
|
* });
|
|
70
73
|
* ```
|
|
@@ -74,13 +77,20 @@ export function createApp(config: JantConfig = {}): App {
|
|
|
74
77
|
|
|
75
78
|
// Initialize services, auth, and config middleware
|
|
76
79
|
app.use("*", async (c, next) => {
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
// Use withSession() to enable D1 Read Replication
|
|
81
|
+
// Automatically routes read queries to the nearest replica for lower latency
|
|
82
|
+
// See: https://developers.cloudflare.com/d1/best-practices/read-replication/
|
|
83
|
+
const session = c.env.DB.withSession();
|
|
84
|
+
|
|
85
|
+
// Note: Drizzle ORM doesn't officially support D1DatabaseSession yet (issue #2226)
|
|
86
|
+
// but it works at runtime. We use type assertion as a temporary workaround.
|
|
87
|
+
const db = createDatabase(session as unknown as D1Database);
|
|
88
|
+
const services = createServices(db, session as unknown as D1Database);
|
|
79
89
|
c.set("services", services);
|
|
80
90
|
c.set("config", config);
|
|
81
91
|
|
|
82
92
|
if (c.env.AUTH_SECRET) {
|
|
83
|
-
const auth = createAuth(
|
|
93
|
+
const auth = createAuth(session as unknown as D1Database, {
|
|
84
94
|
secret: c.env.AUTH_SECRET,
|
|
85
95
|
baseURL: c.env.SITE_URL,
|
|
86
96
|
});
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Configuration Helpers
|
|
3
|
+
*
|
|
4
|
+
* Configuration priority: Environment Variables > Database > Default Values
|
|
5
|
+
*
|
|
6
|
+
* This follows the 12-factor app methodology where configuration is stored
|
|
7
|
+
* in environment variables, while allowing runtime overrides via database.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Context } from "hono";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get site name with fallback chain: ENV > DB > Default
|
|
14
|
+
*
|
|
15
|
+
* @param c - Hono context
|
|
16
|
+
* @returns Site name
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const siteName = await getSiteName(c);
|
|
21
|
+
* // Returns: c.env.SITE_NAME ?? (DB: SITE_NAME) ?? "Jant"
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export async function getSiteName(c: Context): Promise<string> {
|
|
25
|
+
// 1. Check environment variable
|
|
26
|
+
if (c.env.SITE_NAME) {
|
|
27
|
+
return c.env.SITE_NAME;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. Check database setting
|
|
31
|
+
const dbValue = await c.var.services.settings.get("SITE_NAME");
|
|
32
|
+
if (dbValue) {
|
|
33
|
+
return dbValue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 3. Default value
|
|
37
|
+
return "Jant";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get site description with fallback chain: ENV > DB > Default
|
|
42
|
+
*
|
|
43
|
+
* @param c - Hono context
|
|
44
|
+
* @returns Site description
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const description = await getSiteDescription(c);
|
|
49
|
+
* // Returns: c.env.SITE_DESCRIPTION ?? (DB: SITE_DESCRIPTION) ?? "A microblog powered by Jant"
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export async function getSiteDescription(c: Context): Promise<string> {
|
|
53
|
+
// 1. Check environment variable
|
|
54
|
+
if (c.env.SITE_DESCRIPTION) {
|
|
55
|
+
return c.env.SITE_DESCRIPTION;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 2. Check database setting
|
|
59
|
+
const dbValue = await c.var.services.settings.get("SITE_DESCRIPTION");
|
|
60
|
+
if (dbValue) {
|
|
61
|
+
return dbValue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 3. Default value
|
|
65
|
+
return "A microblog powered by Jant";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get site language with fallback chain: ENV > DB > Default
|
|
70
|
+
*
|
|
71
|
+
* @param c - Hono context
|
|
72
|
+
* @returns Site language code
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const lang = await getSiteLanguage(c);
|
|
77
|
+
* // Returns: c.env.SITE_LANGUAGE ?? (DB: SITE_LANGUAGE) ?? "en"
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export async function getSiteLanguage(c: Context): Promise<string> {
|
|
81
|
+
// 1. Check environment variable
|
|
82
|
+
if (c.env.SITE_LANGUAGE) {
|
|
83
|
+
return c.env.SITE_LANGUAGE;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 2. Check database setting
|
|
87
|
+
const dbValue = await c.var.services.settings.get("SITE_LANGUAGE");
|
|
88
|
+
if (dbValue) {
|
|
89
|
+
return dbValue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 3. Default value
|
|
93
|
+
return "en";
|
|
94
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Dashboard Collections Routes
|
|
3
4
|
*/
|
|
@@ -363,7 +364,7 @@ function EditCollectionContent({ collection }: { collection: Collection }) {
|
|
|
363
364
|
|
|
364
365
|
// List collections
|
|
365
366
|
collectionsRoutes.get("/", async (c) => {
|
|
366
|
-
const siteName =
|
|
367
|
+
const siteName = await getSiteName(c);
|
|
367
368
|
const collections = await c.var.services.collections.list();
|
|
368
369
|
|
|
369
370
|
return c.html(
|
|
@@ -380,7 +381,7 @@ collectionsRoutes.get("/", async (c) => {
|
|
|
380
381
|
|
|
381
382
|
// New collection form
|
|
382
383
|
collectionsRoutes.get("/new", async (c) => {
|
|
383
|
-
const siteName =
|
|
384
|
+
const siteName = await getSiteName(c);
|
|
384
385
|
|
|
385
386
|
return c.html(
|
|
386
387
|
<DashLayout
|
|
@@ -422,7 +423,7 @@ collectionsRoutes.get("/:id", async (c) => {
|
|
|
422
423
|
if (!collection) return c.notFound();
|
|
423
424
|
|
|
424
425
|
const posts = await c.var.services.collections.getPosts(id);
|
|
425
|
-
const siteName =
|
|
426
|
+
const siteName = await getSiteName(c);
|
|
426
427
|
|
|
427
428
|
return c.html(
|
|
428
429
|
<DashLayout
|
|
@@ -444,7 +445,7 @@ collectionsRoutes.get("/:id/edit", async (c) => {
|
|
|
444
445
|
const collection = await c.var.services.collections.getById(id);
|
|
445
446
|
if (!collection) return c.notFound();
|
|
446
447
|
|
|
447
|
-
const siteName =
|
|
448
|
+
const siteName = await getSiteName(c);
|
|
448
449
|
|
|
449
450
|
return c.html(
|
|
450
451
|
<DashLayout
|
|
@@ -9,6 +9,7 @@ import { Trans, useLingui } from "@lingui/react/macro";
|
|
|
9
9
|
import type { Bindings } from "../../types.js";
|
|
10
10
|
import type { AppVariables } from "../../app.js";
|
|
11
11
|
import { DashLayout } from "../../theme/layouts/index.js";
|
|
12
|
+
import { getSiteName } from "../../lib/config.js";
|
|
12
13
|
|
|
13
14
|
type Env = { Bindings: Bindings; Variables: AppVariables };
|
|
14
15
|
|
|
@@ -86,7 +87,7 @@ function DashboardContent({
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
dashIndexRoutes.get("/", async (c) => {
|
|
89
|
-
const siteName =
|
|
90
|
+
const siteName = await getSiteName(c);
|
|
90
91
|
|
|
91
92
|
// Get some stats
|
|
92
93
|
const allPosts = await c.var.services.posts.list({ limit: 1000 });
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Dashboard Media Routes
|
|
3
4
|
*
|
|
@@ -544,7 +545,7 @@ function ViewMediaContent({
|
|
|
544
545
|
// List media
|
|
545
546
|
mediaRoutes.get("/", async (c) => {
|
|
546
547
|
const mediaList = await c.var.services.media.list(100);
|
|
547
|
-
const siteName =
|
|
548
|
+
const siteName = await getSiteName(c);
|
|
548
549
|
const r2PublicUrl = c.env.R2_PUBLIC_URL;
|
|
549
550
|
const imageTransformUrl = c.env.IMAGE_TRANSFORM_URL;
|
|
550
551
|
|
|
@@ -570,7 +571,7 @@ mediaRoutes.get("/:id", async (c) => {
|
|
|
570
571
|
const media = await c.var.services.media.getById(id);
|
|
571
572
|
if (!media) return c.notFound();
|
|
572
573
|
|
|
573
|
-
const siteName =
|
|
574
|
+
const siteName = await getSiteName(c);
|
|
574
575
|
const r2PublicUrl = c.env.R2_PUBLIC_URL;
|
|
575
576
|
const imageTransformUrl = c.env.IMAGE_TRANSFORM_URL;
|
|
576
577
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Dashboard Pages Routes
|
|
3
4
|
*
|
|
@@ -189,7 +190,7 @@ pagesRoutes.get("/", async (c) => {
|
|
|
189
190
|
visibility: ["unlisted", "draft"],
|
|
190
191
|
limit: 100,
|
|
191
192
|
});
|
|
192
|
-
const siteName =
|
|
193
|
+
const siteName = await getSiteName(c);
|
|
193
194
|
|
|
194
195
|
return c.html(
|
|
195
196
|
<DashLayout
|
|
@@ -205,7 +206,7 @@ pagesRoutes.get("/", async (c) => {
|
|
|
205
206
|
|
|
206
207
|
// New page form
|
|
207
208
|
pagesRoutes.get("/new", async (c) => {
|
|
208
|
-
const siteName =
|
|
209
|
+
const siteName = await getSiteName(c);
|
|
209
210
|
|
|
210
211
|
return c.html(
|
|
211
212
|
<DashLayout
|
|
@@ -249,7 +250,7 @@ pagesRoutes.get("/:id", async (c) => {
|
|
|
249
250
|
const page = await c.var.services.posts.getById(id);
|
|
250
251
|
if (!page || page.type !== "page") return c.notFound();
|
|
251
252
|
|
|
252
|
-
const siteName =
|
|
253
|
+
const siteName = await getSiteName(c);
|
|
253
254
|
|
|
254
255
|
return c.html(
|
|
255
256
|
<DashLayout
|
|
@@ -271,7 +272,7 @@ pagesRoutes.get("/:id/edit", async (c) => {
|
|
|
271
272
|
const page = await c.var.services.posts.getById(id);
|
|
272
273
|
if (!page || page.type !== "page") return c.notFound();
|
|
273
274
|
|
|
274
|
-
const siteName =
|
|
275
|
+
const siteName = await getSiteName(c);
|
|
275
276
|
|
|
276
277
|
return c.html(
|
|
277
278
|
<DashLayout
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Dashboard Posts Routes
|
|
3
4
|
*/
|
|
@@ -54,7 +55,7 @@ postsRoutes.get("/", async (c) => {
|
|
|
54
55
|
const posts = await c.var.services.posts.list({
|
|
55
56
|
visibility: ["featured", "quiet", "unlisted", "draft"],
|
|
56
57
|
});
|
|
57
|
-
const siteName =
|
|
58
|
+
const siteName = await getSiteName(c);
|
|
58
59
|
|
|
59
60
|
return c.html(
|
|
60
61
|
<DashLayout
|
|
@@ -70,7 +71,7 @@ postsRoutes.get("/", async (c) => {
|
|
|
70
71
|
|
|
71
72
|
// New post form
|
|
72
73
|
postsRoutes.get("/new", async (c) => {
|
|
73
|
-
const siteName =
|
|
74
|
+
const siteName = await getSiteName(c);
|
|
74
75
|
|
|
75
76
|
return c.html(
|
|
76
77
|
<DashLayout
|
|
@@ -166,7 +167,7 @@ postsRoutes.get("/:id", async (c) => {
|
|
|
166
167
|
const post = await c.var.services.posts.getById(id);
|
|
167
168
|
if (!post) return c.notFound();
|
|
168
169
|
|
|
169
|
-
const siteName =
|
|
170
|
+
const siteName = await getSiteName(c);
|
|
170
171
|
const pageTitle = post.title || "Post";
|
|
171
172
|
|
|
172
173
|
return c.html(
|
|
@@ -189,7 +190,7 @@ postsRoutes.get("/:id/edit", async (c) => {
|
|
|
189
190
|
const post = await c.var.services.posts.getById(id);
|
|
190
191
|
if (!post) return c.notFound();
|
|
191
192
|
|
|
192
|
-
const siteName =
|
|
193
|
+
const siteName = await getSiteName(c);
|
|
193
194
|
|
|
194
195
|
return c.html(
|
|
195
196
|
<DashLayout
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Dashboard Redirects Routes
|
|
3
4
|
*/
|
|
@@ -176,7 +177,7 @@ function NewRedirectContent() {
|
|
|
176
177
|
|
|
177
178
|
// List redirects
|
|
178
179
|
redirectsRoutes.get("/", async (c) => {
|
|
179
|
-
const siteName =
|
|
180
|
+
const siteName = await getSiteName(c);
|
|
180
181
|
const redirects = await c.var.services.redirects.list();
|
|
181
182
|
|
|
182
183
|
return c.html(
|
|
@@ -193,7 +194,7 @@ redirectsRoutes.get("/", async (c) => {
|
|
|
193
194
|
|
|
194
195
|
// New redirect form
|
|
195
196
|
redirectsRoutes.get("/new", async (c) => {
|
|
196
|
-
const siteName =
|
|
197
|
+
const siteName = await getSiteName(c);
|
|
197
198
|
|
|
198
199
|
return c.html(
|
|
199
200
|
<DashLayout
|
|
@@ -8,6 +8,11 @@ import type { Bindings } from "../../types.js";
|
|
|
8
8
|
import type { AppVariables } from "../../app.js";
|
|
9
9
|
import { DashLayout } from "../../theme/layouts/index.js";
|
|
10
10
|
import { sse } from "../../lib/sse.js";
|
|
11
|
+
import {
|
|
12
|
+
getSiteName,
|
|
13
|
+
getSiteDescription,
|
|
14
|
+
getSiteLanguage,
|
|
15
|
+
} from "../../lib/config.js";
|
|
11
16
|
|
|
12
17
|
type Env = { Bindings: Bindings; Variables: AppVariables };
|
|
13
18
|
|
|
@@ -207,10 +212,9 @@ function SettingsContent({
|
|
|
207
212
|
|
|
208
213
|
// Settings page
|
|
209
214
|
settingsRoutes.get("/", async (c) => {
|
|
210
|
-
const
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
const siteLanguage = all["SITE_LANGUAGE"] ?? "en";
|
|
215
|
+
const siteName = await getSiteName(c);
|
|
216
|
+
const siteDescription = await getSiteDescription(c);
|
|
217
|
+
const siteLanguage = await getSiteLanguage(c);
|
|
214
218
|
const saved = c.req.query("saved") !== undefined;
|
|
215
219
|
|
|
216
220
|
return c.html(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Archive Page Route
|
|
3
4
|
*
|
|
@@ -225,7 +226,7 @@ archiveRoutes.get("/", async (c) => {
|
|
|
225
226
|
const cursorParam = c.req.query("cursor");
|
|
226
227
|
const cursor = cursorParam ? parseInt(cursorParam, 10) : undefined;
|
|
227
228
|
|
|
228
|
-
const siteName =
|
|
229
|
+
const siteName = await getSiteName(c);
|
|
229
230
|
|
|
230
231
|
// Fetch one extra to check for more
|
|
231
232
|
const posts = await c.var.services.posts.list({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Collection Page Route
|
|
3
4
|
*/
|
|
@@ -89,7 +90,7 @@ collectionRoutes.get("/:path", async (c) => {
|
|
|
89
90
|
if (!collection) return c.notFound();
|
|
90
91
|
|
|
91
92
|
const posts = await c.var.services.collections.getPosts(collection.id);
|
|
92
|
-
const siteName =
|
|
93
|
+
const siteName = await getSiteName(c);
|
|
93
94
|
|
|
94
95
|
return c.html(
|
|
95
96
|
<BaseLayout
|
|
@@ -9,6 +9,7 @@ import type { AppVariables } from "../../app.js";
|
|
|
9
9
|
import { BaseLayout } from "../../theme/layouts/index.js";
|
|
10
10
|
import * as sqid from "../../lib/sqid.js";
|
|
11
11
|
import * as time from "../../lib/time.js";
|
|
12
|
+
import { getSiteName } from "../../lib/config.js";
|
|
12
13
|
|
|
13
14
|
type Env = { Bindings: Bindings; Variables: AppVariables };
|
|
14
15
|
|
|
@@ -106,7 +107,7 @@ homeRoutes.get("/", async (c) => {
|
|
|
106
107
|
return c.redirect("/setup");
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
const siteName =
|
|
110
|
+
const siteName = await getSiteName(c);
|
|
110
111
|
|
|
111
112
|
const posts = await c.var.services.posts.list({
|
|
112
113
|
visibility: ["featured", "quiet"],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Custom Page Route
|
|
3
4
|
*
|
|
@@ -60,7 +61,7 @@ pageRoutes.get("/:path", async (c) => {
|
|
|
60
61
|
return c.notFound();
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
const siteName =
|
|
64
|
+
const siteName = await getSiteName(c);
|
|
64
65
|
|
|
65
66
|
return c.html(
|
|
66
67
|
<BaseLayout
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Single Post Page Route
|
|
3
4
|
*/
|
|
@@ -81,7 +82,7 @@ postRoutes.get("/:id", async (c) => {
|
|
|
81
82
|
return c.notFound();
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
const siteName =
|
|
85
|
+
const siteName = await getSiteName(c);
|
|
85
86
|
const title = post.title || siteName;
|
|
86
87
|
|
|
87
88
|
return c.html(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSiteName } from "../../lib/config.js";
|
|
1
2
|
/**
|
|
2
3
|
* Search Page Route
|
|
3
4
|
*/
|
|
@@ -155,7 +156,7 @@ searchRoutes.get("/", async (c) => {
|
|
|
155
156
|
const pageParam = c.req.query("page");
|
|
156
157
|
const page = pageParam ? Math.max(1, parseInt(pageParam, 10) || 1) : 1;
|
|
157
158
|
|
|
158
|
-
const siteName =
|
|
159
|
+
const siteName = await getSiteName(c);
|
|
159
160
|
|
|
160
161
|
// Only search if there's a query
|
|
161
162
|
let results: Awaited<ReturnType<typeof c.var.services.search.search>> = [];
|
package/src/types.ts
CHANGED
|
@@ -37,6 +37,10 @@ export interface Bindings {
|
|
|
37
37
|
IMAGE_TRANSFORM_URL?: string;
|
|
38
38
|
DEMO_EMAIL?: string;
|
|
39
39
|
DEMO_PASSWORD?: string;
|
|
40
|
+
// Site configuration (optional - can be overridden in DB)
|
|
41
|
+
SITE_NAME?: string;
|
|
42
|
+
SITE_DESCRIPTION?: string;
|
|
43
|
+
SITE_LANGUAGE?: string;
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
// =============================================================================
|
|
@@ -193,42 +197,17 @@ export interface JantTheme {
|
|
|
193
197
|
cssVariables?: Record<string, string>;
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
/**
|
|
197
|
-
* Site configuration
|
|
198
|
-
*/
|
|
199
|
-
export interface SiteConfig {
|
|
200
|
-
/** Site name */
|
|
201
|
-
name?: string;
|
|
202
|
-
/** Site description */
|
|
203
|
-
description?: string;
|
|
204
|
-
/** Default language */
|
|
205
|
-
language?: string;
|
|
206
|
-
/** Site URL (usually set via env) */
|
|
207
|
-
url?: string;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Feature toggles
|
|
212
|
-
*/
|
|
213
|
-
export interface FeatureConfig {
|
|
214
|
-
/** Enable search (default: true) */
|
|
215
|
-
search?: boolean;
|
|
216
|
-
/** Enable RSS feed (default: true) */
|
|
217
|
-
rss?: boolean;
|
|
218
|
-
/** Enable sitemap (default: true) */
|
|
219
|
-
sitemap?: boolean;
|
|
220
|
-
/** Enable i18n (default: true) */
|
|
221
|
-
i18n?: boolean;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
200
|
/**
|
|
225
201
|
* Main Jant configuration
|
|
202
|
+
*
|
|
203
|
+
* Configuration Philosophy:
|
|
204
|
+
* - Use environment variables for runtime config (API keys, feature flags, site settings)
|
|
205
|
+
* - Use code config (this object) for compile-time customization (theme components)
|
|
206
|
+
*
|
|
207
|
+
* Site-level settings (name, description, language) are configured via
|
|
208
|
+
* environment variables, not here. See lib/config.ts for details.
|
|
226
209
|
*/
|
|
227
210
|
export interface JantConfig {
|
|
228
|
-
/**
|
|
229
|
-
site?: SiteConfig;
|
|
230
|
-
/** Theme configuration */
|
|
211
|
+
/** Theme configuration (components, CSS overrides) */
|
|
231
212
|
theme?: JantTheme;
|
|
232
|
-
/** Feature toggles */
|
|
233
|
-
features?: FeatureConfig;
|
|
234
213
|
}
|