@jant/core 0.2.12 → 0.2.13

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 (146) hide show
  1. package/bin/jant.js +3 -1
  2. package/dist/app.d.ts.map +1 -1
  3. package/dist/app.js +112 -85
  4. package/dist/auth.d.ts +1 -0
  5. package/dist/auth.d.ts.map +1 -1
  6. package/dist/auth.js +2 -1
  7. package/dist/client.js +1 -1
  8. package/dist/db/schema.d.ts.map +1 -1
  9. package/dist/i18n/context.d.ts.map +1 -1
  10. package/dist/i18n/context.js +0 -3
  11. package/dist/i18n/detect.d.ts +0 -11
  12. package/dist/i18n/detect.d.ts.map +1 -1
  13. package/dist/i18n/detect.js +1 -52
  14. package/dist/i18n/i18n.d.ts +4 -14
  15. package/dist/i18n/i18n.d.ts.map +1 -1
  16. package/dist/i18n/i18n.js +19 -25
  17. package/dist/i18n/index.d.ts +1 -1
  18. package/dist/i18n/index.d.ts.map +1 -1
  19. package/dist/i18n/index.js +1 -1
  20. package/dist/i18n/middleware.d.ts +2 -5
  21. package/dist/i18n/middleware.d.ts.map +1 -1
  22. package/dist/i18n/middleware.js +12 -23
  23. package/dist/lib/constants.d.ts.map +1 -1
  24. package/dist/lib/image.d.ts.map +1 -1
  25. package/dist/lib/schemas.d.ts.map +1 -1
  26. package/dist/lib/sse.d.ts +45 -17
  27. package/dist/lib/sse.d.ts.map +1 -1
  28. package/dist/lib/sse.js +77 -37
  29. package/dist/middleware/auth.d.ts.map +1 -1
  30. package/dist/routes/api/posts.js +0 -1
  31. package/dist/routes/api/upload.js +3 -1
  32. package/dist/routes/dash/collections.d.ts.map +1 -1
  33. package/dist/routes/dash/collections.js +134 -142
  34. package/dist/routes/dash/index.js +25 -26
  35. package/dist/routes/dash/media.d.ts.map +1 -1
  36. package/dist/routes/dash/media.js +60 -56
  37. package/dist/routes/dash/pages.js +64 -66
  38. package/dist/routes/dash/posts.d.ts.map +1 -1
  39. package/dist/routes/dash/posts.js +50 -59
  40. package/dist/routes/dash/redirects.d.ts.map +1 -1
  41. package/dist/routes/dash/redirects.js +63 -60
  42. package/dist/routes/dash/settings.d.ts.map +1 -1
  43. package/dist/routes/dash/settings.js +249 -93
  44. package/dist/routes/feed/rss.js +6 -4
  45. package/dist/routes/pages/archive.js +60 -62
  46. package/dist/routes/pages/collection.js +8 -8
  47. package/dist/routes/pages/home.js +14 -14
  48. package/dist/routes/pages/page.js +7 -6
  49. package/dist/routes/pages/post.js +8 -8
  50. package/dist/routes/pages/search.js +25 -27
  51. package/dist/services/collection.d.ts.map +1 -1
  52. package/dist/services/index.d.ts.map +1 -1
  53. package/dist/services/media.d.ts.map +1 -1
  54. package/dist/services/post.d.ts.map +1 -1
  55. package/dist/services/redirect.d.ts.map +1 -1
  56. package/dist/services/settings.d.ts.map +1 -1
  57. package/dist/theme/components/ActionButtons.d.ts +1 -1
  58. package/dist/theme/components/ActionButtons.d.ts.map +1 -1
  59. package/dist/theme/components/ActionButtons.js +17 -21
  60. package/dist/theme/components/CrudPageHeader.d.ts.map +1 -1
  61. package/dist/theme/components/DangerZone.d.ts.map +1 -1
  62. package/dist/theme/components/DangerZone.js +12 -15
  63. package/dist/theme/components/EmptyState.d.ts.map +1 -1
  64. package/dist/theme/components/PageForm.d.ts.map +1 -1
  65. package/dist/theme/components/PageForm.js +58 -56
  66. package/dist/theme/components/Pagination.d.ts.map +1 -1
  67. package/dist/theme/components/Pagination.js +22 -25
  68. package/dist/theme/components/PostForm.d.ts +0 -1
  69. package/dist/theme/components/PostForm.d.ts.map +1 -1
  70. package/dist/theme/components/PostForm.js +85 -77
  71. package/dist/theme/components/PostList.d.ts.map +1 -1
  72. package/dist/theme/components/PostList.js +17 -17
  73. package/dist/theme/components/ThreadView.d.ts.map +1 -1
  74. package/dist/theme/components/ThreadView.js +15 -18
  75. package/dist/theme/components/TypeBadge.d.ts.map +1 -1
  76. package/dist/theme/components/TypeBadge.js +20 -20
  77. package/dist/theme/components/VisibilityBadge.d.ts.map +1 -1
  78. package/dist/theme/components/VisibilityBadge.js +14 -14
  79. package/dist/theme/components/index.d.ts +1 -1
  80. package/dist/theme/components/index.d.ts.map +1 -1
  81. package/dist/theme/layouts/BaseLayout.d.ts.map +1 -1
  82. package/dist/theme/layouts/BaseLayout.js +4 -2
  83. package/dist/theme/layouts/DashLayout.d.ts.map +1 -1
  84. package/dist/theme/layouts/DashLayout.js +29 -29
  85. package/dist/types/lingui-react-macro.d.js +9 -0
  86. package/dist/types.d.ts +2 -0
  87. package/dist/types.d.ts.map +1 -1
  88. package/dist/vendor/datastar.js +1606 -0
  89. package/package.json +5 -2
  90. package/src/app.tsx +175 -56
  91. package/src/auth.ts +5 -1
  92. package/src/client.ts +1 -1
  93. package/src/db/schema.ts +22 -7
  94. package/src/i18n/EXAMPLES.md +34 -14
  95. package/src/i18n/README.md +19 -9
  96. package/src/i18n/context.tsx +1 -4
  97. package/src/i18n/detect.ts +1 -67
  98. package/src/i18n/i18n.ts +15 -19
  99. package/src/i18n/index.ts +0 -3
  100. package/src/i18n/middleware.ts +12 -24
  101. package/src/lib/constants.ts +2 -1
  102. package/src/lib/image-processor.ts +23 -7
  103. package/src/lib/image.ts +6 -2
  104. package/src/lib/schemas.ts +6 -2
  105. package/src/lib/sse.ts +138 -50
  106. package/src/middleware/auth.ts +6 -2
  107. package/src/routes/api/posts.ts +14 -5
  108. package/src/routes/api/upload.ts +25 -7
  109. package/src/routes/dash/collections.tsx +162 -70
  110. package/src/routes/dash/index.tsx +22 -7
  111. package/src/routes/dash/media.tsx +59 -16
  112. package/src/routes/dash/pages.tsx +102 -44
  113. package/src/routes/dash/posts.tsx +87 -54
  114. package/src/routes/dash/redirects.tsx +74 -26
  115. package/src/routes/dash/settings.tsx +250 -57
  116. package/src/routes/feed/rss.ts +6 -4
  117. package/src/routes/pages/archive.tsx +71 -21
  118. package/src/routes/pages/collection.tsx +21 -6
  119. package/src/routes/pages/home.tsx +30 -9
  120. package/src/routes/pages/page.tsx +14 -5
  121. package/src/routes/pages/post.tsx +21 -7
  122. package/src/routes/pages/search.tsx +42 -11
  123. package/src/services/collection.ts +34 -9
  124. package/src/services/index.ts +4 -1
  125. package/src/services/media.ts +15 -3
  126. package/src/services/post.ts +39 -10
  127. package/src/services/redirect.ts +4 -1
  128. package/src/services/settings.ts +14 -3
  129. package/src/theme/components/ActionButtons.tsx +26 -14
  130. package/src/theme/components/CrudPageHeader.tsx +6 -1
  131. package/src/theme/components/DangerZone.tsx +19 -13
  132. package/src/theme/components/EmptyState.tsx +6 -1
  133. package/src/theme/components/PageForm.tsx +71 -24
  134. package/src/theme/components/Pagination.tsx +26 -8
  135. package/src/theme/components/PostForm.tsx +72 -25
  136. package/src/theme/components/PostList.tsx +16 -5
  137. package/src/theme/components/ThreadView.tsx +25 -7
  138. package/src/theme/components/TypeBadge.tsx +13 -4
  139. package/src/theme/components/VisibilityBadge.tsx +17 -5
  140. package/src/theme/components/index.ts +4 -1
  141. package/src/theme/layouts/BaseLayout.tsx +5 -2
  142. package/src/theme/layouts/DashLayout.tsx +41 -12
  143. package/src/types/lingui-react-macro.d.ts +34 -0
  144. package/src/types.ts +16 -2
  145. package/src/vendor/datastar.js +9 -0
  146. package/src/vendor/datastar.js.map +7 -0
package/dist/i18n/i18n.js CHANGED
@@ -1,42 +1,36 @@
1
1
  /**
2
- * i18n Runtime using @lingui/core with Lingui macros
2
+ * i18n Runtime using @lingui/core
3
3
  *
4
- * Usage:
5
- * import { msg } from "@lingui/core/macro";
6
- * import { bindI18n } from "@/i18n";
7
- *
8
- * const { i18n } = bindI18n(c.get("i18n"));
9
- *
10
- * // Simple message
11
- * i18n._(msg({ message: "Hello", comment: "@context: Greeting" }))
12
- *
13
- * // With interpolation
14
- * i18n._(msg({ message: "Welcome, {name}!", comment: "@context: Welcome" }), { name })
15
- *
16
- * The msg macro generates hash-based IDs at compile time, which match the compiled catalogs.
4
+ * The SWC Lingui plugin adds hash-based IDs to t() calls when imports come
5
+ * from @lingui/react/macro. The runtimeConfigModule setting rewrites those
6
+ * imports to our custom Hono JSX implementation at build time.
17
7
  */ import { I18n } from "@lingui/core";
18
8
  import { locales, baseLocale, isLocale } from "./locales.js";
19
9
  import { messages as messagesEn } from "./locales/en.js";
20
10
  import { messages as messagesZhHans } from "./locales/zh-Hans.js";
21
11
  import { messages as messagesZhHant } from "./locales/zh-Hant.js";
22
12
  export { locales, baseLocale, isLocale };
13
+ // Pre-compute merged catalogs at module load time (done once, not per request)
14
+ // For non-English locales, merge English as fallback so missing translations
15
+ // fall back to English rather than showing hash IDs.
16
+ const catalogEn = messagesEn;
17
+ const catalogZhHans = {
18
+ ...messagesEn,
19
+ ...messagesZhHans
20
+ };
21
+ const catalogZhHant = {
22
+ ...messagesEn,
23
+ ...messagesZhHant
24
+ };
23
25
  /**
24
26
  * Create a new i18n instance for a specific locale.
25
27
  * IMPORTANT: In Cloudflare Workers (concurrent environment), we must create
26
28
  * a new instance per request to avoid race conditions. Never use a global instance!
27
29
  */ export function createI18n(locale) {
28
30
  const i18n = new I18n({});
29
- // Load all catalogs with English as fallback
30
- i18n.load("en", messagesEn);
31
- i18n.load("zh-Hans", {
32
- ...messagesEn,
33
- ...messagesZhHans
34
- });
35
- i18n.load("zh-Hant", {
36
- ...messagesEn,
37
- ...messagesZhHant
38
- });
39
- // Activate locale after loading messages to avoid warnings
31
+ i18n.load("en", catalogEn);
32
+ i18n.load("zh-Hans", catalogZhHans);
33
+ i18n.load("zh-Hant", catalogZhHant);
40
34
  i18n.activate(locale);
41
35
  return i18n;
42
36
  }
@@ -36,6 +36,6 @@
36
36
  export { createI18n, getI18n, locales, baseLocale, isLocale, type Locale, type I18n, } from "./i18n.js";
37
37
  export { I18nProvider, useLingui } from "./context.js";
38
38
  export { Trans } from "./Trans.js";
39
- export { detectLanguage, isValidLanguage, parseAcceptLanguage, getLanguageDisplayName, getSupportedLanguages, LANGUAGE_COOKIE_NAME, } from "./detect.js";
39
+ export { isValidLanguage, getLanguageDisplayName, getSupportedLanguages, } from "./detect.js";
40
40
  export { i18nMiddleware } from "./middleware.js";
41
41
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,EACL,UAAU,EACV,OAAO,EACP,OAAO,EACP,UAAU,EACV,QAAQ,EACR,KAAK,MAAM,EACX,KAAK,IAAI,GACV,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGvD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,EACL,UAAU,EACV,OAAO,EACP,OAAO,EACP,UAAU,EACV,QAAQ,EACR,KAAK,MAAM,EACX,KAAK,IAAI,GACV,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGvD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
@@ -39,6 +39,6 @@ export { I18nProvider, useLingui } from "./context.js";
39
39
  // Trans component (simplified for Hono JSX)
40
40
  export { Trans } from "./Trans.js";
41
41
  // Language detection utilities
42
- export { detectLanguage, isValidLanguage, parseAcceptLanguage, getLanguageDisplayName, getSupportedLanguages, LANGUAGE_COOKIE_NAME } from "./detect.js";
42
+ export { isValidLanguage, getLanguageDisplayName, getSupportedLanguages } from "./detect.js";
43
43
  // Hono middleware
44
44
  export { i18nMiddleware } from "./middleware.js";
@@ -14,11 +14,8 @@ declare module "hono" {
14
14
  * Hono middleware for internationalization.
15
15
  * Creates a per-request i18n instance to avoid race conditions in concurrent environments.
16
16
  *
17
- * Language detection priority:
18
- * 1. Cookie (user preference)
19
- * 2. Database SITE_LANGUAGE setting (site default)
20
- * 3. Accept-Language header
21
- * 4. Default locale (en)
17
+ * Language is determined by the database SITE_LANGUAGE setting (single source of truth).
18
+ * Falls back to the default locale (en) if not set.
22
19
  */
23
20
  export declare function i18nMiddleware(): MiddlewareHandler;
24
21
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/i18n/middleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAwB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAG9D,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,kBAAkB;QAC1B,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,IAAI,CAAC;KACZ;CACF;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,CA+BlD"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/i18n/middleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAoC,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAG1E,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,kBAAkB;QAC1B,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,IAAI,CAAC;KACZ;CACF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,CAuBlD"}
@@ -1,35 +1,24 @@
1
1
  /**
2
2
  * i18n Hono Middleware
3
- */ import { detectLanguage } from "./detect.js";
4
- import { createI18n, isLocale } from "./i18n.js";
3
+ */ import { createI18n, isLocale, baseLocale } from "./i18n.js";
5
4
  /**
6
5
  * Hono middleware for internationalization.
7
6
  * Creates a per-request i18n instance to avoid race conditions in concurrent environments.
8
7
  *
9
- * Language detection priority:
10
- * 1. Cookie (user preference)
11
- * 2. Database SITE_LANGUAGE setting (site default)
12
- * 3. Accept-Language header
13
- * 4. Default locale (en)
8
+ * Language is determined by the database SITE_LANGUAGE setting (single source of truth).
9
+ * Falls back to the default locale (en) if not set.
14
10
  */ export function i18nMiddleware() {
15
11
  return async (c, next)=>{
16
- // First try cookie and Accept-Language header
17
- let lang = detectLanguage(c);
18
- // If no cookie is set, check database SITE_LANGUAGE setting
19
- const cookies = c.req.raw.headers.get("Cookie") ?? "";
20
- const hasCookie = cookies.includes("lang=");
21
- if (!hasCookie) {
22
- // Check database setting
23
- const services = c.get("services");
24
- if (services) {
25
- try {
26
- const siteLang = await services.settings.get("SITE_LANGUAGE");
27
- if (siteLang && isLocale(siteLang)) {
28
- lang = siteLang;
29
- }
30
- } catch {
31
- // Ignore errors, fall back to detected language
12
+ let lang = baseLocale;
13
+ const services = c.get("services");
14
+ if (services) {
15
+ try {
16
+ const siteLang = await services.settings.get("SITE_LANGUAGE");
17
+ if (siteLang && isLocale(siteLang)) {
18
+ lang = siteLang;
32
19
  }
20
+ } catch {
21
+ // Ignore errors, fall back to default locale
33
22
  }
34
23
  }
35
24
  // Create a new i18n instance for this request to avoid race conditions
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc,mMAqBjB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAE7E;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc,mMAqBjB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAE7E;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAC1B,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/lib/image.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,4BAA4B;IAC5B,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,YAAY,GACrB,MAAM,CAiBR;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAOxF"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/lib/image.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,4BAA4B;IAC5B,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,YAAY,GACrB,MAAM,CAiBR;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAOR"}
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/lib/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;EAAqB,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;EAA4B,CAAC;AAE1D;;;GAGG;AACH,eAAO,MAAM,kBAAkB;;;EAAyB,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;iBAc3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;iBAA6B,CAAC;AAE3D;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAM3F;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GACrB,CAAC,GAAG,SAAS,CAMf"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/lib/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;EAAqB,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;EAA4B,CAAC;AAE1D;;;GAGG;AACH,eAAO,MAAM,kBAAkB;;;EAAyB,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;iBAc3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;iBAA6B,CAAC;AAE3D;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GACrB,CAAC,CAMH;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GACrB,CAAC,GAAG,SAAS,CAMf"}
package/dist/lib/sse.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  /**
2
- * Server-Sent Events (SSE) utilities for Datastar
2
+ * Server-Sent Events (SSE) utilities for Datastar v1.0.0-RC.7
3
3
  *
4
- * Provides helpers for streaming SSE responses that Datastar can consume.
5
- * Datastar uses SSE for real-time UI updates without page reloads.
4
+ * Generates SSE events compatible with the Datastar client's expected format.
6
5
  *
7
6
  * @see https://data-star.dev/
8
7
  *
@@ -11,16 +10,19 @@
11
10
  * app.post("/api/example", (c) => {
12
11
  * return sse(c, async (stream) => {
13
12
  * await stream.patchSignals({ loading: false });
14
- * await stream.patchElements("#result", "<div>Done!</div>");
13
+ * await stream.patchElements('<div id="result">Done!</div>');
14
+ * await stream.redirect("/success");
15
15
  * });
16
16
  * });
17
17
  * ```
18
18
  */
19
19
  import type { Context } from "hono";
20
20
  /**
21
- * Patch modes for DOM updates
21
+ * Patch modes for DOM element updates
22
+ *
23
+ * @see https://data-star.dev/reference/action_plugins/backend/sse
22
24
  */
23
- export type PatchMode = "morph" | "inner" | "outer" | "append" | "prepend" | "remove";
25
+ export type PatchMode = "outer" | "inner" | "replace" | "prepend" | "append" | "before" | "after" | "remove";
24
26
  /**
25
27
  * SSE stream writer for Datastar events
26
28
  */
@@ -29,22 +31,25 @@ export interface SSEStream {
29
31
  * Update reactive signals on the client
30
32
  *
31
33
  * @param signals - Object containing signal values to update
34
+ * @param options - Optional settings (e.g. onlyIfMissing)
32
35
  *
33
36
  * @example
34
37
  * ```ts
35
38
  * await stream.patchSignals({ count: 42, loading: false });
36
39
  * ```
37
40
  */
38
- patchSignals(signals: Record<string, unknown>): Promise<void>;
41
+ patchSignals(signals: Record<string, unknown>, options?: {
42
+ onlyIfMissing?: boolean;
43
+ }): void;
39
44
  /**
40
- * Update DOM elements
45
+ * Update DOM elements via patching
41
46
  *
42
47
  * @param html - HTML content (must include element with id for targeting)
43
- * @param options - Optional mode and selector
48
+ * @param options - Optional patch mode, selector, and view transition
44
49
  *
45
50
  * @example
46
51
  * ```ts
47
- * // Replace element with matching id (default: morph)
52
+ * // Outer patch element with matching id (default)
48
53
  * await stream.patchElements('<div id="content">New content</div>');
49
54
  *
50
55
  * // Append to a container
@@ -57,31 +62,45 @@ export interface SSEStream {
57
62
  patchElements(html: string, options?: {
58
63
  mode?: PatchMode;
59
64
  selector?: string;
60
- }): Promise<void>;
65
+ useViewTransition?: boolean;
66
+ }): void;
67
+ /**
68
+ * Redirect the client to a new URL
69
+ *
70
+ * Uses patchElements internally to inject a script that navigates the client.
71
+ *
72
+ * @param url - The URL to redirect to
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * await stream.redirect('/dash/posts');
77
+ * ```
78
+ */
79
+ redirect(url: string): void;
61
80
  /**
62
- * Execute JavaScript on the client
81
+ * Remove elements matching a CSS selector
63
82
  *
64
- * @param script - JavaScript code to execute
83
+ * @param selector - CSS selector for elements to remove
65
84
  *
66
85
  * @example
67
86
  * ```ts
68
- * await stream.executeScript('console.log("Hello from server")');
87
+ * await stream.remove('#placeholder');
69
88
  * ```
70
89
  */
71
- executeScript(script: string): Promise<void>;
90
+ remove(selector: string): void;
72
91
  }
73
92
  /**
74
93
  * Create an SSE response for Datastar
75
94
  *
76
95
  * @param c - Hono context
77
96
  * @param handler - Async function that writes to the SSE stream
97
+ * @param options - Optional response options (e.g. headers for cookie forwarding)
78
98
  * @returns Response with SSE content-type
79
99
  *
80
100
  * @example
81
101
  * ```ts
82
102
  * app.post("/api/upload", (c) => {
83
103
  * return sse(c, async (stream) => {
84
- * // Process upload...
85
104
  * await stream.patchSignals({ uploading: false });
86
105
  * await stream.patchElements('<div id="new-item">...</div>', {
87
106
  * mode: 'append',
@@ -89,7 +108,16 @@ export interface SSEStream {
89
108
  * });
90
109
  * });
91
110
  * });
111
+ *
112
+ * // With cookie forwarding (for auth)
113
+ * app.post("/signin", (c) => {
114
+ * return sse(c, async (stream) => {
115
+ * await stream.redirect('/dash');
116
+ * }, { headers: { 'Set-Cookie': cookieValue } });
117
+ * });
92
118
  * ```
93
119
  */
94
- export declare function sse(c: Context, handler: (stream: SSEStream) => Promise<void>): Response;
120
+ export declare function sse(c: Context, handler: (stream: SSEStream) => Promise<void>, options?: {
121
+ headers?: Record<string, string>;
122
+ }): Response;
95
123
  //# sourceMappingURL=sse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/lib/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEtF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;;;;OASG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9D;;;;;;;;;;;;;;;;;OAiBG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,SAAS,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9F;;;;;;;;;OASG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAiDvF"}
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/lib/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;;;GAIG;AACH,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,OAAO,GACP,SAAS,GACT,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;;;;;OAUG;IACH,YAAY,CACV,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GACpC,IAAI,CAAC;IAER;;;;;;;;;;;;;;;;;OAiBG;IACH,aAAa,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,SAAS,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B,GACA,IAAI,CAAC;IAER;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,GAAG,CACjB,CAAC,EAAE,OAAO,EACV,OAAO,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,EAC7C,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC7C,QAAQ,CA2EV"}
package/dist/lib/sse.js CHANGED
@@ -1,8 +1,7 @@
1
1
  /**
2
- * Server-Sent Events (SSE) utilities for Datastar
2
+ * Server-Sent Events (SSE) utilities for Datastar v1.0.0-RC.7
3
3
  *
4
- * Provides helpers for streaming SSE responses that Datastar can consume.
5
- * Datastar uses SSE for real-time UI updates without page reloads.
4
+ * Generates SSE events compatible with the Datastar client's expected format.
6
5
  *
7
6
  * @see https://data-star.dev/
8
7
  *
@@ -11,22 +10,37 @@
11
10
  * app.post("/api/example", (c) => {
12
11
  * return sse(c, async (stream) => {
13
12
  * await stream.patchSignals({ loading: false });
14
- * await stream.patchElements("#result", "<div>Done!</div>");
13
+ * await stream.patchElements('<div id="result">Done!</div>');
14
+ * await stream.redirect("/success");
15
15
  * });
16
16
  * });
17
17
  * ```
18
18
  */ /**
19
+ * Format a single SSE event string
20
+ *
21
+ * @param eventType - The Datastar event type (e.g. "datastar-patch-elements")
22
+ * @param dataLines - Array of "key value" data lines
23
+ * @returns Formatted SSE event string
24
+ */ function formatEvent(eventType, dataLines) {
25
+ let event = `event: ${eventType}\n`;
26
+ for (const line of dataLines){
27
+ event += `data: ${line}\n`;
28
+ }
29
+ event += "\n";
30
+ return event;
31
+ }
32
+ /**
19
33
  * Create an SSE response for Datastar
20
34
  *
21
35
  * @param c - Hono context
22
36
  * @param handler - Async function that writes to the SSE stream
37
+ * @param options - Optional response options (e.g. headers for cookie forwarding)
23
38
  * @returns Response with SSE content-type
24
39
  *
25
40
  * @example
26
41
  * ```ts
27
42
  * app.post("/api/upload", (c) => {
28
43
  * return sse(c, async (stream) => {
29
- * // Process upload...
30
44
  * await stream.patchSignals({ uploading: false });
31
45
  * await stream.patchElements('<div id="new-item">...</div>', {
32
46
  * mode: 'append',
@@ -34,48 +48,74 @@
34
48
  * });
35
49
  * });
36
50
  * });
51
+ *
52
+ * // With cookie forwarding (for auth)
53
+ * app.post("/signin", (c) => {
54
+ * return sse(c, async (stream) => {
55
+ * await stream.redirect('/dash');
56
+ * }, { headers: { 'Set-Cookie': cookieValue } });
57
+ * });
37
58
  * ```
38
- */ export function sse(c, handler) {
59
+ */ export function sse(c, handler, options) {
39
60
  const encoder = new TextEncoder();
40
- const stream = new ReadableStream({
61
+ const body = new ReadableStream({
41
62
  async start (controller) {
42
- const write = (data)=>{
43
- controller.enqueue(encoder.encode(data));
44
- };
45
- const sseStream = {
46
- async patchSignals (signals) {
47
- write(`event: datastar-patch-signals\n`);
48
- write(`data: signals ${JSON.stringify(signals)}\n\n`);
63
+ const stream = {
64
+ patchSignals (signals, opts) {
65
+ const dataLines = [
66
+ `signals ${JSON.stringify(signals)}`
67
+ ];
68
+ if (opts?.onlyIfMissing) {
69
+ dataLines.push("onlyIfMissing true");
70
+ }
71
+ controller.enqueue(encoder.encode(formatEvent("datastar-patch-signals", dataLines)));
49
72
  },
50
- async patchElements (html, options = {}) {
51
- write(`event: datastar-patch-elements\n`);
52
- if (options.mode) {
53
- write(`data: mode ${options.mode}\n`);
73
+ patchElements (html, opts) {
74
+ const dataLines = [];
75
+ // Each line of HTML gets its own "elements <line>" data line
76
+ for (const line of html.split("\n")){
77
+ dataLines.push(`elements ${line}`);
78
+ }
79
+ if (opts?.mode) {
80
+ dataLines.push(`mode ${opts.mode}`);
54
81
  }
55
- if (options.selector) {
56
- write(`data: selector ${options.selector}\n`);
82
+ if (opts?.selector) {
83
+ dataLines.push(`selector ${opts.selector}`);
57
84
  }
58
- // Escape newlines in HTML for SSE format
59
- const escapedHtml = html.replace(/\n/g, "\ndata: ");
60
- write(`data: elements ${escapedHtml}\n\n`);
85
+ if (opts?.useViewTransition) {
86
+ dataLines.push("useViewTransition true");
87
+ }
88
+ controller.enqueue(encoder.encode(formatEvent("datastar-patch-elements", dataLines)));
89
+ },
90
+ redirect (url) {
91
+ const escapedUrl = url.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
92
+ const script = `<script data-effect="el.remove()">window.location.href='${escapedUrl}'</script>`;
93
+ const dataLines = [
94
+ `elements ${script}`,
95
+ "mode append",
96
+ "selector body"
97
+ ];
98
+ controller.enqueue(encoder.encode(formatEvent("datastar-patch-elements", dataLines)));
61
99
  },
62
- async executeScript (script) {
63
- write(`event: datastar-execute-script\n`);
64
- write(`data: script ${script}\n\n`);
100
+ remove (selector) {
101
+ controller.enqueue(encoder.encode(formatEvent("datastar-patch-elements", [
102
+ "elements ",
103
+ `mode remove`,
104
+ `selector ${selector}`
105
+ ])));
65
106
  }
66
107
  };
67
- try {
68
- await handler(sseStream);
69
- } finally{
70
- controller.close();
71
- }
108
+ await handler(stream);
109
+ controller.close();
72
110
  }
73
111
  });
74
- return new Response(stream, {
75
- headers: {
76
- "Content-Type": "text/event-stream",
77
- "Cache-Control": "no-cache",
78
- Connection: "keep-alive"
79
- }
112
+ const headers = {
113
+ "Content-Type": "text/event-stream",
114
+ "Cache-Control": "no-cache",
115
+ Connection: "keep-alive",
116
+ ...options?.headers
117
+ };
118
+ return new Response(body, {
119
+ headers
80
120
  });
81
121
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D;;;GAGG;AACH,wBAAgB,WAAW,CAAC,UAAU,SAAY,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAkB1E;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAkBvD"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D;;;GAGG;AACH,wBAAgB,WAAW,CAAC,UAAU,SAAY,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAoB1E;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAoBvD"}
@@ -27,7 +27,6 @@ postsApiRoutes.get("/", async (c)=>{
27
27
  ...p,
28
28
  sqid: sqid.encode(p.id)
29
29
  })),
30
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Array length check guarantees element exists
31
30
  nextCursor: posts.length === limit ? sqid.encode(posts[posts.length - 1].id) : null
32
31
  });
33
32
  });
@@ -56,7 +56,9 @@ uploadApiRoutes.use("*", requireAuthApi());
56
56
  href="/dash/media/${media.id}"
57
57
  class="block aspect-square bg-muted rounded-lg overflow-hidden border hover:border-primary"
58
58
  >
59
- <div class="w-full h-full flex items-center justify-center text-muted-foreground">
59
+ <div
60
+ class="w-full h-full flex items-center justify-center text-muted-foreground"
61
+ >
60
62
  <span class="text-xs">${media.mimeType}</span>
61
63
  </div>
62
64
  </a>
@@ -1 +1 @@
1
- {"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/collections.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAWjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,iBAAiB,kDAAkB,CAAC"}
1
+ {"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/collections.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAYjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,iBAAiB,kDAAkB,CAAC"}