@jant/core 0.3.27 → 0.3.28
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/client/client.css +1 -0
- package/dist/client/client.js +31561 -0
- package/dist/index.js +15209 -15
- package/package.json +21 -15
- package/src/__tests__/helpers/app.ts +19 -3
- package/src/__tests__/helpers/db.ts +44 -0
- package/src/__tests__/helpers/lingui-core-macro-mock.ts +33 -0
- package/src/app.tsx +111 -174
- package/src/client.ts +13 -0
- package/src/db/migrations/0007_post_collections_m2m.sql +94 -0
- package/src/db/migrations/0008_add_collection_dividers.sql +8 -0
- package/src/db/migrations/0009_drop_collection_show_divider.sql +2 -0
- package/src/db/migrations/0010_add_performance_indexes.sql +16 -0
- package/src/db/schema.ts +24 -4
- package/src/i18n/locales/en.po +810 -385
- package/src/i18n/locales/en.ts +1 -1
- package/src/i18n/locales/zh-Hans.po +733 -522
- package/src/i18n/locales/zh-Hans.ts +1 -1
- package/src/i18n/locales/zh-Hant.po +733 -522
- package/src/i18n/locales/zh-Hant.ts +1 -1
- package/src/i18n/middleware.ts +7 -11
- package/src/index.ts +1 -1
- package/src/lib/__tests__/icons.test.ts +178 -0
- package/src/lib/__tests__/resolve-config.test.ts +184 -0
- package/src/lib/__tests__/schemas.test.ts +12 -6
- package/src/lib/__tests__/theme.test.ts +62 -0
- package/src/lib/__tests__/timezones.test.ts +1 -1
- package/src/lib/__tests__/url.test.ts +12 -0
- package/src/lib/__tests__/view.test.ts +1 -5
- package/src/lib/avatar-upload.ts +18 -10
- package/src/lib/collection-form-bridge.ts +52 -0
- package/src/lib/collections-reorder.ts +28 -0
- package/src/lib/compose-bridge.ts +251 -0
- package/src/lib/errors.ts +116 -0
- package/src/lib/excerpt.ts +1 -1
- package/src/lib/favicon.ts +3 -5
- package/src/lib/html.ts +22 -0
- package/src/lib/icon-catalog.ts +181 -0
- package/src/lib/icons.ts +202 -0
- package/src/lib/navigation.ts +18 -33
- package/src/lib/pagination.ts +3 -2
- package/src/lib/post-form-bridge.ts +136 -0
- package/src/lib/render.tsx +11 -4
- package/src/lib/resolve-config.ts +157 -0
- package/src/lib/schemas.ts +76 -12
- package/src/lib/settings-bridge.ts +139 -0
- package/src/lib/storage.ts +37 -16
- package/src/lib/theme.ts +5 -7
- package/src/lib/timeline.ts +4 -8
- package/src/lib/toast.ts +134 -0
- package/src/lib/upload.ts +71 -0
- package/src/lib/url.ts +9 -1
- package/src/lib/version.ts +16 -0
- package/src/lib/view.ts +9 -10
- package/src/middleware/__tests__/auth.test.ts +6 -28
- package/src/middleware/__tests__/onboarding.test.ts +1 -1
- package/src/middleware/auth.ts +6 -12
- package/src/middleware/config.ts +51 -0
- package/src/middleware/error-handler.ts +56 -0
- package/src/middleware/onboarding.ts +1 -1
- package/src/preset.css +6 -0
- package/src/routes/__tests__/compose.test.ts +104 -17
- package/src/routes/api/__tests__/collections.test.ts +93 -2
- package/src/routes/api/__tests__/posts.test.ts +2 -1
- package/src/routes/api/__tests__/settings.test.ts +1 -1
- package/src/routes/api/collections.ts +64 -68
- package/src/routes/api/nav-items.ts +21 -59
- package/src/routes/api/pages.ts +18 -46
- package/src/routes/api/posts.ts +64 -86
- package/src/routes/api/search.ts +6 -4
- package/src/routes/api/settings.ts +8 -24
- package/src/routes/api/upload.ts +55 -53
- package/src/routes/auth/__tests__/setup.test.ts +118 -0
- package/src/routes/auth/reset.tsx +17 -66
- package/src/routes/auth/setup.tsx +67 -11
- package/src/routes/auth/signin.tsx +44 -8
- package/src/routes/compose.tsx +194 -0
- package/src/routes/dash/__tests__/font-theme.test.ts +110 -0
- package/src/routes/dash/__tests__/pages.test.ts +2 -2
- package/src/routes/dash/__tests__/settings-avatar.test.ts +23 -12
- package/src/routes/dash/appearance.tsx +173 -0
- package/src/routes/dash/collections.tsx +80 -14
- package/src/routes/dash/index.tsx +12 -14
- package/src/routes/dash/media.tsx +46 -49
- package/src/routes/dash/pages.tsx +85 -37
- package/src/routes/dash/posts.tsx +60 -23
- package/src/routes/dash/redirects.tsx +43 -33
- package/src/routes/dash/settings.tsx +234 -214
- package/src/routes/feed/__tests__/rss.test.ts +7 -3
- package/src/routes/feed/rss.ts +11 -16
- package/src/routes/feed/sitemap.ts +15 -9
- package/src/routes/pages/__tests__/collections.test.ts +9 -8
- package/src/routes/pages/archive.tsx +2 -2
- package/src/routes/pages/collection.tsx +76 -9
- package/src/routes/pages/collections.tsx +3 -1
- package/src/routes/pages/featured.tsx +2 -2
- package/src/routes/pages/home.tsx +3 -3
- package/src/routes/pages/latest.tsx +2 -2
- package/src/routes/pages/page.tsx +2 -2
- package/src/routes/pages/post.tsx +2 -2
- package/src/routes/pages/search.tsx +2 -2
- package/src/services/__tests__/collection.test.ts +324 -34
- package/src/services/__tests__/media.test.ts +1 -1
- package/src/services/__tests__/page.test.ts +116 -1
- package/src/services/auth.ts +88 -0
- package/src/services/collection.ts +169 -30
- package/src/services/index.ts +8 -3
- package/src/services/media.ts +39 -12
- package/src/services/navigation.ts +17 -5
- package/src/services/page.ts +24 -4
- package/src/services/post.ts +87 -19
- package/src/services/search.ts +0 -1
- package/src/services/settings.ts +21 -13
- package/src/style.css +3 -0
- package/src/styles/components.css +42 -1
- package/src/styles/tokens.css +4 -0
- package/src/styles/ui.css +902 -73
- package/src/types/app-context.ts +25 -0
- package/src/types/bindings.ts +1 -0
- package/src/types/config.ts +60 -23
- package/src/types/entities.ts +12 -2
- package/src/types/lingui-react-macro.d.ts +3 -3
- package/src/types/operations.ts +2 -4
- package/src/types/views.ts +1 -3
- package/src/ui/__tests__/font-themes.test.ts +27 -8
- package/src/ui/color-themes.ts +1 -1
- package/src/ui/components/__tests__/jant-collection-form.test.ts +153 -0
- package/src/ui/components/__tests__/jant-compose-dialog.test.ts +512 -0
- package/src/ui/components/__tests__/jant-compose-editor.test.ts +272 -0
- package/src/ui/components/__tests__/jant-post-form.test.ts +172 -0
- package/src/ui/components/__tests__/jant-settings-avatar.test.ts +235 -0
- package/src/ui/components/__tests__/jant-settings-general.test.ts +319 -0
- package/src/ui/components/collection-types.ts +45 -0
- package/src/ui/components/compose-types.ts +75 -0
- package/src/ui/components/jant-collection-form.ts +512 -0
- package/src/ui/components/jant-compose-dialog.ts +494 -0
- package/src/ui/components/jant-compose-editor.ts +799 -0
- package/src/ui/components/jant-post-form.ts +290 -0
- package/src/ui/components/jant-settings-avatar.ts +231 -0
- package/src/ui/components/jant-settings-general.ts +436 -0
- package/src/ui/components/post-form-template.ts +260 -0
- package/src/ui/components/post-form-types.ts +87 -0
- package/src/ui/components/settings-types.ts +62 -0
- package/src/ui/compose/ComposeDialog.tsx +141 -385
- package/src/ui/compose/ComposePrompt.tsx +3 -3
- package/src/ui/dash/PostList.tsx +55 -61
- package/src/ui/dash/appearance/AdvancedContent.tsx +80 -0
- package/src/ui/dash/appearance/AppearanceNav.tsx +56 -0
- package/src/ui/dash/appearance/ColorThemeContent.tsx +129 -0
- package/src/ui/dash/appearance/FontThemeContent.tsx +98 -0
- package/src/ui/dash/collections/CollectionForm.tsx +130 -117
- package/src/ui/dash/collections/CollectionsListContent.tsx +102 -41
- package/src/ui/dash/collections/IconPickerGrid.tsx +50 -0
- package/src/ui/dash/collections/ViewCollectionContent.tsx +14 -3
- package/src/ui/dash/index.ts +1 -1
- package/src/ui/dash/posts/PostForm.tsx +248 -0
- package/src/ui/dash/settings/AccountContent.tsx +69 -80
- package/src/ui/dash/settings/GeneralContent.tsx +159 -478
- package/src/ui/dash/settings/SettingsNav.tsx +4 -4
- package/src/ui/font-themes.ts +115 -32
- package/src/ui/layouts/BaseLayout.tsx +49 -19
- package/src/ui/layouts/DashLayout.tsx +14 -9
- package/src/ui/layouts/SiteLayout.tsx +38 -23
- package/src/ui/pages/CollectionPage.tsx +12 -2
- package/src/ui/pages/CollectionsPage.tsx +27 -27
- package/src/ui/pages/HomePage.tsx +15 -6
- package/src/ui/pages/SearchPage.tsx +1 -2
- package/src/ui/shared/CollectionsSidebar.tsx +59 -0
- package/src/ui/shared/Pagination.tsx +2 -2
- package/dist/app.js +0 -267
- package/dist/auth.js +0 -39
- package/dist/client.js +0 -13
- package/dist/db/index.js +0 -10
- package/dist/db/schema.js +0 -224
- package/dist/i18n/Trans.js +0 -24
- package/dist/i18n/context.js +0 -58
- package/dist/i18n/detect.js +0 -26
- package/dist/i18n/i18n.js +0 -49
- package/dist/i18n/index.js +0 -44
- package/dist/i18n/locales/en.js +0 -1
- package/dist/i18n/locales/zh-Hans.js +0 -1
- package/dist/i18n/locales/zh-Hant.js +0 -1
- package/dist/i18n/locales.js +0 -13
- package/dist/i18n/middleware.js +0 -30
- package/dist/lib/avatar-upload.js +0 -134
- package/dist/lib/config.js +0 -143
- package/dist/lib/constants.js +0 -50
- package/dist/lib/excerpt.js +0 -76
- package/dist/lib/favicon.js +0 -102
- package/dist/lib/feed.js +0 -123
- package/dist/lib/image-processor.js +0 -187
- package/dist/lib/image.js +0 -97
- package/dist/lib/index.js +0 -7
- package/dist/lib/markdown.js +0 -83
- package/dist/lib/media-helpers.js +0 -49
- package/dist/lib/media-upload.js +0 -104
- package/dist/lib/nav-reorder.js +0 -27
- package/dist/lib/navigation.js +0 -79
- package/dist/lib/pagination.js +0 -44
- package/dist/lib/render.js +0 -53
- package/dist/lib/schemas.js +0 -174
- package/dist/lib/sqid.js +0 -72
- package/dist/lib/sse.js +0 -218
- package/dist/lib/storage.js +0 -164
- package/dist/lib/theme.js +0 -65
- package/dist/lib/time.js +0 -159
- package/dist/lib/timeline.js +0 -95
- package/dist/lib/timezones.js +0 -388
- package/dist/lib/url.js +0 -89
- package/dist/lib/view.js +0 -217
- package/dist/middleware/auth.js +0 -52
- package/dist/middleware/onboarding.js +0 -41
- package/dist/routes/api/collections.js +0 -124
- package/dist/routes/api/nav-items.js +0 -104
- package/dist/routes/api/pages.js +0 -91
- package/dist/routes/api/posts.js +0 -218
- package/dist/routes/api/search.js +0 -48
- package/dist/routes/api/settings.js +0 -68
- package/dist/routes/api/upload.js +0 -246
- package/dist/routes/auth/reset.js +0 -221
- package/dist/routes/auth/setup.js +0 -194
- package/dist/routes/auth/signin.js +0 -176
- package/dist/routes/compose.js +0 -48
- package/dist/routes/dash/collections.js +0 -115
- package/dist/routes/dash/index.js +0 -118
- package/dist/routes/dash/media.js +0 -106
- package/dist/routes/dash/pages.js +0 -294
- package/dist/routes/dash/posts.js +0 -244
- package/dist/routes/dash/redirects.js +0 -257
- package/dist/routes/dash/settings.js +0 -379
- package/dist/routes/feed/rss.js +0 -62
- package/dist/routes/feed/sitemap.js +0 -49
- package/dist/routes/pages/archive.js +0 -62
- package/dist/routes/pages/collection.js +0 -34
- package/dist/routes/pages/collections.js +0 -28
- package/dist/routes/pages/featured.js +0 -36
- package/dist/routes/pages/home.js +0 -64
- package/dist/routes/pages/latest.js +0 -45
- package/dist/routes/pages/page.js +0 -68
- package/dist/routes/pages/post.js +0 -44
- package/dist/routes/pages/search.js +0 -54
- package/dist/services/collection.js +0 -109
- package/dist/services/index.js +0 -24
- package/dist/services/media.js +0 -117
- package/dist/services/navigation.js +0 -91
- package/dist/services/page.js +0 -84
- package/dist/services/post.js +0 -229
- package/dist/services/redirect.js +0 -48
- package/dist/services/search.js +0 -67
- package/dist/services/settings.js +0 -68
- package/dist/types/bindings.js +0 -3
- package/dist/types/config.js +0 -147
- package/dist/types/constants.js +0 -27
- package/dist/types/entities.js +0 -3
- package/dist/types/lingui-react-macro.d.js +0 -9
- package/dist/types/operations.js +0 -3
- package/dist/types/props.js +0 -3
- package/dist/types/sortablejs.d.js +0 -5
- package/dist/types/views.js +0 -5
- package/dist/types.js +0 -11
- package/dist/ui/color-themes.js +0 -268
- package/dist/ui/compose/ComposeDialog.js +0 -467
- package/dist/ui/compose/ComposePrompt.js +0 -55
- package/dist/ui/dash/ActionButtons.js +0 -46
- package/dist/ui/dash/CrudPageHeader.js +0 -22
- package/dist/ui/dash/DangerZone.js +0 -36
- package/dist/ui/dash/FormatBadge.js +0 -27
- package/dist/ui/dash/ListItemRow.js +0 -21
- package/dist/ui/dash/PageForm.js +0 -195
- package/dist/ui/dash/PostForm.js +0 -395
- package/dist/ui/dash/PostList.js +0 -83
- package/dist/ui/dash/StatusBadge.js +0 -46
- package/dist/ui/dash/collections/CollectionForm.js +0 -152
- package/dist/ui/dash/collections/CollectionsListContent.js +0 -68
- package/dist/ui/dash/collections/ViewCollectionContent.js +0 -96
- package/dist/ui/dash/index.js +0 -10
- package/dist/ui/dash/media/MediaListContent.js +0 -166
- package/dist/ui/dash/media/ViewMediaContent.js +0 -212
- package/dist/ui/dash/pages/LinkFormContent.js +0 -130
- package/dist/ui/dash/pages/UnifiedPagesContent.js +0 -193
- package/dist/ui/dash/settings/AccountContent.js +0 -209
- package/dist/ui/dash/settings/AppearanceContent.js +0 -259
- package/dist/ui/dash/settings/GeneralContent.js +0 -536
- package/dist/ui/dash/settings/SettingsNav.js +0 -41
- package/dist/ui/feed/LinkCard.js +0 -72
- package/dist/ui/feed/NoteCard.js +0 -58
- package/dist/ui/feed/QuoteCard.js +0 -63
- package/dist/ui/feed/ThreadPreview.js +0 -48
- package/dist/ui/feed/TimelineFeed.js +0 -41
- package/dist/ui/feed/TimelineItem.js +0 -27
- package/dist/ui/font-themes.js +0 -36
- package/dist/ui/layouts/BaseLayout.js +0 -153
- package/dist/ui/layouts/DashLayout.js +0 -141
- package/dist/ui/layouts/SiteLayout.js +0 -169
- package/dist/ui/pages/ArchivePage.js +0 -143
- package/dist/ui/pages/CollectionPage.js +0 -70
- package/dist/ui/pages/CollectionsPage.js +0 -76
- package/dist/ui/pages/FeaturedPage.js +0 -24
- package/dist/ui/pages/HomePage.js +0 -24
- package/dist/ui/pages/PostPage.js +0 -55
- package/dist/ui/pages/SearchPage.js +0 -122
- package/dist/ui/pages/SinglePage.js +0 -23
- package/dist/ui/shared/EmptyState.js +0 -27
- package/dist/ui/shared/MediaGallery.js +0 -35
- package/dist/ui/shared/Pagination.js +0 -195
- package/dist/ui/shared/ThreadView.js +0 -108
- package/dist/ui/shared/index.js +0 -5
- package/dist/vendor/datastar.js +0 -1606
- package/src/lib/__tests__/config.test.ts +0 -192
- package/src/lib/config.ts +0 -167
- package/src/routes/compose.ts +0 -63
- package/src/ui/dash/PostForm.tsx +0 -360
- package/src/ui/dash/settings/AppearanceContent.tsx +0 -254
package/dist/services/page.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Page Service
|
|
3
|
-
*
|
|
4
|
-
* CRUD operations for standalone pages (about, now, etc.)
|
|
5
|
-
*/ import { eq, desc, sql } from "drizzle-orm";
|
|
6
|
-
import { pages, navItems } from "../db/schema.js";
|
|
7
|
-
import { now } from "../lib/time.js";
|
|
8
|
-
import { render as renderMarkdown } from "../lib/markdown.js";
|
|
9
|
-
export function createPageService(db) {
|
|
10
|
-
function toPage(row) {
|
|
11
|
-
return {
|
|
12
|
-
id: row.id,
|
|
13
|
-
slug: row.slug,
|
|
14
|
-
title: row.title,
|
|
15
|
-
body: row.body,
|
|
16
|
-
bodyHtml: row.bodyHtml,
|
|
17
|
-
status: row.status,
|
|
18
|
-
createdAt: row.createdAt,
|
|
19
|
-
updatedAt: row.updatedAt
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
return {
|
|
23
|
-
async getById (id) {
|
|
24
|
-
const result = await db.select().from(pages).where(eq(pages.id, id)).limit(1);
|
|
25
|
-
return result[0] ? toPage(result[0]) : null;
|
|
26
|
-
},
|
|
27
|
-
async getBySlug (slug) {
|
|
28
|
-
const result = await db.select().from(pages).where(eq(pages.slug, slug)).limit(1);
|
|
29
|
-
return result[0] ? toPage(result[0]) : null;
|
|
30
|
-
},
|
|
31
|
-
async list () {
|
|
32
|
-
const rows = await db.select().from(pages).orderBy(desc(pages.createdAt));
|
|
33
|
-
return rows.map(toPage);
|
|
34
|
-
},
|
|
35
|
-
async listNotInNav () {
|
|
36
|
-
const rows = await db.select().from(pages).where(sql`${pages.id} NOT IN (SELECT ${navItems.pageId} FROM ${navItems} WHERE ${navItems.pageId} IS NOT NULL)`).orderBy(desc(pages.createdAt));
|
|
37
|
-
return rows.map(toPage);
|
|
38
|
-
},
|
|
39
|
-
async create (data) {
|
|
40
|
-
const timestamp = now();
|
|
41
|
-
const bodyHtml = data.body ? renderMarkdown(data.body) : null;
|
|
42
|
-
const result = await db.insert(pages).values({
|
|
43
|
-
slug: data.slug,
|
|
44
|
-
title: data.title ?? null,
|
|
45
|
-
body: data.body ?? null,
|
|
46
|
-
bodyHtml,
|
|
47
|
-
status: data.status ?? "published",
|
|
48
|
-
createdAt: timestamp,
|
|
49
|
-
updatedAt: timestamp
|
|
50
|
-
}).returning();
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- DB insert with .returning() always returns inserted row
|
|
52
|
-
return toPage(result[0]);
|
|
53
|
-
},
|
|
54
|
-
async update (id, data) {
|
|
55
|
-
const existing = await this.getById(id);
|
|
56
|
-
if (!existing) return null;
|
|
57
|
-
const timestamp = now();
|
|
58
|
-
const updates = {
|
|
59
|
-
updatedAt: timestamp
|
|
60
|
-
};
|
|
61
|
-
if (data.slug !== undefined) updates.slug = data.slug;
|
|
62
|
-
if (data.title !== undefined) updates.title = data.title;
|
|
63
|
-
if (data.status !== undefined) updates.status = data.status;
|
|
64
|
-
if (data.body !== undefined) {
|
|
65
|
-
updates.body = data.body;
|
|
66
|
-
updates.bodyHtml = data.body ? renderMarkdown(data.body) : null;
|
|
67
|
-
}
|
|
68
|
-
// If slug changed, update related nav_items
|
|
69
|
-
if (data.slug !== undefined && data.slug !== existing.slug) {
|
|
70
|
-
await db.update(navItems).set({
|
|
71
|
-
url: `/${data.slug}`,
|
|
72
|
-
updatedAt: timestamp
|
|
73
|
-
}).where(eq(navItems.pageId, id));
|
|
74
|
-
}
|
|
75
|
-
const result = await db.update(pages).set(updates).where(eq(pages.id, id)).returning();
|
|
76
|
-
return result[0] ? toPage(result[0]) : null;
|
|
77
|
-
},
|
|
78
|
-
async delete (id) {
|
|
79
|
-
// nav_items with page_id FK have ON DELETE CASCADE, so they auto-delete
|
|
80
|
-
const result = await db.delete(pages).where(eq(pages.id, id)).returning();
|
|
81
|
-
return result.length > 0;
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
package/dist/services/post.js
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Post Service (v2)
|
|
3
|
-
*
|
|
4
|
-
* CRUD operations for posts with Thread support.
|
|
5
|
-
* Posts have format (note/link/quote), status (draft/published),
|
|
6
|
-
* featured flag, and pinned flag.
|
|
7
|
-
*/ import { eq, and, isNull, desc, or, inArray, sql } from "drizzle-orm";
|
|
8
|
-
import { posts } from "../db/schema.js";
|
|
9
|
-
import { now } from "../lib/time.js";
|
|
10
|
-
import { render as renderMarkdown } from "../lib/markdown.js";
|
|
11
|
-
export function createPostService(db) {
|
|
12
|
-
/** Build WHERE conditions from filters (shared by list and count) */ function buildFilterConditions(filters) {
|
|
13
|
-
const conditions = [];
|
|
14
|
-
if (filters.status) {
|
|
15
|
-
conditions.push(eq(posts.status, filters.status));
|
|
16
|
-
}
|
|
17
|
-
if (filters.featured !== undefined) {
|
|
18
|
-
conditions.push(eq(posts.featured, filters.featured ? 1 : 0));
|
|
19
|
-
}
|
|
20
|
-
if (filters.pinned !== undefined) {
|
|
21
|
-
conditions.push(eq(posts.pinned, filters.pinned ? 1 : 0));
|
|
22
|
-
}
|
|
23
|
-
if (filters.format) {
|
|
24
|
-
conditions.push(eq(posts.format, filters.format));
|
|
25
|
-
}
|
|
26
|
-
if (filters.collectionId !== undefined) {
|
|
27
|
-
conditions.push(eq(posts.collectionId, filters.collectionId));
|
|
28
|
-
}
|
|
29
|
-
if (filters.threadId) {
|
|
30
|
-
conditions.push(eq(posts.threadId, filters.threadId));
|
|
31
|
-
}
|
|
32
|
-
if (filters.excludeReplies) {
|
|
33
|
-
conditions.push(isNull(posts.threadId));
|
|
34
|
-
}
|
|
35
|
-
if (!filters.includeDeleted) {
|
|
36
|
-
conditions.push(isNull(posts.deletedAt));
|
|
37
|
-
}
|
|
38
|
-
return conditions;
|
|
39
|
-
}
|
|
40
|
-
function toPost(row) {
|
|
41
|
-
return {
|
|
42
|
-
id: row.id,
|
|
43
|
-
format: row.format,
|
|
44
|
-
status: row.status,
|
|
45
|
-
featured: row.featured,
|
|
46
|
-
pinned: row.pinned,
|
|
47
|
-
path: row.path,
|
|
48
|
-
title: row.title,
|
|
49
|
-
url: row.url,
|
|
50
|
-
body: row.body,
|
|
51
|
-
bodyHtml: row.bodyHtml,
|
|
52
|
-
quoteText: row.quoteText,
|
|
53
|
-
rating: row.rating,
|
|
54
|
-
collectionId: row.collectionId,
|
|
55
|
-
replyToId: row.replyToId,
|
|
56
|
-
threadId: row.threadId,
|
|
57
|
-
deletedAt: row.deletedAt,
|
|
58
|
-
publishedAt: row.publishedAt,
|
|
59
|
-
createdAt: row.createdAt,
|
|
60
|
-
updatedAt: row.updatedAt
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
async getById (id) {
|
|
65
|
-
const result = await db.select().from(posts).where(and(eq(posts.id, id), isNull(posts.deletedAt))).limit(1);
|
|
66
|
-
return result[0] ? toPost(result[0]) : null;
|
|
67
|
-
},
|
|
68
|
-
async getByPath (path) {
|
|
69
|
-
const result = await db.select().from(posts).where(and(eq(posts.path, path), isNull(posts.deletedAt))).limit(1);
|
|
70
|
-
return result[0] ? toPost(result[0]) : null;
|
|
71
|
-
},
|
|
72
|
-
async list (filters = {}) {
|
|
73
|
-
const conditions = buildFilterConditions(filters);
|
|
74
|
-
if (filters.cursor) {
|
|
75
|
-
conditions.push(sql`${posts.id} < ${filters.cursor}`);
|
|
76
|
-
}
|
|
77
|
-
let query = db.select().from(posts).where(conditions.length > 0 ? and(...conditions) : undefined).orderBy(desc(posts.publishedAt), desc(posts.id)).limit(filters.limit ?? 100);
|
|
78
|
-
if (filters.offset !== undefined) {
|
|
79
|
-
query = query.offset(filters.offset);
|
|
80
|
-
}
|
|
81
|
-
const rows = await query;
|
|
82
|
-
return rows.map(toPost);
|
|
83
|
-
},
|
|
84
|
-
async count (filters = {}) {
|
|
85
|
-
const conditions = buildFilterConditions(filters);
|
|
86
|
-
const result = await db.select({
|
|
87
|
-
count: sql`count(*)`.as("count")
|
|
88
|
-
}).from(posts).where(conditions.length > 0 ? and(...conditions) : undefined);
|
|
89
|
-
return result[0]?.count ?? 0;
|
|
90
|
-
},
|
|
91
|
-
async create (data) {
|
|
92
|
-
const timestamp = now();
|
|
93
|
-
const bodyHtml = data.body ? renderMarkdown(data.body) : null;
|
|
94
|
-
// Handle thread relationship
|
|
95
|
-
let threadId = null;
|
|
96
|
-
let status = data.status ?? "published";
|
|
97
|
-
let featured = data.featured ?? false;
|
|
98
|
-
if (data.replyToId) {
|
|
99
|
-
const parent = await this.getById(data.replyToId);
|
|
100
|
-
if (parent) {
|
|
101
|
-
threadId = parent.threadId ?? parent.id;
|
|
102
|
-
// Inherit status and featured from root
|
|
103
|
-
const root = parent.threadId ? await this.getById(parent.threadId) : parent;
|
|
104
|
-
if (root) {
|
|
105
|
-
status = root.status;
|
|
106
|
-
featured = root.featured === 1;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
const result = await db.insert(posts).values({
|
|
111
|
-
format: data.format,
|
|
112
|
-
status,
|
|
113
|
-
featured: featured ? 1 : 0,
|
|
114
|
-
pinned: data.pinned ? 1 : 0,
|
|
115
|
-
path: data.path ?? null,
|
|
116
|
-
title: data.title ?? null,
|
|
117
|
-
url: data.url ?? null,
|
|
118
|
-
body: data.body ?? null,
|
|
119
|
-
bodyHtml,
|
|
120
|
-
quoteText: data.quoteText ?? null,
|
|
121
|
-
rating: data.rating ?? null,
|
|
122
|
-
collectionId: data.collectionId ?? null,
|
|
123
|
-
replyToId: data.replyToId ?? null,
|
|
124
|
-
threadId,
|
|
125
|
-
publishedAt: data.publishedAt ?? timestamp,
|
|
126
|
-
createdAt: timestamp,
|
|
127
|
-
updatedAt: timestamp
|
|
128
|
-
}).returning();
|
|
129
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- DB insert with .returning() always returns inserted row
|
|
130
|
-
return toPost(result[0]);
|
|
131
|
-
},
|
|
132
|
-
async update (id, data) {
|
|
133
|
-
const existing = await this.getById(id);
|
|
134
|
-
if (!existing) return null;
|
|
135
|
-
const timestamp = now();
|
|
136
|
-
const updates = {
|
|
137
|
-
updatedAt: timestamp
|
|
138
|
-
};
|
|
139
|
-
if (data.format !== undefined) updates.format = data.format;
|
|
140
|
-
if (data.path !== undefined) updates.path = data.path;
|
|
141
|
-
if (data.title !== undefined) updates.title = data.title;
|
|
142
|
-
if (data.url !== undefined) updates.url = data.url;
|
|
143
|
-
if (data.quoteText !== undefined) updates.quoteText = data.quoteText;
|
|
144
|
-
if (data.rating !== undefined) updates.rating = data.rating;
|
|
145
|
-
if (data.collectionId !== undefined) updates.collectionId = data.collectionId;
|
|
146
|
-
if (data.publishedAt !== undefined) updates.publishedAt = data.publishedAt;
|
|
147
|
-
if (data.pinned !== undefined) updates.pinned = data.pinned ? 1 : 0;
|
|
148
|
-
if (data.body !== undefined) {
|
|
149
|
-
updates.body = data.body;
|
|
150
|
-
updates.bodyHtml = data.body ? renderMarkdown(data.body) : null;
|
|
151
|
-
}
|
|
152
|
-
// Handle status/featured change - cascade to thread if this is root
|
|
153
|
-
const statusChanged = data.status !== undefined && data.status !== existing.status;
|
|
154
|
-
const featuredChanged = data.featured !== undefined && (data.featured ? 1 : 0) !== existing.featured;
|
|
155
|
-
if (statusChanged) updates.status = data.status;
|
|
156
|
-
if (featuredChanged) updates.featured = data.featured ? 1 : 0;
|
|
157
|
-
// If this is a root post and status/featured changed, cascade to thread
|
|
158
|
-
if ((statusChanged || featuredChanged) && !existing.threadId) {
|
|
159
|
-
await this.updateThreadStatusAndFeatured(id, data.status ?? existing.status, data.featured !== undefined ? data.featured : existing.featured === 1);
|
|
160
|
-
}
|
|
161
|
-
const result = await db.update(posts).set(updates).where(eq(posts.id, id)).returning();
|
|
162
|
-
return result[0] ? toPost(result[0]) : null;
|
|
163
|
-
},
|
|
164
|
-
async delete (id) {
|
|
165
|
-
const existing = await this.getById(id);
|
|
166
|
-
if (!existing) return false;
|
|
167
|
-
const timestamp = now();
|
|
168
|
-
// If this is a thread root, soft delete all posts in the thread
|
|
169
|
-
if (!existing.threadId) {
|
|
170
|
-
await db.update(posts).set({
|
|
171
|
-
deletedAt: timestamp,
|
|
172
|
-
updatedAt: timestamp
|
|
173
|
-
}).where(or(eq(posts.id, id), eq(posts.threadId, id)));
|
|
174
|
-
} else {
|
|
175
|
-
await db.update(posts).set({
|
|
176
|
-
deletedAt: timestamp,
|
|
177
|
-
updatedAt: timestamp
|
|
178
|
-
}).where(eq(posts.id, id));
|
|
179
|
-
}
|
|
180
|
-
return true;
|
|
181
|
-
},
|
|
182
|
-
async getThread (rootId) {
|
|
183
|
-
const rows = await db.select().from(posts).where(and(or(eq(posts.id, rootId), eq(posts.threadId, rootId)), isNull(posts.deletedAt))).orderBy(posts.createdAt);
|
|
184
|
-
return rows.map(toPost);
|
|
185
|
-
},
|
|
186
|
-
async updateThreadStatusAndFeatured (rootId, status, featured) {
|
|
187
|
-
const timestamp = now();
|
|
188
|
-
await db.update(posts).set({
|
|
189
|
-
status,
|
|
190
|
-
featured: featured ? 1 : 0,
|
|
191
|
-
updatedAt: timestamp
|
|
192
|
-
}).where(eq(posts.threadId, rootId));
|
|
193
|
-
},
|
|
194
|
-
async getReplyCounts (postIds) {
|
|
195
|
-
if (postIds.length === 0) return new Map();
|
|
196
|
-
const rows = await db.select({
|
|
197
|
-
threadId: posts.threadId,
|
|
198
|
-
count: sql`count(*)`.as("count")
|
|
199
|
-
}).from(posts).where(and(inArray(posts.threadId, postIds), isNull(posts.deletedAt))).groupBy(posts.threadId);
|
|
200
|
-
const counts = new Map();
|
|
201
|
-
for (const row of rows){
|
|
202
|
-
if (row.threadId !== null) {
|
|
203
|
-
counts.set(row.threadId, row.count);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return counts;
|
|
207
|
-
},
|
|
208
|
-
async getThreadPreviews (rootIds, previewCount = 3) {
|
|
209
|
-
if (rootIds.length === 0) return new Map();
|
|
210
|
-
const rows = await db.select().from(posts).where(and(inArray(posts.threadId, rootIds), isNull(posts.deletedAt))).orderBy(posts.threadId, posts.createdAt);
|
|
211
|
-
const result = new Map();
|
|
212
|
-
for (const row of rows){
|
|
213
|
-
const post = toPost(row);
|
|
214
|
-
if (post.threadId === null) continue;
|
|
215
|
-
const list = result.get(post.threadId);
|
|
216
|
-
if (list) {
|
|
217
|
-
if (list.length < previewCount) {
|
|
218
|
-
list.push(post);
|
|
219
|
-
}
|
|
220
|
-
} else {
|
|
221
|
-
result.set(post.threadId, [
|
|
222
|
-
post
|
|
223
|
-
]);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return result;
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Redirect Service
|
|
3
|
-
*
|
|
4
|
-
* URL redirect management for path changes
|
|
5
|
-
*/ import { eq } from "drizzle-orm";
|
|
6
|
-
import { redirects } from "../db/schema.js";
|
|
7
|
-
import { now } from "../lib/time.js";
|
|
8
|
-
import { normalizePath } from "../lib/url.js";
|
|
9
|
-
export function createRedirectService(db) {
|
|
10
|
-
function toRedirect(row) {
|
|
11
|
-
return {
|
|
12
|
-
id: row.id,
|
|
13
|
-
fromPath: row.fromPath,
|
|
14
|
-
toPath: row.toPath,
|
|
15
|
-
type: row.type,
|
|
16
|
-
createdAt: row.createdAt
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
return {
|
|
20
|
-
async getByPath (fromPath) {
|
|
21
|
-
const normalized = normalizePath(fromPath);
|
|
22
|
-
const result = await db.select().from(redirects).where(eq(redirects.fromPath, normalized)).limit(1);
|
|
23
|
-
return result[0] ? toRedirect(result[0]) : null;
|
|
24
|
-
},
|
|
25
|
-
async create (fromPath, toPath, type = 301) {
|
|
26
|
-
const timestamp = now();
|
|
27
|
-
const normalizedFrom = normalizePath(fromPath);
|
|
28
|
-
// Delete existing redirect from this path if any
|
|
29
|
-
await db.delete(redirects).where(eq(redirects.fromPath, normalizedFrom));
|
|
30
|
-
const result = await db.insert(redirects).values({
|
|
31
|
-
fromPath: normalizedFrom,
|
|
32
|
-
toPath,
|
|
33
|
-
type,
|
|
34
|
-
createdAt: timestamp
|
|
35
|
-
}).returning();
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- DB insert with .returning() always returns inserted row
|
|
37
|
-
return toRedirect(result[0]);
|
|
38
|
-
},
|
|
39
|
-
async delete (id) {
|
|
40
|
-
const result = await db.delete(redirects).where(eq(redirects.id, id)).returning();
|
|
41
|
-
return result.length > 0;
|
|
42
|
-
},
|
|
43
|
-
async list () {
|
|
44
|
-
const rows = await db.select().from(redirects);
|
|
45
|
-
return rows.map(toRedirect);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
}
|
package/dist/services/search.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Search Service (v2)
|
|
3
|
-
*
|
|
4
|
-
* Full-text search using FTS5
|
|
5
|
-
*/ export function createSearchService(d1) {
|
|
6
|
-
return {
|
|
7
|
-
async search (query, options = {}) {
|
|
8
|
-
const limit = options.limit ?? 20;
|
|
9
|
-
const offset = options.offset ?? 0;
|
|
10
|
-
const status = options.status ?? [
|
|
11
|
-
"published"
|
|
12
|
-
];
|
|
13
|
-
// Escape and prepare the query for FTS5
|
|
14
|
-
const ftsQuery = query.trim().split(/\s+/).filter((term)=>term.length > 0).map((term)=>`"${term.replace(/"/g, '""')}"*`).join(" ");
|
|
15
|
-
if (!ftsQuery) {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
// Build status placeholders
|
|
19
|
-
const statusPlaceholders = status.map(()=>"?").join(", ");
|
|
20
|
-
// Build format filter
|
|
21
|
-
const formatFilter = options.format ? "AND posts.format = ?" : "";
|
|
22
|
-
const formatParams = options.format ? [
|
|
23
|
-
options.format
|
|
24
|
-
] : [];
|
|
25
|
-
const stmt = d1.prepare(`
|
|
26
|
-
SELECT
|
|
27
|
-
posts.*,
|
|
28
|
-
posts_fts.rank AS rank,
|
|
29
|
-
snippet(posts_fts, 1, '<mark>', '</mark>', '...', 32) AS snippet
|
|
30
|
-
FROM posts_fts
|
|
31
|
-
JOIN posts ON posts.id = posts_fts.rowid
|
|
32
|
-
WHERE posts_fts MATCH ?
|
|
33
|
-
AND posts.deleted_at IS NULL
|
|
34
|
-
AND posts.status IN (${statusPlaceholders})
|
|
35
|
-
${formatFilter}
|
|
36
|
-
ORDER BY posts_fts.rank
|
|
37
|
-
LIMIT ? OFFSET ?
|
|
38
|
-
`);
|
|
39
|
-
const { results } = await stmt.bind(ftsQuery, ...status, ...formatParams, limit, offset).all();
|
|
40
|
-
return (results || []).map((row)=>({
|
|
41
|
-
post: {
|
|
42
|
-
id: row.id,
|
|
43
|
-
format: row.format,
|
|
44
|
-
status: row.status,
|
|
45
|
-
featured: row.featured,
|
|
46
|
-
pinned: row.pinned,
|
|
47
|
-
path: row.path,
|
|
48
|
-
title: row.title,
|
|
49
|
-
url: row.url,
|
|
50
|
-
body: row.body,
|
|
51
|
-
bodyHtml: row.body_html,
|
|
52
|
-
quoteText: row.quote_text,
|
|
53
|
-
rating: row.rating,
|
|
54
|
-
collectionId: row.collection_id,
|
|
55
|
-
replyToId: row.reply_to_id,
|
|
56
|
-
threadId: row.thread_id,
|
|
57
|
-
deletedAt: row.deleted_at,
|
|
58
|
-
publishedAt: row.published_at,
|
|
59
|
-
createdAt: row.created_at,
|
|
60
|
-
updatedAt: row.updated_at
|
|
61
|
-
},
|
|
62
|
-
rank: row.rank,
|
|
63
|
-
snippet: row.snippet
|
|
64
|
-
}));
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Settings Service
|
|
3
|
-
*
|
|
4
|
-
* Key-value store for site configuration
|
|
5
|
-
*/ import { eq } from "drizzle-orm";
|
|
6
|
-
import { settings } from "../db/schema.js";
|
|
7
|
-
import { now } from "../lib/time.js";
|
|
8
|
-
import { SETTINGS_KEYS, ONBOARDING_STATUS } from "../lib/constants.js";
|
|
9
|
-
export function createSettingsService(db) {
|
|
10
|
-
return {
|
|
11
|
-
async get (key) {
|
|
12
|
-
const result = await db.select().from(settings).where(eq(settings.key, key)).limit(1);
|
|
13
|
-
return result[0]?.value ?? null;
|
|
14
|
-
},
|
|
15
|
-
async getAll () {
|
|
16
|
-
const rows = await db.select().from(settings);
|
|
17
|
-
const result = {};
|
|
18
|
-
for (const row of rows){
|
|
19
|
-
result[row.key] = row.value;
|
|
20
|
-
}
|
|
21
|
-
return result;
|
|
22
|
-
},
|
|
23
|
-
async set (key, value) {
|
|
24
|
-
const timestamp = now();
|
|
25
|
-
await db.insert(settings).values({
|
|
26
|
-
key,
|
|
27
|
-
value,
|
|
28
|
-
updatedAt: timestamp
|
|
29
|
-
}).onConflictDoUpdate({
|
|
30
|
-
target: settings.key,
|
|
31
|
-
set: {
|
|
32
|
-
value,
|
|
33
|
-
updatedAt: timestamp
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
},
|
|
37
|
-
async remove (key) {
|
|
38
|
-
await db.delete(settings).where(eq(settings.key, key));
|
|
39
|
-
},
|
|
40
|
-
async setMany (entries) {
|
|
41
|
-
const timestamp = now();
|
|
42
|
-
const keys = Object.keys(entries);
|
|
43
|
-
for (const key of keys){
|
|
44
|
-
const value = entries[key];
|
|
45
|
-
if (value !== undefined) {
|
|
46
|
-
await db.insert(settings).values({
|
|
47
|
-
key,
|
|
48
|
-
value,
|
|
49
|
-
updatedAt: timestamp
|
|
50
|
-
}).onConflictDoUpdate({
|
|
51
|
-
target: settings.key,
|
|
52
|
-
set: {
|
|
53
|
-
value,
|
|
54
|
-
updatedAt: timestamp
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
async isOnboardingComplete () {
|
|
61
|
-
const status = await this.get(SETTINGS_KEYS.ONBOARDING_STATUS);
|
|
62
|
-
return status === ONBOARDING_STATUS.COMPLETED;
|
|
63
|
-
},
|
|
64
|
-
async completeOnboarding () {
|
|
65
|
-
await this.set(SETTINGS_KEYS.ONBOARDING_STATUS, ONBOARDING_STATUS.COMPLETED);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
}
|
package/dist/types/bindings.js
DELETED
package/dist/types/config.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration System
|
|
3
|
-
*
|
|
4
|
-
* Single Source of Truth for all configuration fields.
|
|
5
|
-
*/ /**
|
|
6
|
-
* Configuration Registry - Single Source of Truth
|
|
7
|
-
*
|
|
8
|
-
* All available configuration fields with their metadata.
|
|
9
|
-
* Add new fields here, and they'll automatically work everywhere.
|
|
10
|
-
*
|
|
11
|
-
* Priority logic:
|
|
12
|
-
* - envOnly: false -> User-configurable (DB > ENV > Default)
|
|
13
|
-
* - envOnly: true -> Environment-only (ENV > Default)
|
|
14
|
-
*/ export const CONFIG_FIELDS = {
|
|
15
|
-
// User-configurable (can be modified in dashboard)
|
|
16
|
-
SITE_NAME: {
|
|
17
|
-
defaultValue: "Jant",
|
|
18
|
-
envOnly: false
|
|
19
|
-
},
|
|
20
|
-
SITE_DESCRIPTION: {
|
|
21
|
-
defaultValue: "A microblog powered by Jant",
|
|
22
|
-
envOnly: false
|
|
23
|
-
},
|
|
24
|
-
SITE_LANGUAGE: {
|
|
25
|
-
defaultValue: "en",
|
|
26
|
-
envOnly: false
|
|
27
|
-
},
|
|
28
|
-
HOME_DEFAULT_VIEW: {
|
|
29
|
-
defaultValue: "latest",
|
|
30
|
-
envOnly: false
|
|
31
|
-
},
|
|
32
|
-
// Environment-only (deployment/infrastructure config)
|
|
33
|
-
SITE_URL: {
|
|
34
|
-
defaultValue: "",
|
|
35
|
-
envOnly: true
|
|
36
|
-
},
|
|
37
|
-
AUTH_SECRET: {
|
|
38
|
-
defaultValue: "",
|
|
39
|
-
envOnly: true
|
|
40
|
-
},
|
|
41
|
-
R2_PUBLIC_URL: {
|
|
42
|
-
defaultValue: "",
|
|
43
|
-
envOnly: true
|
|
44
|
-
},
|
|
45
|
-
IMAGE_TRANSFORM_URL: {
|
|
46
|
-
defaultValue: "",
|
|
47
|
-
envOnly: true
|
|
48
|
-
},
|
|
49
|
-
DEMO_EMAIL: {
|
|
50
|
-
defaultValue: "",
|
|
51
|
-
envOnly: true
|
|
52
|
-
},
|
|
53
|
-
DEMO_PASSWORD: {
|
|
54
|
-
defaultValue: "",
|
|
55
|
-
envOnly: true
|
|
56
|
-
},
|
|
57
|
-
PAGE_SIZE: {
|
|
58
|
-
defaultValue: "20",
|
|
59
|
-
envOnly: true
|
|
60
|
-
},
|
|
61
|
-
STORAGE_DRIVER: {
|
|
62
|
-
defaultValue: "r2",
|
|
63
|
-
envOnly: true
|
|
64
|
-
},
|
|
65
|
-
S3_ENDPOINT: {
|
|
66
|
-
defaultValue: "",
|
|
67
|
-
envOnly: true
|
|
68
|
-
},
|
|
69
|
-
S3_BUCKET: {
|
|
70
|
-
defaultValue: "",
|
|
71
|
-
envOnly: true
|
|
72
|
-
},
|
|
73
|
-
S3_ACCESS_KEY_ID: {
|
|
74
|
-
defaultValue: "",
|
|
75
|
-
envOnly: true
|
|
76
|
-
},
|
|
77
|
-
S3_SECRET_ACCESS_KEY: {
|
|
78
|
-
defaultValue: "",
|
|
79
|
-
envOnly: true
|
|
80
|
-
},
|
|
81
|
-
S3_REGION: {
|
|
82
|
-
defaultValue: "auto",
|
|
83
|
-
envOnly: true
|
|
84
|
-
},
|
|
85
|
-
S3_PUBLIC_URL: {
|
|
86
|
-
defaultValue: "",
|
|
87
|
-
envOnly: true
|
|
88
|
-
},
|
|
89
|
-
// Internal settings (DB-only, not configurable via env or dashboard)
|
|
90
|
-
THEME: {
|
|
91
|
-
defaultValue: "",
|
|
92
|
-
envOnly: false,
|
|
93
|
-
internal: true
|
|
94
|
-
},
|
|
95
|
-
CUSTOM_CSS: {
|
|
96
|
-
defaultValue: "",
|
|
97
|
-
envOnly: false,
|
|
98
|
-
internal: true
|
|
99
|
-
},
|
|
100
|
-
SITE_AVATAR: {
|
|
101
|
-
defaultValue: "",
|
|
102
|
-
envOnly: false,
|
|
103
|
-
internal: true
|
|
104
|
-
},
|
|
105
|
-
SHOW_HEADER_AVATAR: {
|
|
106
|
-
defaultValue: "",
|
|
107
|
-
envOnly: false,
|
|
108
|
-
internal: true
|
|
109
|
-
},
|
|
110
|
-
SITE_FAVICON_ICO: {
|
|
111
|
-
defaultValue: "",
|
|
112
|
-
envOnly: false,
|
|
113
|
-
internal: true
|
|
114
|
-
},
|
|
115
|
-
SITE_FAVICON_APPLE_TOUCH: {
|
|
116
|
-
defaultValue: "",
|
|
117
|
-
envOnly: false,
|
|
118
|
-
internal: true
|
|
119
|
-
},
|
|
120
|
-
FONT_THEME: {
|
|
121
|
-
defaultValue: "",
|
|
122
|
-
envOnly: false,
|
|
123
|
-
internal: true
|
|
124
|
-
},
|
|
125
|
-
TIME_ZONE: {
|
|
126
|
-
defaultValue: "UTC",
|
|
127
|
-
envOnly: false
|
|
128
|
-
},
|
|
129
|
-
SITE_FOOTER: {
|
|
130
|
-
defaultValue: "",
|
|
131
|
-
envOnly: false
|
|
132
|
-
},
|
|
133
|
-
NOINDEX: {
|
|
134
|
-
defaultValue: "",
|
|
135
|
-
envOnly: false
|
|
136
|
-
},
|
|
137
|
-
ONBOARDING_STATUS: {
|
|
138
|
-
defaultValue: "pending",
|
|
139
|
-
envOnly: false,
|
|
140
|
-
internal: true
|
|
141
|
-
},
|
|
142
|
-
PASSWORD_RESET_TOKEN: {
|
|
143
|
-
defaultValue: "",
|
|
144
|
-
envOnly: false,
|
|
145
|
-
internal: true
|
|
146
|
-
}
|
|
147
|
-
};
|
package/dist/types/constants.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Content Type Constants
|
|
3
|
-
*/ export const FORMATS = [
|
|
4
|
-
"note",
|
|
5
|
-
"link",
|
|
6
|
-
"quote"
|
|
7
|
-
];
|
|
8
|
-
export const STATUSES = [
|
|
9
|
-
"draft",
|
|
10
|
-
"published"
|
|
11
|
-
];
|
|
12
|
-
export const SORT_ORDERS = [
|
|
13
|
-
"newest",
|
|
14
|
-
"oldest",
|
|
15
|
-
"rating_desc",
|
|
16
|
-
"rating_asc"
|
|
17
|
-
];
|
|
18
|
-
export const NAV_ITEM_TYPES = [
|
|
19
|
-
"page",
|
|
20
|
-
"link"
|
|
21
|
-
];
|
|
22
|
-
export const MAX_MEDIA_ATTACHMENTS = 20;
|
|
23
|
-
export const MAX_PINNED_POSTS = 3;
|
|
24
|
-
export const STORAGE_DRIVERS = [
|
|
25
|
-
"r2",
|
|
26
|
-
"s3"
|
|
27
|
-
];
|
package/dist/types/entities.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type declarations for @lingui/react/macro
|
|
3
|
-
*
|
|
4
|
-
* @lingui/react is not installed (it requires React as a peer dependency),
|
|
5
|
-
* but the SWC Lingui plugin recognizes imports from @lingui/react/macro and
|
|
6
|
-
* rewrites them via runtimeConfigModule to our custom Hono JSX implementation.
|
|
7
|
-
*
|
|
8
|
-
* These declarations satisfy TypeScript for the pre-transformation API surface.
|
|
9
|
-
*/
|