@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.
Files changed (307) hide show
  1. package/bin/commands/export.js +1 -1
  2. package/bin/commands/import-site.js +529 -0
  3. package/bin/commands/reset-password.js +3 -2
  4. package/dist/client/assets/heic-to-DIRPI3VF.js +1 -0
  5. package/dist/client/assets/module-RjUF93sV.js +716 -0
  6. package/dist/client/assets/native-48B9X9Wg.js +1 -0
  7. package/dist/client/assets/url-FWFqPJPb.js +1 -0
  8. package/dist/client/client.css +1 -1
  9. package/dist/client/client.js +4564 -3013
  10. package/dist/index.js +12885 -8161
  11. package/package.json +23 -6
  12. package/src/__tests__/helpers/app.ts +10 -10
  13. package/src/__tests__/helpers/db.ts +91 -87
  14. package/src/app.tsx +157 -31
  15. package/src/auth.ts +20 -2
  16. package/src/client/archive-nav.js +187 -0
  17. package/src/client/audio-player.ts +478 -0
  18. package/src/client/audio-processor.ts +84 -0
  19. package/src/{lib → client}/avatar-upload.ts +4 -3
  20. package/src/{lib → client}/collection-form-bridge.ts +2 -2
  21. package/src/{ui → client}/components/__tests__/jant-collection-form.test.ts +26 -9
  22. package/src/client/components/__tests__/jant-compose-dialog.test.ts +1140 -0
  23. package/src/client/components/__tests__/jant-compose-editor.test.ts +504 -0
  24. package/src/{ui → client}/components/__tests__/jant-post-form.test.ts +37 -17
  25. package/src/{ui → client}/components/__tests__/jant-settings-avatar.test.ts +2 -2
  26. package/src/{ui → client}/components/__tests__/jant-settings-general.test.ts +3 -3
  27. package/src/client/components/collection-sidebar-types.ts +43 -0
  28. package/src/{ui → client}/components/collection-types.ts +3 -4
  29. package/src/client/components/compose-types.ts +174 -0
  30. package/src/client/components/jant-collection-form.ts +667 -0
  31. package/src/client/components/jant-collection-sidebar.ts +805 -0
  32. package/src/client/components/jant-compose-dialog.ts +2161 -0
  33. package/src/client/components/jant-compose-editor.ts +1813 -0
  34. package/src/client/components/jant-compose-fullscreen.ts +283 -0
  35. package/src/client/components/jant-media-lightbox.ts +259 -0
  36. package/src/{ui → client}/components/jant-nav-manager.ts +97 -298
  37. package/src/{ui → client}/components/jant-post-form.ts +141 -12
  38. package/src/client/components/jant-post-menu.ts +1019 -0
  39. package/src/{ui → client}/components/jant-settings-avatar.ts +3 -3
  40. package/src/{ui → client}/components/jant-settings-general.ts +38 -4
  41. package/src/client/components/jant-text-preview.ts +232 -0
  42. package/src/{ui → client}/components/nav-manager-types.ts +6 -18
  43. package/src/{ui → client}/components/post-form-template.ts +137 -38
  44. package/src/{ui → client}/components/post-form-types.ts +15 -4
  45. package/src/client/compose-bridge.ts +583 -0
  46. package/src/{lib → client}/image-processor.ts +26 -8
  47. package/src/client/lazy-slugify.ts +51 -0
  48. package/src/client/media-metadata.ts +247 -0
  49. package/src/client/multipart-upload.ts +160 -0
  50. package/src/{lib → client}/nav-manager-bridge.ts +1 -1
  51. package/src/{lib → client}/post-form-bridge.ts +53 -2
  52. package/src/{lib → client}/settings-bridge.ts +3 -15
  53. package/src/client/thread-context.ts +140 -0
  54. package/src/client/tiptap/bubble-menu.ts +205 -0
  55. package/src/client/tiptap/create-editor.ts +86 -0
  56. package/src/client/tiptap/exitable-marks.ts +73 -0
  57. package/src/client/tiptap/extensions.ts +65 -0
  58. package/src/client/tiptap/image-node.ts +482 -0
  59. package/src/client/tiptap/link-toolbar.ts +371 -0
  60. package/src/client/tiptap/more-break.ts +50 -0
  61. package/src/client/tiptap/paste-image.ts +129 -0
  62. package/src/client/tiptap/slash-commands.ts +438 -0
  63. package/src/{lib → client}/toast.ts +101 -3
  64. package/src/client/types/sortablejs.d.ts +44 -0
  65. package/src/client/upload-with-metadata.ts +54 -0
  66. package/src/client/video-processor.ts +207 -0
  67. package/src/client.ts +27 -17
  68. package/src/db/__tests__/migrations.test.ts +118 -0
  69. package/src/db/index.ts +52 -0
  70. package/src/db/migrations/0000_baseline.sql +269 -0
  71. package/src/db/migrations/0001_fts_setup.sql +31 -0
  72. package/src/db/migrations/meta/0000_snapshot.json +703 -119
  73. package/src/db/migrations/meta/0001_snapshot.json +1337 -0
  74. package/src/db/migrations/meta/_journal.json +4 -39
  75. package/src/db/schema.ts +409 -140
  76. package/src/i18n/__tests__/detect.test.ts +115 -0
  77. package/src/i18n/context.tsx +2 -2
  78. package/src/i18n/detect.ts +85 -1
  79. package/src/i18n/i18n.ts +1 -1
  80. package/src/i18n/index.ts +2 -1
  81. package/src/i18n/locales/en.po +783 -1087
  82. package/src/i18n/locales/en.ts +1 -1
  83. package/src/i18n/locales/zh-Hans.po +867 -812
  84. package/src/i18n/locales/zh-Hans.ts +1 -1
  85. package/src/i18n/locales/zh-Hant.po +878 -823
  86. package/src/i18n/locales/zh-Hant.ts +1 -1
  87. package/src/i18n/middleware.ts +6 -0
  88. package/src/index.ts +5 -7
  89. package/src/lib/__tests__/blurhash-placeholder.test.ts +75 -0
  90. package/src/lib/__tests__/constants.test.ts +0 -1
  91. package/src/lib/__tests__/markdown-to-tiptap.test.ts +358 -0
  92. package/src/lib/__tests__/nanoid.test.ts +26 -0
  93. package/src/lib/__tests__/resolve-config.test.ts +2 -2
  94. package/src/lib/__tests__/schemas.test.ts +186 -65
  95. package/src/lib/__tests__/slug.test.ts +126 -0
  96. package/src/lib/__tests__/sse.test.ts +6 -6
  97. package/src/lib/__tests__/summary.test.ts +264 -0
  98. package/src/lib/__tests__/theme.test.ts +1 -1
  99. package/src/lib/__tests__/timeline.test.ts +33 -30
  100. package/src/lib/__tests__/tiptap-to-markdown.test.ts +346 -0
  101. package/src/lib/__tests__/url.test.ts +2 -2
  102. package/src/lib/__tests__/view.test.ts +140 -65
  103. package/src/lib/blurhash-placeholder.ts +102 -0
  104. package/src/lib/constants.ts +3 -1
  105. package/src/lib/emoji-catalog.ts +963 -0
  106. package/src/lib/errors.ts +11 -8
  107. package/src/lib/feed.ts +77 -31
  108. package/src/lib/html.ts +2 -1
  109. package/src/lib/icon-catalog.ts +5033 -1
  110. package/src/lib/icons.ts +3 -2
  111. package/src/lib/index.ts +0 -1
  112. package/src/lib/markdown-to-tiptap.ts +286 -0
  113. package/src/lib/media-helpers.ts +22 -12
  114. package/src/lib/nanoid.ts +29 -0
  115. package/src/lib/navigation.ts +1 -1
  116. package/src/lib/render.tsx +24 -5
  117. package/src/lib/resolve-config.ts +13 -2
  118. package/src/lib/schemas.ts +226 -58
  119. package/src/lib/search-snippet.ts +34 -0
  120. package/src/lib/slug.ts +96 -0
  121. package/src/lib/sse.ts +6 -6
  122. package/src/lib/storage.ts +115 -7
  123. package/src/lib/summary.ts +158 -0
  124. package/src/lib/theme.ts +11 -8
  125. package/src/lib/timeline.ts +76 -34
  126. package/src/lib/tiptap-render.ts +191 -0
  127. package/src/lib/tiptap-to-markdown.ts +305 -0
  128. package/src/lib/upload.ts +263 -14
  129. package/src/lib/url.ts +37 -22
  130. package/src/lib/view.ts +236 -55
  131. package/src/middleware/__tests__/auth.test.ts +191 -11
  132. package/src/middleware/__tests__/onboarding.test.ts +12 -10
  133. package/src/middleware/auth.ts +63 -9
  134. package/src/middleware/error-handler.ts +3 -3
  135. package/src/middleware/onboarding.ts +1 -1
  136. package/src/middleware/secure-headers.ts +40 -0
  137. package/src/preset.css +83 -2
  138. package/src/routes/__tests__/compose.test.ts +17 -24
  139. package/src/routes/api/__tests__/collections.test.ts +109 -61
  140. package/src/routes/api/__tests__/nav-items.test.ts +46 -29
  141. package/src/routes/api/__tests__/posts.test.ts +132 -68
  142. package/src/routes/api/__tests__/search.test.ts +15 -2
  143. package/src/routes/api/__tests__/upload-multipart.test.ts +534 -0
  144. package/src/routes/api/collections.ts +57 -31
  145. package/src/routes/api/custom-urls.ts +80 -0
  146. package/src/routes/api/export.ts +31 -0
  147. package/src/routes/api/nav-items.ts +23 -19
  148. package/src/routes/api/posts.ts +81 -62
  149. package/src/routes/api/search.ts +3 -4
  150. package/src/routes/api/upload-multipart.ts +245 -0
  151. package/src/routes/api/upload.ts +92 -24
  152. package/src/routes/auth/__tests__/setup.test.ts +20 -60
  153. package/src/routes/auth/reset.tsx +5 -4
  154. package/src/routes/auth/setup.tsx +39 -31
  155. package/src/routes/auth/signin.tsx +13 -14
  156. package/src/routes/compose.tsx +27 -63
  157. package/src/routes/dash/__tests__/settings-avatar.test.ts +44 -9
  158. package/src/routes/dash/custom-urls.tsx +414 -0
  159. package/src/routes/dash/settings.tsx +475 -99
  160. package/src/routes/feed/__tests__/rss.test.ts +22 -23
  161. package/src/routes/feed/rss.ts +6 -2
  162. package/src/routes/feed/sitemap.ts +2 -12
  163. package/src/routes/pages/__tests__/collections.test.ts +5 -6
  164. package/src/routes/pages/__tests__/featured.test.ts +36 -18
  165. package/src/routes/pages/archive.tsx +177 -37
  166. package/src/routes/pages/collection.tsx +43 -14
  167. package/src/routes/pages/collections.tsx +11 -2
  168. package/src/routes/pages/featured.tsx +27 -3
  169. package/src/routes/pages/home.tsx +15 -14
  170. package/src/routes/pages/latest.tsx +1 -11
  171. package/src/routes/pages/new.tsx +39 -0
  172. package/src/routes/pages/page.tsx +95 -49
  173. package/src/routes/pages/search.tsx +1 -1
  174. package/src/services/__tests__/api-token.test.ts +135 -0
  175. package/src/services/__tests__/collection.test.ts +275 -227
  176. package/src/services/__tests__/custom-url.test.ts +213 -0
  177. package/src/services/__tests__/media.test.ts +162 -22
  178. package/src/services/__tests__/navigation.test.ts +109 -68
  179. package/src/services/__tests__/post-timeline.test.ts +205 -32
  180. package/src/services/__tests__/post.test.ts +800 -230
  181. package/src/services/__tests__/search.test.ts +67 -10
  182. package/src/services/__tests__/settings.test.ts +3 -3
  183. package/src/services/api-token.ts +166 -0
  184. package/src/services/auth.ts +17 -2
  185. package/src/services/collection.ts +397 -131
  186. package/src/services/custom-url.ts +188 -0
  187. package/src/services/export.ts +802 -0
  188. package/src/services/index.ts +26 -19
  189. package/src/services/media.ts +100 -22
  190. package/src/services/navigation.ts +158 -47
  191. package/src/services/path.ts +339 -0
  192. package/src/services/post.ts +764 -172
  193. package/src/services/search.ts +161 -74
  194. package/src/services/settings.ts +6 -2
  195. package/src/styles/components.css +293 -62
  196. package/src/styles/tokens.css +93 -5
  197. package/src/styles/ui.css +4349 -766
  198. package/src/types/bindings.ts +8 -0
  199. package/src/types/config.ts +34 -4
  200. package/src/types/constants.ts +17 -2
  201. package/src/types/entities.ts +83 -37
  202. package/src/types/operations.ts +20 -27
  203. package/src/types/props.ts +52 -17
  204. package/src/types/views.ts +48 -24
  205. package/src/ui/color-themes.ts +133 -23
  206. package/src/ui/compose/ComposeDialog.tsx +255 -16
  207. package/src/ui/compose/ComposePrompt.tsx +1 -1
  208. package/src/ui/dash/CrudPageHeader.tsx +1 -1
  209. package/src/ui/dash/ListItemRow.tsx +1 -1
  210. package/src/ui/dash/StatusBadge.tsx +12 -2
  211. package/src/ui/dash/appearance/AdvancedContent.tsx +71 -59
  212. package/src/ui/dash/appearance/ColorThemeContent.tsx +48 -33
  213. package/src/ui/dash/appearance/FontThemeContent.tsx +65 -73
  214. package/src/ui/dash/appearance/NavigationContent.tsx +106 -135
  215. package/src/ui/dash/index.ts +0 -3
  216. package/src/ui/dash/settings/AccountContent.tsx +87 -146
  217. package/src/ui/dash/settings/AccountMenuContent.tsx +147 -0
  218. package/src/ui/dash/settings/ApiTokensContent.tsx +232 -0
  219. package/src/ui/dash/settings/AvatarContent.tsx +78 -0
  220. package/src/ui/dash/settings/GeneralContent.tsx +3 -62
  221. package/src/ui/dash/settings/SessionsContent.tsx +159 -0
  222. package/src/ui/dash/settings/SettingsRootContent.tsx +266 -0
  223. package/src/ui/feed/LinkCard.tsx +89 -40
  224. package/src/ui/feed/NoteCard.tsx +39 -25
  225. package/src/ui/feed/PostStatusBadges.tsx +67 -0
  226. package/src/ui/feed/QuoteCard.tsx +38 -23
  227. package/src/ui/feed/ThreadPreview.tsx +90 -26
  228. package/src/ui/feed/TimelineFeed.tsx +3 -2
  229. package/src/ui/feed/TimelineItem.tsx +15 -6
  230. package/src/ui/feed/__tests__/thread-preview.test.ts +107 -0
  231. package/src/ui/feed/thread-preview-state.ts +61 -0
  232. package/src/ui/font-themes.ts +2 -2
  233. package/src/ui/layouts/BaseLayout.tsx +2 -2
  234. package/src/ui/layouts/SiteLayout.tsx +116 -103
  235. package/src/ui/pages/ArchivePage.tsx +923 -95
  236. package/src/ui/pages/CollectionPage.tsx +6 -35
  237. package/src/ui/pages/CollectionsPage.tsx +2 -1
  238. package/src/ui/pages/ComposePage.tsx +54 -0
  239. package/src/ui/pages/FeaturedPage.tsx +2 -1
  240. package/src/ui/pages/HomePage.tsx +1 -1
  241. package/src/ui/pages/PostPage.tsx +30 -45
  242. package/src/ui/pages/SearchPage.tsx +182 -38
  243. package/src/ui/shared/AdminBreadcrumb.tsx +29 -0
  244. package/src/ui/shared/CollectionsSidebar.tsx +239 -4
  245. package/src/ui/shared/MediaGallery.tsx +475 -41
  246. package/src/ui/shared/PostFooter.tsx +204 -0
  247. package/src/ui/shared/StarRating.tsx +27 -0
  248. package/src/ui/shared/__tests__/format-chars.test.ts +35 -0
  249. package/src/ui/shared/index.ts +0 -1
  250. package/src/db/migrations/0000_square_wallflower.sql +0 -118
  251. package/src/db/migrations/0001_add_search_fts.sql +0 -34
  252. package/src/db/migrations/0002_add_media_attachments.sql +0 -3
  253. package/src/db/migrations/0003_add_navigation_links.sql +0 -8
  254. package/src/db/migrations/0004_add_storage_provider.sql +0 -3
  255. package/src/db/migrations/0005_v2_schema_migration.sql +0 -268
  256. package/src/db/migrations/0006_rename_slug_to_path.sql +0 -5
  257. package/src/db/migrations/0007_post_collections_m2m.sql +0 -94
  258. package/src/db/migrations/0008_add_collection_dividers.sql +0 -8
  259. package/src/db/migrations/0009_drop_collection_show_divider.sql +0 -2
  260. package/src/db/migrations/0010_add_performance_indexes.sql +0 -16
  261. package/src/db/migrations/0011_add_path_registry.sql +0 -23
  262. package/src/db/migrations/meta/0003_snapshot.json +0 -821
  263. package/src/lib/__tests__/sqid.test.ts +0 -65
  264. package/src/lib/collections-reorder.ts +0 -28
  265. package/src/lib/compose-bridge.ts +0 -280
  266. package/src/lib/media-upload.ts +0 -148
  267. package/src/lib/sqid.ts +0 -79
  268. package/src/routes/api/__tests__/pages.test.ts +0 -218
  269. package/src/routes/api/pages.ts +0 -73
  270. package/src/routes/dash/__tests__/pages.test.ts +0 -226
  271. package/src/routes/dash/appearance.tsx +0 -240
  272. package/src/routes/dash/collections.tsx +0 -211
  273. package/src/routes/dash/index.tsx +0 -103
  274. package/src/routes/dash/media.tsx +0 -132
  275. package/src/routes/dash/pages.tsx +0 -239
  276. package/src/routes/dash/posts.tsx +0 -334
  277. package/src/routes/dash/redirects.tsx +0 -257
  278. package/src/routes/pages/post.tsx +0 -59
  279. package/src/services/__tests__/page.test.ts +0 -298
  280. package/src/services/__tests__/path-registry.test.ts +0 -165
  281. package/src/services/__tests__/redirect.test.ts +0 -159
  282. package/src/services/page.ts +0 -203
  283. package/src/services/path-registry.ts +0 -160
  284. package/src/services/redirect.ts +0 -97
  285. package/src/types/sortablejs.d.ts +0 -29
  286. package/src/ui/components/__tests__/jant-compose-dialog.test.ts +0 -512
  287. package/src/ui/components/__tests__/jant-compose-editor.test.ts +0 -272
  288. package/src/ui/components/compose-types.ts +0 -75
  289. package/src/ui/components/jant-collection-form.ts +0 -512
  290. package/src/ui/components/jant-compose-dialog.ts +0 -495
  291. package/src/ui/components/jant-compose-editor.ts +0 -814
  292. package/src/ui/dash/PageForm.tsx +0 -185
  293. package/src/ui/dash/PostList.tsx +0 -95
  294. package/src/ui/dash/appearance/AppearanceNav.tsx +0 -60
  295. package/src/ui/dash/collections/CollectionForm.tsx +0 -166
  296. package/src/ui/dash/collections/CollectionsListContent.tsx +0 -146
  297. package/src/ui/dash/collections/IconPickerGrid.tsx +0 -50
  298. package/src/ui/dash/collections/ViewCollectionContent.tsx +0 -103
  299. package/src/ui/dash/media/MediaListContent.tsx +0 -201
  300. package/src/ui/dash/media/ViewMediaContent.tsx +0 -208
  301. package/src/ui/dash/pages/PagesContent.tsx +0 -74
  302. package/src/ui/dash/posts/PostForm.tsx +0 -248
  303. package/src/ui/dash/settings/SettingsNav.tsx +0 -52
  304. package/src/ui/layouts/DashLayout.tsx +0 -165
  305. package/src/ui/pages/SinglePage.tsx +0 -23
  306. package/src/ui/shared/ThreadView.tsx +0 -136
  307. /package/src/{ui → client}/components/settings-types.ts +0 -0
@@ -1,268 +0,0 @@
1
- -- v2 Schema Migration
2
- -- Restructures posts, creates pages, updates collections, replaces navigation_links with nav_items
3
-
4
- -- Disable FK checks for migration (dropping/recreating tables with cross-references)
5
- PRAGMA foreign_keys = OFF;
6
- --> statement-breakpoint
7
-
8
- -- =============================================================================
9
- -- 1. Create pages table (before modifying posts, migrate type='page' data)
10
- -- =============================================================================
11
-
12
- CREATE TABLE `pages` (
13
- `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
14
- `slug` text NOT NULL,
15
- `title` text,
16
- `body` text,
17
- `body_html` text,
18
- `status` text DEFAULT 'published' NOT NULL,
19
- `created_at` integer NOT NULL,
20
- `updated_at` integer NOT NULL
21
- );
22
- --> statement-breakpoint
23
- CREATE UNIQUE INDEX `pages_slug_unique` ON `pages` (`slug`);
24
- --> statement-breakpoint
25
-
26
- -- Migrate type='page' posts into pages table
27
- INSERT INTO `pages` (`slug`, `title`, `body`, `body_html`, `status`, `created_at`, `updated_at`)
28
- SELECT
29
- CASE
30
- WHEN `path` IS NOT NULL AND `path` != '' THEN REPLACE(`path`, '/', '')
31
- ELSE 'page-' || `id`
32
- END,
33
- `title`,
34
- `content`,
35
- `content_html`,
36
- CASE WHEN `visibility` = 'draft' THEN 'draft' ELSE 'published' END,
37
- `created_at`,
38
- `updated_at`
39
- FROM `posts`
40
- WHERE `type` = 'page';
41
- --> statement-breakpoint
42
-
43
- -- =============================================================================
44
- -- 2. Restructure posts table (create new → migrate → drop old → rename)
45
- -- =============================================================================
46
-
47
- CREATE TABLE `posts_new` (
48
- `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
49
- `format` text DEFAULT 'note' NOT NULL,
50
- `status` text DEFAULT 'published' NOT NULL,
51
- `featured` integer DEFAULT 0 NOT NULL,
52
- `pinned` integer DEFAULT 0 NOT NULL,
53
- `slug` text,
54
- `title` text,
55
- `url` text,
56
- `body` text,
57
- `body_html` text,
58
- `quote_text` text,
59
- `rating` integer,
60
- `collection_id` integer,
61
- `reply_to_id` integer,
62
- `thread_id` integer,
63
- `deleted_at` integer,
64
- `published_at` integer NOT NULL,
65
- `created_at` integer NOT NULL,
66
- `updated_at` integer NOT NULL,
67
- FOREIGN KEY (`collection_id`) REFERENCES `collections`(`id`) ON UPDATE no action ON DELETE set null
68
- );
69
- --> statement-breakpoint
70
-
71
- -- Migrate data from old posts to new posts (excluding type='page')
72
- INSERT INTO `posts_new` (
73
- `id`, `format`, `status`, `featured`, `pinned`,
74
- `slug`, `title`, `url`, `body`, `body_html`, `quote_text`, `rating`,
75
- `collection_id`, `reply_to_id`, `thread_id`,
76
- `deleted_at`, `published_at`, `created_at`, `updated_at`
77
- )
78
- SELECT
79
- `id`,
80
- -- format mapping: article→note, image→note, note→note, link→link, quote→quote
81
- CASE
82
- WHEN `type` IN ('article', 'image', 'note') THEN 'note'
83
- WHEN `type` = 'link' THEN 'link'
84
- WHEN `type` = 'quote' THEN 'quote'
85
- ELSE 'note'
86
- END,
87
- -- status mapping from visibility
88
- CASE WHEN `visibility` = 'draft' THEN 'draft' ELSE 'published' END,
89
- -- featured mapping from visibility
90
- CASE WHEN `visibility` = 'featured' THEN 1 ELSE 0 END,
91
- -- pinned: default 0
92
- 0,
93
- -- slug: migrate from path (strip leading /)
94
- CASE
95
- WHEN `path` IS NOT NULL AND `path` != '' THEN REPLACE(`path`, '/', '')
96
- ELSE NULL
97
- END,
98
- `title`,
99
- `source_url`,
100
- `content`,
101
- `content_html`,
102
- -- quote_text: for quote type, content was the quote; set to null (manual fix may be needed)
103
- NULL,
104
- -- rating: null
105
- NULL,
106
- -- collection_id: migrate from post_collections (take first collection for each post)
107
- (SELECT `collection_id` FROM `post_collections` WHERE `post_collections`.`post_id` = `posts`.`id` LIMIT 1),
108
- `reply_to_id`,
109
- `thread_id`,
110
- `deleted_at`,
111
- `published_at`,
112
- `created_at`,
113
- `updated_at`
114
- FROM `posts`
115
- WHERE `type` != 'page';
116
- --> statement-breakpoint
117
-
118
- -- Update media references to point at new table (foreign keys reference posts)
119
- -- media.post_id still works since IDs are preserved
120
- --> statement-breakpoint
121
-
122
- -- Drop old posts table and rename new one
123
- DROP TABLE `posts`;
124
- --> statement-breakpoint
125
- ALTER TABLE `posts_new` RENAME TO `posts`;
126
- --> statement-breakpoint
127
- CREATE UNIQUE INDEX `posts_slug_unique` ON `posts` (`slug`);
128
- --> statement-breakpoint
129
-
130
- -- =============================================================================
131
- -- 3. Update collections table (add new columns, rename path→slug)
132
- -- =============================================================================
133
-
134
- CREATE TABLE `collections_new` (
135
- `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
136
- `slug` text NOT NULL,
137
- `title` text NOT NULL,
138
- `description` text,
139
- `icon` text,
140
- `sort_order` text DEFAULT 'newest' NOT NULL,
141
- `position` integer DEFAULT 0 NOT NULL,
142
- `show_divider` integer DEFAULT 0 NOT NULL,
143
- `created_at` integer NOT NULL,
144
- `updated_at` integer NOT NULL
145
- );
146
- --> statement-breakpoint
147
- CREATE UNIQUE INDEX `collections_new_slug_unique` ON `collections_new` (`slug`);
148
- --> statement-breakpoint
149
-
150
- INSERT INTO `collections_new` (`id`, `slug`, `title`, `description`, `icon`, `sort_order`, `position`, `show_divider`, `created_at`, `updated_at`)
151
- SELECT
152
- `id`,
153
- COALESCE(`path`, 'collection-' || `id`),
154
- `title`,
155
- `description`,
156
- NULL,
157
- 'newest',
158
- 0,
159
- 0,
160
- `created_at`,
161
- `updated_at`
162
- FROM `collections`;
163
- --> statement-breakpoint
164
-
165
- DROP TABLE `collections`;
166
- --> statement-breakpoint
167
- ALTER TABLE `collections_new` RENAME TO `collections`;
168
- --> statement-breakpoint
169
- CREATE UNIQUE INDEX `collections_slug_unique` ON `collections` (`slug`);
170
- --> statement-breakpoint
171
-
172
- -- =============================================================================
173
- -- 4. Replace navigation_links with nav_items
174
- -- =============================================================================
175
-
176
- CREATE TABLE `nav_items` (
177
- `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
178
- `type` text DEFAULT 'link' NOT NULL,
179
- `label` text NOT NULL,
180
- `url` text NOT NULL,
181
- `page_id` integer,
182
- `position` integer DEFAULT 0 NOT NULL,
183
- `created_at` integer NOT NULL,
184
- `updated_at` integer NOT NULL,
185
- FOREIGN KEY (`page_id`) REFERENCES `pages`(`id`) ON UPDATE no action ON DELETE cascade
186
- );
187
- --> statement-breakpoint
188
-
189
- -- Migrate existing navigation_links as type='link'
190
- INSERT INTO `nav_items` (`type`, `label`, `url`, `page_id`, `position`, `created_at`, `updated_at`)
191
- SELECT 'link', `label`, `url`, NULL, `position`, `created_at`, `updated_at`
192
- FROM `navigation_links`;
193
- --> statement-breakpoint
194
-
195
- DROP TABLE `navigation_links`;
196
- --> statement-breakpoint
197
-
198
- -- =============================================================================
199
- -- 5. Drop post_collections table (replaced by posts.collection_id)
200
- -- =============================================================================
201
-
202
- DROP TABLE `post_collections`;
203
- --> statement-breakpoint
204
-
205
- -- =============================================================================
206
- -- 6. Rebuild FTS5 (column rename: content→body, add quote_text)
207
- -- =============================================================================
208
-
209
- -- Drop old FTS triggers
210
- DROP TRIGGER IF EXISTS posts_fts_insert;
211
- --> statement-breakpoint
212
- DROP TRIGGER IF EXISTS posts_fts_update;
213
- --> statement-breakpoint
214
- DROP TRIGGER IF EXISTS posts_fts_delete;
215
- --> statement-breakpoint
216
-
217
- -- Drop old FTS table
218
- DROP TABLE IF EXISTS posts_fts;
219
- --> statement-breakpoint
220
-
221
- -- Create new FTS table with updated columns
222
- CREATE VIRTUAL TABLE IF NOT EXISTS posts_fts USING fts5(
223
- title,
224
- body,
225
- quote_text,
226
- content=posts,
227
- content_rowid=id,
228
- tokenize='trigram'
229
- );
230
- --> statement-breakpoint
231
-
232
- -- Populate FTS with migrated data
233
- INSERT INTO posts_fts(rowid, title, body, quote_text)
234
- SELECT id, COALESCE(title, ''), COALESCE(body, ''), COALESCE(quote_text, '')
235
- FROM posts WHERE deleted_at IS NULL;
236
- --> statement-breakpoint
237
-
238
- -- Trigger: sync FTS on INSERT
239
- CREATE TRIGGER posts_fts_insert AFTER INSERT ON posts
240
- WHEN NEW.deleted_at IS NULL
241
- BEGIN
242
- INSERT INTO posts_fts(rowid, title, body, quote_text)
243
- VALUES (NEW.id, COALESCE(NEW.title, ''), COALESCE(NEW.body, ''), COALESCE(NEW.quote_text, ''));
244
- END;
245
- --> statement-breakpoint
246
-
247
- -- Trigger: sync FTS on UPDATE
248
- CREATE TRIGGER posts_fts_update AFTER UPDATE ON posts BEGIN
249
- DELETE FROM posts_fts WHERE rowid = OLD.id;
250
- INSERT INTO posts_fts(rowid, title, body, quote_text)
251
- SELECT NEW.id, COALESCE(NEW.title, ''), COALESCE(NEW.body, ''), COALESCE(NEW.quote_text, '')
252
- WHERE NEW.deleted_at IS NULL;
253
- END;
254
- --> statement-breakpoint
255
-
256
- -- Trigger: sync FTS on DELETE
257
- CREATE TRIGGER posts_fts_delete AFTER DELETE ON posts BEGIN
258
- DELETE FROM posts_fts WHERE rowid = OLD.id;
259
- END;
260
- --> statement-breakpoint
261
-
262
- -- =============================================================================
263
- -- 7. Re-enable FK checks and verify integrity
264
- -- =============================================================================
265
-
266
- PRAGMA foreign_keys = ON;
267
- --> statement-breakpoint
268
- PRAGMA foreign_key_check;
@@ -1,5 +0,0 @@
1
- ALTER TABLE posts RENAME COLUMN slug TO path;
2
- --> statement-breakpoint
3
- DROP INDEX IF EXISTS posts_slug_unique;
4
- --> statement-breakpoint
5
- CREATE UNIQUE INDEX posts_path_unique ON posts (path);
@@ -1,94 +0,0 @@
1
- -- Post-Collections M:N migration
2
- -- Restore many-to-many relationship between posts and collections
3
-
4
- PRAGMA foreign_keys = OFF;
5
- --> statement-breakpoint
6
-
7
- -- 1. Create junction table
8
- CREATE TABLE `post_collections` (
9
- `post_id` integer NOT NULL,
10
- `collection_id` integer NOT NULL,
11
- PRIMARY KEY (`post_id`, `collection_id`),
12
- FOREIGN KEY (`post_id`) REFERENCES `posts`(`id`) ON DELETE CASCADE,
13
- FOREIGN KEY (`collection_id`) REFERENCES `collections`(`id`) ON DELETE CASCADE
14
- );
15
- --> statement-breakpoint
16
-
17
- -- 2. Migrate existing data from posts.collection_id
18
- INSERT INTO `post_collections` (`post_id`, `collection_id`)
19
- SELECT `id`, `collection_id` FROM `posts`
20
- WHERE `collection_id` IS NOT NULL;
21
- --> statement-breakpoint
22
-
23
- -- 3. Recreate posts table without collection_id
24
- CREATE TABLE `posts_new` (
25
- `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
26
- `format` text NOT NULL,
27
- `status` text DEFAULT 'published' NOT NULL,
28
- `featured` integer DEFAULT 0 NOT NULL,
29
- `pinned` integer DEFAULT 0 NOT NULL,
30
- `path` text,
31
- `title` text,
32
- `url` text,
33
- `body` text,
34
- `body_html` text,
35
- `quote_text` text,
36
- `rating` integer,
37
- `reply_to_id` integer,
38
- `thread_id` integer,
39
- `deleted_at` integer,
40
- `published_at` integer NOT NULL,
41
- `created_at` integer NOT NULL,
42
- `updated_at` integer NOT NULL
43
- );
44
- --> statement-breakpoint
45
-
46
- INSERT INTO `posts_new` (
47
- `id`, `format`, `status`, `featured`, `pinned`,
48
- `path`, `title`, `url`, `body`, `body_html`, `quote_text`, `rating`,
49
- `reply_to_id`, `thread_id`, `deleted_at`, `published_at`, `created_at`, `updated_at`
50
- )
51
- SELECT
52
- `id`, `format`, `status`, `featured`, `pinned`,
53
- `path`, `title`, `url`, `body`, `body_html`, `quote_text`, `rating`,
54
- `reply_to_id`, `thread_id`, `deleted_at`, `published_at`, `created_at`, `updated_at`
55
- FROM `posts`;
56
- --> statement-breakpoint
57
-
58
- DROP TABLE `posts`;
59
- --> statement-breakpoint
60
- ALTER TABLE `posts_new` RENAME TO `posts`;
61
- --> statement-breakpoint
62
- CREATE UNIQUE INDEX `posts_path_unique` ON `posts` (`path`);
63
- --> statement-breakpoint
64
-
65
- -- 4. Rebuild FTS triggers (column references changed due to table recreation)
66
- DROP TRIGGER IF EXISTS posts_fts_insert;
67
- --> statement-breakpoint
68
- DROP TRIGGER IF EXISTS posts_fts_update;
69
- --> statement-breakpoint
70
- DROP TRIGGER IF EXISTS posts_fts_delete;
71
- --> statement-breakpoint
72
-
73
- CREATE TRIGGER posts_fts_insert AFTER INSERT ON posts
74
- WHEN NEW.deleted_at IS NULL
75
- BEGIN
76
- INSERT INTO posts_fts(rowid, title, body, quote_text)
77
- VALUES (NEW.id, COALESCE(NEW.title, ''), COALESCE(NEW.body, ''), COALESCE(NEW.quote_text, ''));
78
- END;
79
- --> statement-breakpoint
80
-
81
- CREATE TRIGGER posts_fts_update AFTER UPDATE ON posts BEGIN
82
- DELETE FROM posts_fts WHERE rowid = OLD.id;
83
- INSERT INTO posts_fts(rowid, title, body, quote_text)
84
- SELECT NEW.id, COALESCE(NEW.title, ''), COALESCE(NEW.body, ''), COALESCE(NEW.quote_text, '')
85
- WHERE NEW.deleted_at IS NULL;
86
- END;
87
- --> statement-breakpoint
88
-
89
- CREATE TRIGGER posts_fts_delete AFTER DELETE ON posts BEGIN
90
- DELETE FROM posts_fts WHERE rowid = OLD.id;
91
- END;
92
- --> statement-breakpoint
93
-
94
- PRAGMA foreign_keys = ON;
@@ -1,8 +0,0 @@
1
- -- Add collection_dividers table for standalone sortable divider lines
2
-
3
- CREATE TABLE `collection_dividers` (
4
- `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
5
- `position` integer DEFAULT 0 NOT NULL,
6
- `created_at` integer NOT NULL,
7
- `updated_at` integer NOT NULL
8
- );
@@ -1,2 +0,0 @@
1
- -- Drop the show_divider column from collections (replaced by collection_dividers table)
2
- ALTER TABLE `collections` DROP COLUMN `show_divider`;
@@ -1,16 +0,0 @@
1
- -- Performance indexes for frequently queried columns
2
- -- Posts: almost every query filters by deleted_at IS NULL AND status = 'published'
3
- CREATE INDEX IF NOT EXISTS idx_posts_status_deleted ON posts (status, deleted_at);--> statement-breakpoint
4
-
5
- -- Posts: thread lookups and reply counts
6
- CREATE INDEX IF NOT EXISTS idx_posts_thread_id ON posts (thread_id);--> statement-breakpoint
7
-
8
- -- Posts: ordering by publication date
9
- CREATE INDEX IF NOT EXISTS idx_posts_published_at ON posts (published_at);--> statement-breakpoint
10
-
11
- -- Media: lookup by post
12
- CREATE INDEX IF NOT EXISTS idx_media_post_id ON media (post_id);--> statement-breakpoint
13
-
14
- -- Post-Collections: junction table queries in both directions
15
- CREATE UNIQUE INDEX IF NOT EXISTS idx_post_collections_pk ON post_collections (post_id, collection_id);--> statement-breakpoint
16
- CREATE INDEX IF NOT EXISTS idx_post_collections_collection ON post_collections (collection_id);
@@ -1,23 +0,0 @@
1
- -- Path Registry: single source of truth for all claimed URL paths.
2
- -- Enforces uniqueness at the DB level via PRIMARY KEY on path.
3
-
4
- CREATE TABLE path_registry (
5
- path TEXT PRIMARY KEY,
6
- owner_type TEXT NOT NULL,
7
- owner_id INTEGER NOT NULL,
8
- created_at INTEGER NOT NULL
9
- );
10
- --> statement-breakpoint
11
- CREATE INDEX idx_path_registry_owner ON path_registry (owner_type, owner_id);
12
- --> statement-breakpoint
13
- -- Backfill from existing pages (slug)
14
- INSERT INTO path_registry (path, owner_type, owner_id, created_at)
15
- SELECT slug, 'page', id, created_at FROM pages;
16
- --> statement-breakpoint
17
- -- Backfill from existing posts with custom paths (non-deleted only)
18
- INSERT INTO path_registry (path, owner_type, owner_id, created_at)
19
- SELECT path, 'post', id, created_at FROM posts WHERE path IS NOT NULL AND deleted_at IS NULL;
20
- --> statement-breakpoint
21
- -- Backfill from existing redirects
22
- INSERT INTO path_registry (path, owner_type, owner_id, created_at)
23
- SELECT from_path, 'redirect', id, created_at FROM redirects;