@jant/core 0.3.35 → 0.3.37
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/bin/commands/export.js +1 -1
- package/bin/commands/import-site.js +529 -0
- package/bin/commands/reset-password.js +3 -2
- package/dist/client/assets/heic-to-DIRPI3VF.js +1 -0
- package/dist/client/assets/module-RjUF93sV.js +716 -0
- package/dist/client/assets/native-48B9X9Wg.js +1 -0
- package/dist/client/assets/url-FWFqPJPb.js +1 -0
- package/dist/client/client.css +1 -1
- package/dist/client/client.js +4564 -3013
- package/dist/index.js +12885 -8161
- package/package.json +23 -6
- package/src/__tests__/helpers/app.ts +10 -10
- package/src/__tests__/helpers/db.ts +91 -87
- package/src/app.tsx +157 -31
- package/src/auth.ts +20 -2
- package/src/client/archive-nav.js +187 -0
- package/src/client/audio-player.ts +478 -0
- package/src/client/audio-processor.ts +84 -0
- package/src/{lib → client}/avatar-upload.ts +4 -3
- package/src/{lib → client}/collection-form-bridge.ts +2 -2
- package/src/{ui → client}/components/__tests__/jant-collection-form.test.ts +26 -9
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +1140 -0
- package/src/client/components/__tests__/jant-compose-editor.test.ts +504 -0
- package/src/{ui → client}/components/__tests__/jant-post-form.test.ts +37 -17
- package/src/{ui → client}/components/__tests__/jant-settings-avatar.test.ts +2 -2
- package/src/{ui → client}/components/__tests__/jant-settings-general.test.ts +3 -3
- package/src/client/components/collection-sidebar-types.ts +43 -0
- package/src/{ui → client}/components/collection-types.ts +3 -4
- package/src/client/components/compose-types.ts +174 -0
- package/src/client/components/jant-collection-form.ts +667 -0
- package/src/client/components/jant-collection-sidebar.ts +805 -0
- package/src/client/components/jant-compose-dialog.ts +2161 -0
- package/src/client/components/jant-compose-editor.ts +1813 -0
- package/src/client/components/jant-compose-fullscreen.ts +283 -0
- package/src/client/components/jant-media-lightbox.ts +259 -0
- package/src/{ui → client}/components/jant-nav-manager.ts +97 -298
- package/src/{ui → client}/components/jant-post-form.ts +141 -12
- package/src/client/components/jant-post-menu.ts +1019 -0
- package/src/{ui → client}/components/jant-settings-avatar.ts +3 -3
- package/src/{ui → client}/components/jant-settings-general.ts +38 -4
- package/src/client/components/jant-text-preview.ts +232 -0
- package/src/{ui → client}/components/nav-manager-types.ts +6 -18
- package/src/{ui → client}/components/post-form-template.ts +137 -38
- package/src/{ui → client}/components/post-form-types.ts +15 -4
- package/src/client/compose-bridge.ts +583 -0
- package/src/{lib → client}/image-processor.ts +26 -8
- package/src/client/lazy-slugify.ts +51 -0
- package/src/client/media-metadata.ts +247 -0
- package/src/client/multipart-upload.ts +160 -0
- package/src/{lib → client}/nav-manager-bridge.ts +1 -1
- package/src/{lib → client}/post-form-bridge.ts +53 -2
- package/src/{lib → client}/settings-bridge.ts +3 -15
- package/src/client/thread-context.ts +140 -0
- package/src/client/tiptap/bubble-menu.ts +205 -0
- package/src/client/tiptap/create-editor.ts +86 -0
- package/src/client/tiptap/exitable-marks.ts +73 -0
- package/src/client/tiptap/extensions.ts +65 -0
- package/src/client/tiptap/image-node.ts +482 -0
- package/src/client/tiptap/link-toolbar.ts +371 -0
- package/src/client/tiptap/more-break.ts +50 -0
- package/src/client/tiptap/paste-image.ts +129 -0
- package/src/client/tiptap/slash-commands.ts +438 -0
- package/src/{lib → client}/toast.ts +101 -3
- package/src/client/types/sortablejs.d.ts +44 -0
- package/src/client/upload-with-metadata.ts +54 -0
- package/src/client/video-processor.ts +207 -0
- package/src/client.ts +27 -17
- package/src/db/__tests__/migrations.test.ts +118 -0
- package/src/db/index.ts +52 -0
- package/src/db/migrations/0000_baseline.sql +269 -0
- package/src/db/migrations/0001_fts_setup.sql +31 -0
- package/src/db/migrations/meta/0000_snapshot.json +703 -119
- package/src/db/migrations/meta/0001_snapshot.json +1337 -0
- package/src/db/migrations/meta/_journal.json +4 -39
- package/src/db/schema.ts +409 -140
- package/src/i18n/__tests__/detect.test.ts +115 -0
- package/src/i18n/context.tsx +2 -2
- package/src/i18n/detect.ts +85 -1
- package/src/i18n/i18n.ts +1 -1
- package/src/i18n/index.ts +2 -1
- package/src/i18n/locales/en.po +783 -1087
- package/src/i18n/locales/en.ts +1 -1
- package/src/i18n/locales/zh-Hans.po +867 -812
- package/src/i18n/locales/zh-Hans.ts +1 -1
- package/src/i18n/locales/zh-Hant.po +878 -823
- package/src/i18n/locales/zh-Hant.ts +1 -1
- package/src/i18n/middleware.ts +6 -0
- package/src/index.ts +5 -7
- package/src/lib/__tests__/blurhash-placeholder.test.ts +75 -0
- package/src/lib/__tests__/constants.test.ts +0 -1
- package/src/lib/__tests__/markdown-to-tiptap.test.ts +358 -0
- package/src/lib/__tests__/nanoid.test.ts +26 -0
- package/src/lib/__tests__/resolve-config.test.ts +2 -2
- package/src/lib/__tests__/schemas.test.ts +186 -65
- package/src/lib/__tests__/slug.test.ts +126 -0
- package/src/lib/__tests__/sse.test.ts +6 -6
- package/src/lib/__tests__/summary.test.ts +264 -0
- package/src/lib/__tests__/theme.test.ts +1 -1
- package/src/lib/__tests__/timeline.test.ts +33 -30
- package/src/lib/__tests__/tiptap-to-markdown.test.ts +346 -0
- package/src/lib/__tests__/url.test.ts +2 -2
- package/src/lib/__tests__/view.test.ts +140 -65
- package/src/lib/blurhash-placeholder.ts +102 -0
- package/src/lib/constants.ts +3 -1
- package/src/lib/emoji-catalog.ts +963 -0
- package/src/lib/errors.ts +11 -8
- package/src/lib/feed.ts +77 -31
- package/src/lib/html.ts +2 -1
- package/src/lib/icon-catalog.ts +5033 -1
- package/src/lib/icons.ts +3 -2
- package/src/lib/index.ts +0 -1
- package/src/lib/markdown-to-tiptap.ts +286 -0
- package/src/lib/media-helpers.ts +22 -12
- package/src/lib/nanoid.ts +29 -0
- package/src/lib/navigation.ts +1 -1
- package/src/lib/render.tsx +24 -5
- package/src/lib/resolve-config.ts +13 -2
- package/src/lib/schemas.ts +226 -58
- package/src/lib/search-snippet.ts +34 -0
- package/src/lib/slug.ts +96 -0
- package/src/lib/sse.ts +6 -6
- package/src/lib/storage.ts +115 -7
- package/src/lib/summary.ts +158 -0
- package/src/lib/theme.ts +11 -8
- package/src/lib/timeline.ts +76 -34
- package/src/lib/tiptap-render.ts +191 -0
- package/src/lib/tiptap-to-markdown.ts +305 -0
- package/src/lib/upload.ts +263 -14
- package/src/lib/url.ts +37 -22
- package/src/lib/view.ts +236 -55
- package/src/middleware/__tests__/auth.test.ts +191 -11
- package/src/middleware/__tests__/onboarding.test.ts +12 -10
- package/src/middleware/auth.ts +63 -9
- package/src/middleware/error-handler.ts +3 -3
- package/src/middleware/onboarding.ts +1 -1
- package/src/middleware/secure-headers.ts +40 -0
- package/src/preset.css +83 -2
- package/src/routes/__tests__/compose.test.ts +17 -24
- package/src/routes/api/__tests__/collections.test.ts +109 -61
- package/src/routes/api/__tests__/nav-items.test.ts +46 -29
- package/src/routes/api/__tests__/posts.test.ts +132 -68
- package/src/routes/api/__tests__/search.test.ts +15 -2
- package/src/routes/api/__tests__/upload-multipart.test.ts +534 -0
- package/src/routes/api/collections.ts +57 -31
- package/src/routes/api/custom-urls.ts +80 -0
- package/src/routes/api/export.ts +31 -0
- package/src/routes/api/nav-items.ts +23 -19
- package/src/routes/api/posts.ts +81 -62
- package/src/routes/api/search.ts +3 -4
- package/src/routes/api/upload-multipart.ts +245 -0
- package/src/routes/api/upload.ts +92 -24
- package/src/routes/auth/__tests__/setup.test.ts +20 -60
- package/src/routes/auth/reset.tsx +5 -4
- package/src/routes/auth/setup.tsx +39 -31
- package/src/routes/auth/signin.tsx +13 -14
- package/src/routes/compose.tsx +27 -63
- package/src/routes/dash/__tests__/settings-avatar.test.ts +44 -9
- package/src/routes/dash/custom-urls.tsx +414 -0
- package/src/routes/dash/settings.tsx +475 -99
- package/src/routes/feed/__tests__/rss.test.ts +22 -23
- package/src/routes/feed/rss.ts +6 -2
- package/src/routes/feed/sitemap.ts +2 -12
- package/src/routes/pages/__tests__/collections.test.ts +5 -6
- package/src/routes/pages/__tests__/featured.test.ts +36 -18
- package/src/routes/pages/archive.tsx +177 -37
- package/src/routes/pages/collection.tsx +43 -14
- package/src/routes/pages/collections.tsx +11 -2
- package/src/routes/pages/featured.tsx +27 -3
- package/src/routes/pages/home.tsx +15 -14
- package/src/routes/pages/latest.tsx +1 -11
- package/src/routes/pages/new.tsx +39 -0
- package/src/routes/pages/page.tsx +95 -49
- package/src/routes/pages/search.tsx +1 -1
- package/src/services/__tests__/api-token.test.ts +135 -0
- package/src/services/__tests__/collection.test.ts +275 -227
- package/src/services/__tests__/custom-url.test.ts +213 -0
- package/src/services/__tests__/media.test.ts +162 -22
- package/src/services/__tests__/navigation.test.ts +109 -68
- package/src/services/__tests__/post-timeline.test.ts +205 -32
- package/src/services/__tests__/post.test.ts +800 -230
- package/src/services/__tests__/search.test.ts +67 -10
- package/src/services/__tests__/settings.test.ts +3 -3
- package/src/services/api-token.ts +166 -0
- package/src/services/auth.ts +17 -2
- package/src/services/collection.ts +397 -131
- package/src/services/custom-url.ts +188 -0
- package/src/services/export.ts +802 -0
- package/src/services/index.ts +26 -19
- package/src/services/media.ts +100 -22
- package/src/services/navigation.ts +158 -47
- package/src/services/path.ts +339 -0
- package/src/services/post.ts +764 -172
- package/src/services/search.ts +161 -74
- package/src/services/settings.ts +6 -2
- package/src/styles/components.css +293 -62
- package/src/styles/tokens.css +93 -5
- package/src/styles/ui.css +4349 -766
- package/src/types/bindings.ts +8 -0
- package/src/types/config.ts +34 -4
- package/src/types/constants.ts +17 -2
- package/src/types/entities.ts +83 -37
- package/src/types/operations.ts +20 -27
- package/src/types/props.ts +52 -17
- package/src/types/views.ts +48 -24
- package/src/ui/color-themes.ts +133 -23
- package/src/ui/compose/ComposeDialog.tsx +255 -16
- package/src/ui/compose/ComposePrompt.tsx +1 -1
- package/src/ui/dash/CrudPageHeader.tsx +1 -1
- package/src/ui/dash/ListItemRow.tsx +1 -1
- package/src/ui/dash/StatusBadge.tsx +12 -2
- package/src/ui/dash/appearance/AdvancedContent.tsx +71 -59
- package/src/ui/dash/appearance/ColorThemeContent.tsx +48 -33
- package/src/ui/dash/appearance/FontThemeContent.tsx +65 -73
- package/src/ui/dash/appearance/NavigationContent.tsx +106 -135
- package/src/ui/dash/index.ts +0 -3
- package/src/ui/dash/settings/AccountContent.tsx +87 -146
- package/src/ui/dash/settings/AccountMenuContent.tsx +147 -0
- package/src/ui/dash/settings/ApiTokensContent.tsx +232 -0
- package/src/ui/dash/settings/AvatarContent.tsx +78 -0
- package/src/ui/dash/settings/GeneralContent.tsx +3 -62
- package/src/ui/dash/settings/SessionsContent.tsx +159 -0
- package/src/ui/dash/settings/SettingsRootContent.tsx +266 -0
- package/src/ui/feed/LinkCard.tsx +89 -40
- package/src/ui/feed/NoteCard.tsx +39 -25
- package/src/ui/feed/PostStatusBadges.tsx +67 -0
- package/src/ui/feed/QuoteCard.tsx +38 -23
- package/src/ui/feed/ThreadPreview.tsx +90 -26
- package/src/ui/feed/TimelineFeed.tsx +3 -2
- package/src/ui/feed/TimelineItem.tsx +15 -6
- package/src/ui/feed/__tests__/thread-preview.test.ts +107 -0
- package/src/ui/feed/thread-preview-state.ts +61 -0
- package/src/ui/font-themes.ts +2 -2
- package/src/ui/layouts/BaseLayout.tsx +2 -2
- package/src/ui/layouts/SiteLayout.tsx +116 -103
- package/src/ui/pages/ArchivePage.tsx +923 -95
- package/src/ui/pages/CollectionPage.tsx +6 -35
- package/src/ui/pages/CollectionsPage.tsx +2 -1
- package/src/ui/pages/ComposePage.tsx +54 -0
- package/src/ui/pages/FeaturedPage.tsx +2 -1
- package/src/ui/pages/HomePage.tsx +1 -1
- package/src/ui/pages/PostPage.tsx +30 -45
- package/src/ui/pages/SearchPage.tsx +182 -38
- package/src/ui/shared/AdminBreadcrumb.tsx +29 -0
- package/src/ui/shared/CollectionsSidebar.tsx +239 -4
- package/src/ui/shared/MediaGallery.tsx +475 -41
- package/src/ui/shared/PostFooter.tsx +204 -0
- package/src/ui/shared/StarRating.tsx +27 -0
- package/src/ui/shared/__tests__/format-chars.test.ts +35 -0
- package/src/ui/shared/index.ts +0 -1
- package/src/db/migrations/0000_square_wallflower.sql +0 -118
- package/src/db/migrations/0001_add_search_fts.sql +0 -34
- package/src/db/migrations/0002_add_media_attachments.sql +0 -3
- package/src/db/migrations/0003_add_navigation_links.sql +0 -8
- package/src/db/migrations/0004_add_storage_provider.sql +0 -3
- package/src/db/migrations/0005_v2_schema_migration.sql +0 -268
- package/src/db/migrations/0006_rename_slug_to_path.sql +0 -5
- package/src/db/migrations/0007_post_collections_m2m.sql +0 -94
- package/src/db/migrations/0008_add_collection_dividers.sql +0 -8
- package/src/db/migrations/0009_drop_collection_show_divider.sql +0 -2
- package/src/db/migrations/0010_add_performance_indexes.sql +0 -16
- package/src/db/migrations/0011_add_path_registry.sql +0 -23
- package/src/db/migrations/meta/0003_snapshot.json +0 -821
- package/src/lib/__tests__/sqid.test.ts +0 -65
- package/src/lib/collections-reorder.ts +0 -28
- package/src/lib/compose-bridge.ts +0 -280
- package/src/lib/media-upload.ts +0 -148
- package/src/lib/sqid.ts +0 -79
- package/src/routes/api/__tests__/pages.test.ts +0 -218
- package/src/routes/api/pages.ts +0 -73
- package/src/routes/dash/__tests__/pages.test.ts +0 -226
- package/src/routes/dash/appearance.tsx +0 -240
- package/src/routes/dash/collections.tsx +0 -211
- package/src/routes/dash/index.tsx +0 -103
- package/src/routes/dash/media.tsx +0 -132
- package/src/routes/dash/pages.tsx +0 -239
- package/src/routes/dash/posts.tsx +0 -334
- package/src/routes/dash/redirects.tsx +0 -257
- package/src/routes/pages/post.tsx +0 -59
- package/src/services/__tests__/page.test.ts +0 -298
- package/src/services/__tests__/path-registry.test.ts +0 -165
- package/src/services/__tests__/redirect.test.ts +0 -159
- package/src/services/page.ts +0 -203
- package/src/services/path-registry.ts +0 -160
- package/src/services/redirect.ts +0 -97
- package/src/types/sortablejs.d.ts +0 -29
- package/src/ui/components/__tests__/jant-compose-dialog.test.ts +0 -512
- package/src/ui/components/__tests__/jant-compose-editor.test.ts +0 -272
- package/src/ui/components/compose-types.ts +0 -75
- package/src/ui/components/jant-collection-form.ts +0 -512
- package/src/ui/components/jant-compose-dialog.ts +0 -495
- package/src/ui/components/jant-compose-editor.ts +0 -814
- package/src/ui/dash/PageForm.tsx +0 -185
- package/src/ui/dash/PostList.tsx +0 -95
- package/src/ui/dash/appearance/AppearanceNav.tsx +0 -60
- package/src/ui/dash/collections/CollectionForm.tsx +0 -166
- package/src/ui/dash/collections/CollectionsListContent.tsx +0 -146
- package/src/ui/dash/collections/IconPickerGrid.tsx +0 -50
- package/src/ui/dash/collections/ViewCollectionContent.tsx +0 -103
- package/src/ui/dash/media/MediaListContent.tsx +0 -201
- package/src/ui/dash/media/ViewMediaContent.tsx +0 -208
- package/src/ui/dash/pages/PagesContent.tsx +0 -74
- package/src/ui/dash/posts/PostForm.tsx +0 -248
- package/src/ui/dash/settings/SettingsNav.tsx +0 -52
- package/src/ui/layouts/DashLayout.tsx +0 -165
- package/src/ui/pages/SinglePage.tsx +0 -23
- package/src/ui/shared/ThreadView.tsx +0 -136
- /package/src/{ui → client}/components/settings-types.ts +0 -0
package/src/types/bindings.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface Bindings {
|
|
|
12
12
|
IMAGE_TRANSFORM_URL?: string;
|
|
13
13
|
DEMO_EMAIL?: string;
|
|
14
14
|
DEMO_PASSWORD?: string;
|
|
15
|
+
DEV_API_TOKEN?: string;
|
|
15
16
|
// Timeline
|
|
16
17
|
PAGE_SIZE?: string;
|
|
17
18
|
// Site configuration (optional - can be overridden in DB)
|
|
@@ -27,6 +28,13 @@ export interface Bindings {
|
|
|
27
28
|
S3_SECRET_ACCESS_KEY?: string;
|
|
28
29
|
S3_REGION?: string;
|
|
29
30
|
S3_PUBLIC_URL?: string;
|
|
31
|
+
// Upload
|
|
32
|
+
UPLOAD_MAX_FILE_SIZE_MB?: string;
|
|
33
|
+
// Summary extraction
|
|
34
|
+
SUMMARY_MAX_PARAGRAPHS?: string;
|
|
35
|
+
SUMMARY_MAX_CHARS?: string;
|
|
36
|
+
// Slug generation
|
|
37
|
+
SLUG_ID_LENGTH?: string;
|
|
30
38
|
// RSS feed
|
|
31
39
|
RSS_FEED_LIMIT?: string;
|
|
32
40
|
}
|
package/src/types/config.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* - envOnly: true -> Environment-only (ENV > Default)
|
|
16
16
|
*/
|
|
17
17
|
export const CONFIG_FIELDS = {
|
|
18
|
-
// User-configurable (can be modified in
|
|
18
|
+
// User-configurable (can be modified in settings)
|
|
19
19
|
SITE_NAME: {
|
|
20
20
|
defaultValue: "Jant",
|
|
21
21
|
envOnly: false,
|
|
@@ -33,7 +33,7 @@ export const CONFIG_FIELDS = {
|
|
|
33
33
|
envOnly: false,
|
|
34
34
|
},
|
|
35
35
|
HEADER_NAV_MAX_VISIBLE: {
|
|
36
|
-
defaultValue: "
|
|
36
|
+
defaultValue: "2",
|
|
37
37
|
envOnly: false,
|
|
38
38
|
},
|
|
39
39
|
|
|
@@ -98,8 +98,24 @@ export const CONFIG_FIELDS = {
|
|
|
98
98
|
defaultValue: "",
|
|
99
99
|
envOnly: true,
|
|
100
100
|
},
|
|
101
|
+
UPLOAD_MAX_FILE_SIZE_MB: {
|
|
102
|
+
defaultValue: "500",
|
|
103
|
+
envOnly: true,
|
|
104
|
+
},
|
|
105
|
+
SUMMARY_MAX_PARAGRAPHS: {
|
|
106
|
+
defaultValue: "5",
|
|
107
|
+
envOnly: true,
|
|
108
|
+
},
|
|
109
|
+
SUMMARY_MAX_CHARS: {
|
|
110
|
+
defaultValue: "500",
|
|
111
|
+
envOnly: true,
|
|
112
|
+
},
|
|
113
|
+
SLUG_ID_LENGTH: {
|
|
114
|
+
defaultValue: "5",
|
|
115
|
+
envOnly: true,
|
|
116
|
+
},
|
|
101
117
|
|
|
102
|
-
// Internal settings (DB-only, not configurable via env or
|
|
118
|
+
// Internal settings (DB-only, not configurable via env or settings UI)
|
|
103
119
|
THEME: {
|
|
104
120
|
defaultValue: "",
|
|
105
121
|
envOnly: false,
|
|
@@ -195,10 +211,24 @@ export interface AppConfig {
|
|
|
195
211
|
s3PublicUrl: string;
|
|
196
212
|
imageTransformUrl: string;
|
|
197
213
|
|
|
214
|
+
// Upload (ENV only, parsed to number)
|
|
215
|
+
/** Max upload file size in MB. Defaults to 500. */
|
|
216
|
+
uploadMaxFileSize: number;
|
|
217
|
+
|
|
218
|
+
// Summary extraction (ENV only)
|
|
219
|
+
/** Max paragraphs to include in auto-extracted summary. Defaults to 5. */
|
|
220
|
+
summaryMaxParagraphs: number;
|
|
221
|
+
/** Max characters to include in auto-extracted summary. Defaults to 500. */
|
|
222
|
+
summaryMaxChars: number;
|
|
223
|
+
|
|
198
224
|
// Pagination/Feed (ENV only, parsed to number)
|
|
199
225
|
pageSize: number;
|
|
200
226
|
rssFeedLimit: number;
|
|
201
227
|
|
|
228
|
+
// Slug (ENV only)
|
|
229
|
+
/** Length of random IDs used in auto-generated slugs. Defaults to 5. */
|
|
230
|
+
slugIdLength: number;
|
|
231
|
+
|
|
202
232
|
// Demo (ENV only)
|
|
203
233
|
demoEmail: string;
|
|
204
234
|
demoPassword: string;
|
|
@@ -216,7 +246,7 @@ export interface AppConfig {
|
|
|
216
246
|
siteAvatarUrl: string;
|
|
217
247
|
faviconVersion: string;
|
|
218
248
|
|
|
219
|
-
//
|
|
249
|
+
// Settings form placeholders (ENV > Default, without DB)
|
|
220
250
|
fallbacks: {
|
|
221
251
|
siteName: string;
|
|
222
252
|
siteDescription: string;
|
package/src/types/constants.ts
CHANGED
|
@@ -8,6 +8,9 @@ export type Format = (typeof FORMATS)[number];
|
|
|
8
8
|
export const STATUSES = ["draft", "published"] as const;
|
|
9
9
|
export type Status = (typeof STATUSES)[number];
|
|
10
10
|
|
|
11
|
+
export const VISIBILITIES = ["public", "unlisted", "private"] as const;
|
|
12
|
+
export type Visibility = (typeof VISIBILITIES)[number];
|
|
13
|
+
|
|
11
14
|
export const SORT_ORDERS = [
|
|
12
15
|
"newest",
|
|
13
16
|
"oldest",
|
|
@@ -16,12 +19,12 @@ export const SORT_ORDERS = [
|
|
|
16
19
|
] as const;
|
|
17
20
|
export type SortOrder = (typeof SORT_ORDERS)[number];
|
|
18
21
|
|
|
19
|
-
export const NAV_ITEM_TYPES = ["
|
|
22
|
+
export const NAV_ITEM_TYPES = ["link", "system"] as const;
|
|
20
23
|
export type NavItemType = (typeof NAV_ITEM_TYPES)[number];
|
|
21
24
|
|
|
22
25
|
export const SYSTEM_NAV_KEYS = {
|
|
23
26
|
rss: { defaultLabel: "RSS", url: "/feed" },
|
|
24
|
-
|
|
27
|
+
settings: { defaultLabel: "Settings", url: "/settings" },
|
|
25
28
|
collections: { defaultLabel: "Collections", url: "/c" },
|
|
26
29
|
archive: { defaultLabel: "Archive", url: "/archive" },
|
|
27
30
|
} as const;
|
|
@@ -30,5 +33,17 @@ export type SystemNavKey = keyof typeof SYSTEM_NAV_KEYS;
|
|
|
30
33
|
export const MAX_MEDIA_ATTACHMENTS = 20;
|
|
31
34
|
export const MAX_PINNED_POSTS = 3;
|
|
32
35
|
|
|
36
|
+
export const MEDIA_KINDS = [
|
|
37
|
+
"image",
|
|
38
|
+
"video",
|
|
39
|
+
"audio",
|
|
40
|
+
"text",
|
|
41
|
+
"document",
|
|
42
|
+
] as const;
|
|
43
|
+
export type MediaKind = (typeof MEDIA_KINDS)[number];
|
|
44
|
+
|
|
33
45
|
export const STORAGE_DRIVERS = ["r2", "s3"] as const;
|
|
34
46
|
export type StorageDriver = (typeof STORAGE_DRIVERS)[number];
|
|
47
|
+
|
|
48
|
+
export const PATH_KINDS = ["slug", "alias", "redirect"] as const;
|
|
49
|
+
export type PathKind = (typeof PATH_KINDS)[number];
|
package/src/types/entities.ts
CHANGED
|
@@ -2,43 +2,44 @@
|
|
|
2
2
|
* Entity Types (database-level models)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
Format,
|
|
7
|
+
Status,
|
|
8
|
+
Visibility,
|
|
9
|
+
SortOrder,
|
|
10
|
+
NavItemType,
|
|
11
|
+
MediaKind,
|
|
12
|
+
PathKind,
|
|
13
|
+
} from "./constants.js";
|
|
6
14
|
|
|
7
15
|
export interface Post {
|
|
8
|
-
id:
|
|
16
|
+
id: string;
|
|
9
17
|
format: Format;
|
|
10
18
|
status: Status;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
visibility: Visibility;
|
|
20
|
+
pinnedAt: number | null;
|
|
21
|
+
featuredAt: number | null;
|
|
22
|
+
slug: string;
|
|
14
23
|
title: string | null;
|
|
15
24
|
url: string | null;
|
|
16
25
|
body: string | null;
|
|
17
26
|
bodyHtml: string | null;
|
|
27
|
+
bodyText: string | null;
|
|
18
28
|
quoteText: string | null;
|
|
29
|
+
summary: string | null;
|
|
19
30
|
rating: number | null;
|
|
20
|
-
replyToId:
|
|
21
|
-
threadId:
|
|
31
|
+
replyToId: string | null;
|
|
32
|
+
threadId: string;
|
|
22
33
|
deletedAt: number | null;
|
|
23
|
-
publishedAt: number;
|
|
24
|
-
|
|
25
|
-
updatedAt: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface Page {
|
|
29
|
-
id: number;
|
|
30
|
-
slug: string;
|
|
31
|
-
title: string | null;
|
|
32
|
-
body: string | null;
|
|
33
|
-
bodyHtml: string | null;
|
|
34
|
-
status: Status;
|
|
34
|
+
publishedAt: number | null;
|
|
35
|
+
lastActivityAt: number;
|
|
35
36
|
createdAt: number;
|
|
36
37
|
updatedAt: number;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export interface Media {
|
|
40
41
|
id: string; // UUIDv7
|
|
41
|
-
postId:
|
|
42
|
+
postId: string | null;
|
|
42
43
|
filename: string;
|
|
43
44
|
originalName: string;
|
|
44
45
|
mimeType: string;
|
|
@@ -48,9 +49,15 @@ export interface Media {
|
|
|
48
49
|
width: number | null;
|
|
49
50
|
height: number | null;
|
|
50
51
|
alt: string | null;
|
|
51
|
-
position:
|
|
52
|
+
position: string;
|
|
52
53
|
blurhash: string | null;
|
|
54
|
+
waveform: string | null;
|
|
55
|
+
posterKey: string | null;
|
|
56
|
+
summary: string | null;
|
|
57
|
+
chars: number | null;
|
|
58
|
+
mediaKind: MediaKind;
|
|
53
59
|
createdAt: number;
|
|
60
|
+
updatedAt: number;
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
export interface MediaAttachment {
|
|
@@ -59,10 +66,16 @@ export interface MediaAttachment {
|
|
|
59
66
|
previewUrl: string;
|
|
60
67
|
alt: string | null;
|
|
61
68
|
blurhash: string | null;
|
|
69
|
+
waveform: string | null;
|
|
70
|
+
posterUrl: string | null;
|
|
62
71
|
width: number | null;
|
|
63
72
|
height: number | null;
|
|
64
|
-
position:
|
|
73
|
+
position: string;
|
|
65
74
|
mimeType: string;
|
|
75
|
+
originalName: string;
|
|
76
|
+
size: number;
|
|
77
|
+
summary: string | null;
|
|
78
|
+
chars: number | null;
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
export interface PostWithMedia extends Post {
|
|
@@ -70,46 +83,62 @@ export interface PostWithMedia extends Post {
|
|
|
70
83
|
}
|
|
71
84
|
|
|
72
85
|
export interface Collection {
|
|
73
|
-
id:
|
|
86
|
+
id: string;
|
|
74
87
|
slug: string;
|
|
75
88
|
title: string;
|
|
76
89
|
description: string | null;
|
|
77
90
|
icon: string | null;
|
|
78
91
|
sortOrder: SortOrder;
|
|
79
|
-
position: number;
|
|
80
92
|
createdAt: number;
|
|
81
93
|
updatedAt: number;
|
|
82
94
|
}
|
|
83
95
|
|
|
84
|
-
export
|
|
85
|
-
|
|
86
|
-
|
|
96
|
+
export type SidebarItemType = "collection" | "divider";
|
|
97
|
+
|
|
98
|
+
export interface SidebarItem {
|
|
99
|
+
id: string;
|
|
100
|
+
type: SidebarItemType;
|
|
101
|
+
collectionId: string | null;
|
|
102
|
+
position: string;
|
|
87
103
|
createdAt: number;
|
|
88
104
|
updatedAt: number;
|
|
89
105
|
}
|
|
90
106
|
|
|
91
107
|
export interface PostCollection {
|
|
92
|
-
postId:
|
|
93
|
-
collectionId:
|
|
108
|
+
postId: string;
|
|
109
|
+
collectionId: string;
|
|
94
110
|
}
|
|
95
111
|
|
|
96
112
|
export interface NavItem {
|
|
97
|
-
id:
|
|
113
|
+
id: string;
|
|
98
114
|
type: NavItemType;
|
|
99
115
|
label: string;
|
|
100
116
|
url: string;
|
|
101
|
-
|
|
102
|
-
position: number;
|
|
117
|
+
position: string;
|
|
103
118
|
createdAt: number;
|
|
104
119
|
updatedAt: number;
|
|
105
120
|
}
|
|
106
121
|
|
|
107
|
-
export interface
|
|
108
|
-
id:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
122
|
+
export interface CustomUrl {
|
|
123
|
+
id: string;
|
|
124
|
+
path: string;
|
|
125
|
+
targetType: "post" | "collection" | "redirect";
|
|
126
|
+
targetId: string | null;
|
|
127
|
+
toPath: string | null;
|
|
128
|
+
redirectType: 301 | 302 | null;
|
|
129
|
+
createdAt: number;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface PathRecord {
|
|
133
|
+
id: string;
|
|
134
|
+
path: string;
|
|
135
|
+
kind: PathKind;
|
|
136
|
+
postId: string | null;
|
|
137
|
+
collectionId: string | null;
|
|
138
|
+
redirectToPath: string | null;
|
|
139
|
+
redirectType: 301 | 302 | null;
|
|
112
140
|
createdAt: number;
|
|
141
|
+
updatedAt: number;
|
|
113
142
|
}
|
|
114
143
|
|
|
115
144
|
export interface Setting {
|
|
@@ -117,3 +146,20 @@ export interface Setting {
|
|
|
117
146
|
value: string;
|
|
118
147
|
updatedAt: number;
|
|
119
148
|
}
|
|
149
|
+
|
|
150
|
+
export interface ApiToken {
|
|
151
|
+
id: string;
|
|
152
|
+
name: string;
|
|
153
|
+
prefix: string;
|
|
154
|
+
lastUsedAt: number | null;
|
|
155
|
+
createdAt: number;
|
|
156
|
+
updatedAt: number;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Latest-reply context for a thread root, used in timeline display */
|
|
160
|
+
export interface ThreadTimelineContext {
|
|
161
|
+
latestReply: Post;
|
|
162
|
+
/** Parent of latestReply, only if it's not the root */
|
|
163
|
+
parentReply: Post | null;
|
|
164
|
+
totalReplyCount: number;
|
|
165
|
+
}
|
package/src/types/operations.ts
CHANGED
|
@@ -2,21 +2,30 @@
|
|
|
2
2
|
* Operation Types (create/update DTOs)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
Format,
|
|
7
|
+
Status,
|
|
8
|
+
Visibility,
|
|
9
|
+
SortOrder,
|
|
10
|
+
NavItemType,
|
|
11
|
+
} from "./constants.js";
|
|
6
12
|
|
|
7
13
|
export interface CreatePost {
|
|
8
14
|
format: Format;
|
|
9
15
|
status?: Status;
|
|
10
|
-
|
|
16
|
+
visibility?: Visibility;
|
|
11
17
|
pinned?: boolean;
|
|
18
|
+
featured?: boolean;
|
|
19
|
+
slug?: string;
|
|
12
20
|
path?: string;
|
|
13
21
|
title?: string;
|
|
14
22
|
url?: string;
|
|
15
23
|
body?: string;
|
|
24
|
+
bodyMarkdown?: string;
|
|
16
25
|
quoteText?: string;
|
|
17
26
|
rating?: number;
|
|
18
|
-
collectionIds?:
|
|
19
|
-
replyToId?:
|
|
27
|
+
collectionIds?: string[];
|
|
28
|
+
replyToId?: string;
|
|
20
29
|
publishedAt?: number;
|
|
21
30
|
mediaIds?: string[];
|
|
22
31
|
}
|
|
@@ -24,47 +33,33 @@ export interface CreatePost {
|
|
|
24
33
|
export interface UpdatePost {
|
|
25
34
|
format?: Format;
|
|
26
35
|
status?: Status;
|
|
27
|
-
|
|
36
|
+
visibility?: Visibility;
|
|
28
37
|
pinned?: boolean;
|
|
29
|
-
|
|
38
|
+
featured?: boolean;
|
|
39
|
+
slug?: string;
|
|
30
40
|
title?: string | null;
|
|
31
41
|
url?: string | null;
|
|
32
42
|
body?: string | null;
|
|
43
|
+
bodyMarkdown?: string | null;
|
|
33
44
|
quoteText?: string | null;
|
|
34
45
|
rating?: number | null;
|
|
35
|
-
collectionIds?:
|
|
46
|
+
collectionIds?: string[];
|
|
36
47
|
publishedAt?: number;
|
|
37
48
|
mediaIds?: string[];
|
|
38
49
|
}
|
|
39
50
|
|
|
40
|
-
export interface CreatePage {
|
|
41
|
-
slug: string;
|
|
42
|
-
title?: string;
|
|
43
|
-
body?: string;
|
|
44
|
-
status?: Status;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface UpdatePage {
|
|
48
|
-
slug?: string;
|
|
49
|
-
title?: string | null;
|
|
50
|
-
body?: string | null;
|
|
51
|
-
status?: Status;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
51
|
export interface CreateNavItem {
|
|
55
52
|
type: NavItemType;
|
|
56
53
|
label: string;
|
|
57
54
|
url: string;
|
|
58
|
-
|
|
59
|
-
position?: number;
|
|
55
|
+
position?: string;
|
|
60
56
|
}
|
|
61
57
|
|
|
62
58
|
export interface UpdateNavItem {
|
|
63
59
|
type?: NavItemType;
|
|
64
60
|
label?: string;
|
|
65
61
|
url?: string;
|
|
66
|
-
|
|
67
|
-
position?: number;
|
|
62
|
+
position?: string;
|
|
68
63
|
}
|
|
69
64
|
|
|
70
65
|
export interface CreateCollection {
|
|
@@ -73,7 +68,6 @@ export interface CreateCollection {
|
|
|
73
68
|
description?: string;
|
|
74
69
|
icon?: string;
|
|
75
70
|
sortOrder?: SortOrder;
|
|
76
|
-
position?: number;
|
|
77
71
|
}
|
|
78
72
|
|
|
79
73
|
export interface UpdateCollection {
|
|
@@ -82,5 +76,4 @@ export interface UpdateCollection {
|
|
|
82
76
|
description?: string | null;
|
|
83
77
|
icon?: string | null;
|
|
84
78
|
sortOrder?: SortOrder;
|
|
85
|
-
position?: number;
|
|
86
79
|
}
|
package/src/types/props.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
* Page-Level Props & Feed Data Types
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { Format } from "./constants.js";
|
|
5
|
+
import type { Format, MediaKind } from "./constants.js";
|
|
6
6
|
import type { Collection } from "./entities.js";
|
|
7
7
|
import type {
|
|
8
8
|
PostView,
|
|
9
|
-
PageView,
|
|
10
9
|
TimelineItemView,
|
|
11
10
|
SearchResultView,
|
|
12
11
|
ArchiveGroup,
|
|
@@ -19,7 +18,6 @@ import type {
|
|
|
19
18
|
/** Props for the home page component */
|
|
20
19
|
export interface HomePageProps {
|
|
21
20
|
items: TimelineItemView[];
|
|
22
|
-
pinnedItems: PostView[];
|
|
23
21
|
currentPage: number;
|
|
24
22
|
totalPages: number;
|
|
25
23
|
}
|
|
@@ -27,11 +25,7 @@ export interface HomePageProps {
|
|
|
27
25
|
/** Props for the single post page component */
|
|
28
26
|
export interface PostPageProps {
|
|
29
27
|
post: PostView;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/** Props for the custom page component */
|
|
33
|
-
export interface SinglePageProps {
|
|
34
|
-
page: PageView;
|
|
28
|
+
threadPosts?: PostView[];
|
|
35
29
|
}
|
|
36
30
|
|
|
37
31
|
/** Props for the featured page component */
|
|
@@ -39,13 +33,35 @@ export interface FeaturedPageProps {
|
|
|
39
33
|
items: TimelineItemView[];
|
|
40
34
|
}
|
|
41
35
|
|
|
36
|
+
/** Visibility filter values for the archive page (includes "featured" as a virtual value). */
|
|
37
|
+
export type ArchiveVisibility = "public" | "unlisted" | "private" | "featured";
|
|
38
|
+
|
|
39
|
+
/** View mode for the archive page. */
|
|
40
|
+
export type ArchiveView = "grid" | "list";
|
|
41
|
+
|
|
42
|
+
/** Filters currently active on the archive page */
|
|
43
|
+
export interface ArchiveFilters {
|
|
44
|
+
year?: number;
|
|
45
|
+
collectionSlug?: string;
|
|
46
|
+
collectionTitle?: string;
|
|
47
|
+
collectionIcon?: string | null;
|
|
48
|
+
format?: Format;
|
|
49
|
+
mediaKinds?: MediaKind[];
|
|
50
|
+
hasMedia?: boolean;
|
|
51
|
+
hasTitle?: boolean;
|
|
52
|
+
visibility?: ArchiveVisibility;
|
|
53
|
+
view?: ArchiveView;
|
|
54
|
+
}
|
|
55
|
+
|
|
42
56
|
/** Props for the archive page component */
|
|
43
57
|
export interface ArchivePageProps {
|
|
44
58
|
groups: ArchiveGroup[];
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
currentPage: number;
|
|
60
|
+
totalPages: number;
|
|
61
|
+
filters: ArchiveFilters;
|
|
62
|
+
availableYears: number[];
|
|
63
|
+
availableCollections: { slug: string; title: string; icon: string | null }[];
|
|
64
|
+
isAuthenticated: boolean;
|
|
49
65
|
}
|
|
50
66
|
|
|
51
67
|
/** Props for the search page component */
|
|
@@ -60,9 +76,9 @@ export interface SearchPageProps {
|
|
|
60
76
|
/** Props for the single collection page component */
|
|
61
77
|
export interface CollectionPageProps {
|
|
62
78
|
collection: Collection;
|
|
63
|
-
|
|
79
|
+
items: TimelineItemView[];
|
|
64
80
|
hasMore: boolean;
|
|
65
|
-
nextCursor?:
|
|
81
|
+
nextCursor?: string;
|
|
66
82
|
}
|
|
67
83
|
|
|
68
84
|
/** Props for the collections list page component */
|
|
@@ -87,23 +103,42 @@ export interface FeedData {
|
|
|
87
103
|
export interface SitemapData {
|
|
88
104
|
siteUrl: string;
|
|
89
105
|
posts: PostView[];
|
|
90
|
-
pages: PageView[];
|
|
91
106
|
}
|
|
92
107
|
|
|
93
108
|
// =============================================================================
|
|
94
109
|
// Timeline Types
|
|
95
110
|
// =============================================================================
|
|
96
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Display mode for timeline cards.
|
|
114
|
+
* - `compact` — condensed view for constrained contexts
|
|
115
|
+
* - `feed` — standard timeline card (default)
|
|
116
|
+
* - `detail` — full single-post page view
|
|
117
|
+
*/
|
|
118
|
+
export type CardMode = "compact" | "feed" | "detail";
|
|
119
|
+
|
|
120
|
+
export interface PostFooterDisplayOptions {
|
|
121
|
+
hideActions?: boolean;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface TimelineCardDisplayOptions {
|
|
125
|
+
hideStatusBadges?: boolean;
|
|
126
|
+
hideRating?: boolean;
|
|
127
|
+
footer?: PostFooterDisplayOptions;
|
|
128
|
+
}
|
|
129
|
+
|
|
97
130
|
/** Props for per-type timeline cards */
|
|
98
131
|
export interface TimelineCardProps {
|
|
99
132
|
post: PostView;
|
|
100
|
-
|
|
133
|
+
mode?: CardMode;
|
|
134
|
+
display?: TimelineCardDisplayOptions;
|
|
101
135
|
}
|
|
102
136
|
|
|
103
137
|
/** Props for thread inline preview */
|
|
104
138
|
export interface ThreadPreviewProps {
|
|
105
139
|
rootPost: PostView;
|
|
106
|
-
|
|
140
|
+
latestReply: PostView;
|
|
141
|
+
parentReply?: PostView;
|
|
107
142
|
totalReplyCount: number;
|
|
108
143
|
}
|
|
109
144
|
|