@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/bin/jant.js CHANGED
@@ -71,7 +71,9 @@ function listComponents() {
71
71
  }
72
72
 
73
73
  function generateWrapperCode(componentName, info) {
74
- const importPath = info.isLayout ? "@jant/core/theme/layouts" : "@jant/core/theme/components";
74
+ const importPath = info.isLayout
75
+ ? "@jant/core/theme/layouts"
76
+ : "@jant/core/theme/components";
75
77
 
76
78
  return `/**
77
79
  * Custom ${componentName} component
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AAElD,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAmCvD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AAExE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,MAAM,GAAE,UAAe,GAAG,GAAG,CA+VtD"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AAGlD,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoCvD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AAExE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,MAAM,GAAE,UAAe,GAAG,GAAG,CAodtD"}
package/dist/app.js CHANGED
@@ -5,7 +5,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
5
5
  import { createDatabase } from "./db/index.js";
6
6
  import { createServices } from "./services/index.js";
7
7
  import { createAuth } from "./auth.js";
8
- import { i18nMiddleware, useLingui } from "./i18n/index.js";
8
+ import { i18nMiddleware } from "./i18n/index.js";
9
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
9
10
  // Routes - Pages
10
11
  import { homeRoutes } from "./routes/pages/home.js";
11
12
  import { postRoutes } from "./routes/pages/post.js";
@@ -32,6 +33,7 @@ import { sitemapRoutes } from "./routes/feed/sitemap.js";
32
33
  import { requireAuth } from "./middleware/auth.js";
33
34
  // Layouts for auth pages
34
35
  import { BaseLayout } from "./theme/layouts/index.js";
36
+ import { sse } from "./lib/sse.js";
35
37
  /**
36
38
  * Create a Jant application
37
39
  *
@@ -106,8 +108,8 @@ import { BaseLayout } from "./theme/layouts/index.js";
106
108
  // API Routes
107
109
  app.route("/api/posts", postsApiRoutes);
108
110
  // Setup page component
109
- const SetupContent = ({ error })=>{
110
- const { t } = useLingui();
111
+ const SetupContent = ()=>{
112
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
111
113
  return /*#__PURE__*/ _jsx("div", {
112
114
  class: "min-h-screen flex items-center justify-center",
113
115
  children: /*#__PURE__*/ _jsxs("div", {
@@ -116,28 +118,27 @@ import { BaseLayout } from "./theme/layouts/index.js";
116
118
  /*#__PURE__*/ _jsxs("header", {
117
119
  children: [
118
120
  /*#__PURE__*/ _jsx("h2", {
119
- children: t({
120
- message: "Welcome to Jant",
121
- comment: "@context: Setup page welcome heading"
121
+ children: $__i18n._({
122
+ id: "GorKul",
123
+ message: "Welcome to Jant"
122
124
  })
123
125
  }),
124
126
  /*#__PURE__*/ _jsx("p", {
125
- children: t({
126
- message: "Let's set up your site.",
127
- comment: "@context: Setup page description"
127
+ children: $__i18n._({
128
+ id: "ig4hg2",
129
+ message: "Let's set up your site."
128
130
  })
129
131
  })
130
132
  ]
131
133
  }),
132
134
  /*#__PURE__*/ _jsxs("section", {
133
135
  children: [
134
- error && /*#__PURE__*/ _jsx("p", {
135
- class: "text-destructive text-sm mb-4",
136
- children: error
136
+ /*#__PURE__*/ _jsx("div", {
137
+ id: "setup-message"
137
138
  }),
138
139
  /*#__PURE__*/ _jsxs("form", {
139
- method: "post",
140
- action: "/setup",
140
+ "data-signals": "{siteName: '', name: '', email: '', password: ''}",
141
+ "data-on:submit__prevent": "@post('/setup')",
141
142
  class: "flex flex-col gap-4",
142
143
  children: [
143
144
  /*#__PURE__*/ _jsxs("div", {
@@ -145,19 +146,19 @@ import { BaseLayout } from "./theme/layouts/index.js";
145
146
  children: [
146
147
  /*#__PURE__*/ _jsx("label", {
147
148
  class: "label",
148
- children: t({
149
- message: "Site Name",
150
- comment: "@context: Setup form field - site name"
149
+ children: $__i18n._({
150
+ id: "SJmfuf",
151
+ message: "Site Name"
151
152
  })
152
153
  }),
153
154
  /*#__PURE__*/ _jsx("input", {
154
155
  type: "text",
155
- name: "siteName",
156
+ "data-bind": "siteName",
156
157
  class: "input",
157
158
  required: true,
158
- placeholder: t({
159
- message: "My Blog",
160
- comment: "@context: Setup site name placeholder"
159
+ placeholder: $__i18n._({
160
+ id: "HfyyXl",
161
+ message: "My Blog"
161
162
  })
162
163
  })
163
164
  ]
@@ -167,14 +168,14 @@ import { BaseLayout } from "./theme/layouts/index.js";
167
168
  children: [
168
169
  /*#__PURE__*/ _jsx("label", {
169
170
  class: "label",
170
- children: t({
171
- message: "Your Name",
172
- comment: "@context: Setup form field - user name"
171
+ children: $__i18n._({
172
+ id: "/Rj5P4",
173
+ message: "Your Name"
173
174
  })
174
175
  }),
175
176
  /*#__PURE__*/ _jsx("input", {
176
177
  type: "text",
177
- name: "name",
178
+ "data-bind": "name",
178
179
  class: "input",
179
180
  required: true,
180
181
  placeholder: "John Doe"
@@ -186,14 +187,14 @@ import { BaseLayout } from "./theme/layouts/index.js";
186
187
  children: [
187
188
  /*#__PURE__*/ _jsx("label", {
188
189
  class: "label",
189
- children: t({
190
- message: "Email",
191
- comment: "@context: Setup/signin form field - email"
190
+ children: $__i18n._({
191
+ id: "O3oNi5",
192
+ message: "Email"
192
193
  })
193
194
  }),
194
195
  /*#__PURE__*/ _jsx("input", {
195
196
  type: "email",
196
- name: "email",
197
+ "data-bind": "email",
197
198
  class: "input",
198
199
  required: true,
199
200
  placeholder: "you@example.com"
@@ -205,14 +206,14 @@ import { BaseLayout } from "./theme/layouts/index.js";
205
206
  children: [
206
207
  /*#__PURE__*/ _jsx("label", {
207
208
  class: "label",
208
- children: t({
209
- message: "Password",
210
- comment: "@context: Setup/signin form field - password"
209
+ children: $__i18n._({
210
+ id: "8ZsakT",
211
+ message: "Password"
211
212
  })
212
213
  }),
213
214
  /*#__PURE__*/ _jsx("input", {
214
215
  type: "password",
215
- name: "password",
216
+ "data-bind": "password",
216
217
  class: "input",
217
218
  required: true,
218
219
  minLength: 8
@@ -222,9 +223,9 @@ import { BaseLayout } from "./theme/layouts/index.js";
222
223
  /*#__PURE__*/ _jsx("button", {
223
224
  type: "submit",
224
225
  class: "btn",
225
- children: t({
226
- message: "Complete Setup",
227
- comment: "@context: Setup form submit button"
226
+ children: $__i18n._({
227
+ id: "EGwzOK",
228
+ message: "Complete Setup"
228
229
  })
229
230
  })
230
231
  ]
@@ -239,31 +240,31 @@ import { BaseLayout } from "./theme/layouts/index.js";
239
240
  app.get("/setup", async (c)=>{
240
241
  const isComplete = await c.var.services.settings.isOnboardingComplete();
241
242
  if (isComplete) return c.redirect("/");
242
- const error = c.req.query("error");
243
243
  return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
244
244
  title: "Setup - Jant",
245
245
  c: c,
246
- children: /*#__PURE__*/ _jsx(SetupContent, {
247
- error: error
248
- })
246
+ children: /*#__PURE__*/ _jsx(SetupContent, {})
249
247
  }));
250
248
  });
251
249
  app.post("/setup", async (c)=>{
252
250
  const isComplete = await c.var.services.settings.isOnboardingComplete();
253
251
  if (isComplete) return c.redirect("/");
254
- const formData = await c.req.formData();
255
- const siteName = formData.get("siteName");
256
- const name = formData.get("name");
257
- const email = formData.get("email");
258
- const password = formData.get("password");
252
+ const body = await c.req.json();
253
+ const { siteName, name, email, password } = body;
259
254
  if (!siteName || !name || !email || !password) {
260
- return c.redirect("/setup?error=All fields are required");
255
+ return sse(c, async (stream)=>{
256
+ await stream.patchElements('<div id="setup-message"><p class="text-destructive text-sm mb-4">All fields are required</p></div>');
257
+ });
261
258
  }
262
259
  if (password.length < 8) {
263
- return c.redirect("/setup?error=Password must be at least 8 characters");
260
+ return sse(c, async (stream)=>{
261
+ await stream.patchElements('<div id="setup-message"><p class="text-destructive text-sm mb-4">Password must be at least 8 characters</p></div>');
262
+ });
264
263
  }
265
264
  if (!c.var.auth) {
266
- return c.redirect("/setup?error=AUTH_SECRET not configured");
265
+ return sse(c, async (stream)=>{
266
+ await stream.patchElements('<div id="setup-message"><p class="text-destructive text-sm mb-4">AUTH_SECRET not configured</p></div>');
267
+ });
267
268
  }
268
269
  try {
269
270
  const signUpResponse = await c.var.auth.api.signUpEmail({
@@ -274,23 +275,33 @@ import { BaseLayout } from "./theme/layouts/index.js";
274
275
  }
275
276
  });
276
277
  if (!signUpResponse || "error" in signUpResponse) {
277
- return c.redirect("/setup?error=Failed to create account");
278
+ return sse(c, async (stream)=>{
279
+ await stream.patchElements('<div id="setup-message"><p class="text-destructive text-sm mb-4">Failed to create account</p></div>');
280
+ });
278
281
  }
279
282
  await c.var.services.settings.setMany({
280
283
  SITE_NAME: siteName,
281
284
  SITE_LANGUAGE: "en"
282
285
  });
283
286
  await c.var.services.settings.completeOnboarding();
284
- return c.redirect("/signin");
287
+ return sse(c, async (stream)=>{
288
+ await stream.redirect("/signin");
289
+ });
285
290
  } catch (err) {
286
291
  // eslint-disable-next-line no-console -- Error logging is intentional
287
292
  console.error("Setup error:", err);
288
- return c.redirect("/setup?error=Failed to create account");
293
+ return sse(c, async (stream)=>{
294
+ await stream.patchElements('<div id="setup-message"><p class="text-destructive text-sm mb-4">Failed to create account</p></div>');
295
+ });
289
296
  }
290
297
  });
291
298
  // Signin page component
292
- const SigninContent = ({ error })=>{
293
- const { t } = useLingui();
299
+ const SigninContent = ({ demoEmail, demoPassword })=>{
300
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
301
+ const signals = JSON.stringify({
302
+ email: demoEmail || "",
303
+ password: demoPassword || ""
304
+ }).replace(/</g, "\\u003c");
294
305
  return /*#__PURE__*/ _jsx("div", {
295
306
  class: "min-h-screen flex items-center justify-center",
296
307
  children: /*#__PURE__*/ _jsxs("div", {
@@ -298,21 +309,27 @@ import { BaseLayout } from "./theme/layouts/index.js";
298
309
  children: [
299
310
  /*#__PURE__*/ _jsx("header", {
300
311
  children: /*#__PURE__*/ _jsx("h2", {
301
- children: t({
302
- message: "Sign In",
303
- comment: "@context: Sign in page heading"
312
+ children: $__i18n._({
313
+ id: "n1ekoW",
314
+ message: "Sign In"
304
315
  })
305
316
  })
306
317
  }),
307
318
  /*#__PURE__*/ _jsxs("section", {
308
319
  children: [
309
- error && /*#__PURE__*/ _jsx("p", {
310
- class: "text-destructive text-sm mb-4",
311
- children: error
320
+ /*#__PURE__*/ _jsx("div", {
321
+ id: "signin-message"
322
+ }),
323
+ demoEmail && demoPassword && /*#__PURE__*/ _jsx("p", {
324
+ class: "text-muted-foreground text-sm mb-4",
325
+ children: $__i18n._({
326
+ id: "er8+x7",
327
+ message: "Demo account pre-filled. Just click Sign In."
328
+ })
312
329
  }),
313
330
  /*#__PURE__*/ _jsxs("form", {
314
- method: "post",
315
- action: "/signin",
331
+ "data-signals": signals,
332
+ "data-on:submit__prevent": "@post('/signin')",
316
333
  class: "flex flex-col gap-4",
317
334
  children: [
318
335
  /*#__PURE__*/ _jsxs("div", {
@@ -320,14 +337,14 @@ import { BaseLayout } from "./theme/layouts/index.js";
320
337
  children: [
321
338
  /*#__PURE__*/ _jsx("label", {
322
339
  class: "label",
323
- children: t({
324
- message: "Email",
325
- comment: "@context: Setup/signin form field - email"
340
+ children: $__i18n._({
341
+ id: "O3oNi5",
342
+ message: "Email"
326
343
  })
327
344
  }),
328
345
  /*#__PURE__*/ _jsx("input", {
329
346
  type: "email",
330
- name: "email",
347
+ "data-bind": "email",
331
348
  class: "input",
332
349
  required: true
333
350
  })
@@ -338,14 +355,14 @@ import { BaseLayout } from "./theme/layouts/index.js";
338
355
  children: [
339
356
  /*#__PURE__*/ _jsx("label", {
340
357
  class: "label",
341
- children: t({
342
- message: "Password",
343
- comment: "@context: Setup/signin form field - password"
358
+ children: $__i18n._({
359
+ id: "8ZsakT",
360
+ message: "Password"
344
361
  })
345
362
  }),
346
363
  /*#__PURE__*/ _jsx("input", {
347
364
  type: "password",
348
- name: "password",
365
+ "data-bind": "password",
349
366
  class: "input",
350
367
  required: true
351
368
  })
@@ -354,9 +371,9 @@ import { BaseLayout } from "./theme/layouts/index.js";
354
371
  /*#__PURE__*/ _jsx("button", {
355
372
  type: "submit",
356
373
  class: "btn",
357
- children: t({
358
- message: "Sign In",
359
- comment: "@context: Sign in form submit button"
374
+ children: $__i18n._({
375
+ id: "n1ekoW",
376
+ message: "Sign In"
360
377
  })
361
378
  })
362
379
  ]
@@ -369,22 +386,23 @@ import { BaseLayout } from "./theme/layouts/index.js";
369
386
  };
370
387
  // Signin page
371
388
  app.get("/signin", async (c)=>{
372
- const error = c.req.query("error");
373
389
  return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
374
390
  title: "Sign In - Jant",
375
391
  c: c,
376
392
  children: /*#__PURE__*/ _jsx(SigninContent, {
377
- error: error
393
+ demoEmail: c.env.DEMO_EMAIL,
394
+ demoPassword: c.env.DEMO_PASSWORD
378
395
  })
379
396
  }));
380
397
  });
381
398
  app.post("/signin", async (c)=>{
382
399
  if (!c.var.auth) {
383
- return c.redirect("/signin?error=Auth not configured");
400
+ return sse(c, async (stream)=>{
401
+ await stream.patchElements('<div id="signin-message"><p class="text-destructive text-sm mb-4">Auth not configured</p></div>');
402
+ });
384
403
  }
385
- const formData = await c.req.formData();
386
- const email = formData.get("email");
387
- const password = formData.get("password");
404
+ const body = await c.req.json();
405
+ const { email, password } = body;
388
406
  try {
389
407
  const signInRequest = new Request(`${c.env.SITE_URL}/api/auth/sign-in/email`, {
390
408
  method: "POST",
@@ -398,18 +416,27 @@ import { BaseLayout } from "./theme/layouts/index.js";
398
416
  });
399
417
  const response = await c.var.auth.handler(signInRequest);
400
418
  if (!response.ok) {
401
- return c.redirect("/signin?error=Invalid email or password");
419
+ return sse(c, async (stream)=>{
420
+ await stream.patchElements('<div id="signin-message"><p class="text-destructive text-sm mb-4">Invalid email or password</p></div>');
421
+ });
422
+ }
423
+ // Forward Set-Cookie headers from auth response
424
+ const cookieHeaders = {};
425
+ const setCookie = response.headers.get("set-cookie");
426
+ if (setCookie) {
427
+ cookieHeaders["Set-Cookie"] = setCookie;
402
428
  }
403
- const headers = new Headers(response.headers);
404
- headers.set("Location", "/dash");
405
- return new Response(null, {
406
- status: 302,
407
- headers
429
+ return sse(c, async (stream)=>{
430
+ await stream.redirect("/dash");
431
+ }, {
432
+ headers: cookieHeaders
408
433
  });
409
434
  } catch (err) {
410
435
  // eslint-disable-next-line no-console -- Error logging is intentional
411
436
  console.error("Signin error:", err);
412
- return c.redirect("/signin?error=Invalid email or password");
437
+ return sse(c, async (stream)=>{
438
+ await stream.patchElements('<div id="signin-message"><p class="text-destructive text-sm mb-4">Invalid email or password</p></div>');
439
+ });
413
440
  }
414
441
  });
415
442
  app.get("/signout", async (c)=>{
package/dist/auth.d.ts CHANGED
@@ -11,6 +11,7 @@ export declare function createAuth(d1: D1Database, options: {
11
11
  emailAndPassword: {
12
12
  enabled: true;
13
13
  autoSignIn: true;
14
+ minPasswordLength: number;
14
15
  };
15
16
  session: {
16
17
  cookieCache: {
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,UAAU,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;GA0BtF;AAED,MAAM,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,UAAU,CACxB,EAAE,EAAE,UAAU,EACd,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;GA4B7C;AAED,MAAM,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC"}
package/dist/auth.js CHANGED
@@ -22,7 +22,8 @@ export function createAuth(d1, options) {
22
22
  baseURL: options.baseURL,
23
23
  emailAndPassword: {
24
24
  enabled: true,
25
- autoSignIn: true
25
+ autoSignIn: true,
26
+ minPasswordLength: 8
26
27
  },
27
28
  session: {
28
29
  cookieCache: {
package/dist/client.js CHANGED
@@ -5,6 +5,6 @@
5
5
  * - Datastar (reactivity)
6
6
  * - BaseCoat (dialogs, dropdowns)
7
7
  * - ImageProcessor (media uploads)
8
- */ import "@sudodevnull/datastar";
8
+ */ import "./vendor/datastar.js";
9
9
  import "basecoat-css/all";
10
10
  import "./lib/image-processor.js";
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBhB,CAAC;AAMH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYhB,CAAC;AAMH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOtB,CAAC;AAMH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY3B,CAAC;AAMF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMpB,CAAC;AAMH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAInB,CAAC;AAOH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASf,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWlB,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBlB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOvB,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBhB,CAAC;AAMH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYhB,CAAC;AAMH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOtB,CAAC;AAMH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY3B,CAAC;AAMF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMpB,CAAC;AAMH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAInB,CAAC;AAOH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWf,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWlB,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoBlB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOvB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/i18n/context.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,cAAc,CAAC;AAG5D;;;GAGG;AACH,KAAK,qBAAqB,GAAG;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAKF;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,CAAC,EAAE,OAAO,CAAC;CACZ;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAM9C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS;;oBASQ,qBAAqB;oBAArB,qBAAqB;EAcrD"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/i18n/context.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,cAAc,CAAC;AAG5D;;;GAGG;AACH,KAAK,qBAAqB,GAAG;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAKF;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,CAAC,EAAE,OAAO,CAAC;CACZ;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAM9C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS;;oBAQQ,qBAAqB;oBAArB,qBAAqB;EAYrD"}
@@ -44,10 +44,7 @@ export const I18nProvider = ({ c, children })=>{
44
44
  if (!currentI18n) {
45
45
  throw new Error("useLingui() called outside of I18nProvider. " + "Make sure your component is wrapped in <I18nProvider c={c}>...</I18nProvider>");
46
46
  }
47
- // Create translation function that accepts both pre-macro and post-macro formats
48
47
  const translate = (descriptor)=>{
49
- // The macro will add the id, or it's already present
50
- // At runtime, we pass it to i18n._ which handles the descriptor with values
51
48
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- currentI18n is checked above
52
49
  return currentI18n._(descriptor);
53
50
  };
@@ -1,9 +1,7 @@
1
1
  /**
2
2
  * Language Detection Utilities
3
3
  */
4
- import type { Context } from "hono";
5
4
  import { type Locale } from "./locales.js";
6
- export declare const LANGUAGE_COOKIE_NAME = "lang";
7
5
  /**
8
6
  * Get display name for a language code
9
7
  */
@@ -19,13 +17,4 @@ export declare function getSupportedLanguages(): Array<{
19
17
  * Check if a language code is valid
20
18
  */
21
19
  export declare function isValidLanguage(lang: unknown): lang is Locale;
22
- /**
23
- * Parse Accept-Language header and return best matching locale
24
- */
25
- export declare function parseAcceptLanguage(header: string | null): Locale;
26
- /**
27
- * Detect user's preferred language from Hono context
28
- * Priority: Cookie > Accept-Language header > Default
29
- */
30
- export declare function detectLanguage(c: Context): Locale;
31
20
  //# sourceMappingURL=detect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/i18n/detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAiC,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE1E,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAE3C;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAK7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAwCjE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAYjD"}
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/i18n/detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAqB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE9D;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAK7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAE7D"}
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Language Detection Utilities
3
- */ import { locales, baseLocale, isLocale } from "./locales.js";
4
- export const LANGUAGE_COOKIE_NAME = "lang";
3
+ */ import { locales, isLocale } from "./locales.js";
5
4
  /**
6
5
  * Get display name for a language code
7
6
  */ export function getLanguageDisplayName(locale) {
@@ -25,53 +24,3 @@ export const LANGUAGE_COOKIE_NAME = "lang";
25
24
  */ export function isValidLanguage(lang) {
26
25
  return isLocale(lang);
27
26
  }
28
- /**
29
- * Parse Accept-Language header and return best matching locale
30
- */ export function parseAcceptLanguage(header) {
31
- if (!header) return baseLocale;
32
- // Parse "en-US,en;q=0.9,zh-CN;q=0.8" format
33
- const languages = header.split(",").map((part)=>{
34
- const [lang, qPart] = part.trim().split(";");
35
- const q = qPart ? parseFloat(qPart.replace("q=", "")) : 1;
36
- return {
37
- lang: lang?.trim() ?? "",
38
- q
39
- };
40
- }).sort((a, b)=>b.q - a.q);
41
- for (const { lang } of languages){
42
- // Direct match
43
- if (isLocale(lang)) {
44
- return lang;
45
- }
46
- // Map common variants
47
- const normalized = lang.toLowerCase();
48
- if (normalized.startsWith("zh-cn") || normalized.startsWith("zh-hans")) {
49
- return "zh-Hans";
50
- }
51
- if (normalized.startsWith("zh-tw") || normalized.startsWith("zh-hk") || normalized.startsWith("zh-hant")) {
52
- return "zh-Hant";
53
- }
54
- if (normalized.startsWith("zh")) {
55
- return "zh-Hans"; // Default Chinese to Simplified
56
- }
57
- if (normalized.startsWith("en")) {
58
- return "en";
59
- }
60
- }
61
- return baseLocale;
62
- }
63
- /**
64
- * Detect user's preferred language from Hono context
65
- * Priority: Cookie > Accept-Language header > Default
66
- */ export function detectLanguage(c) {
67
- // 1. Check cookie (using getCookie helper)
68
- const cookies = c.req.raw.headers.get("Cookie") ?? "";
69
- const cookieMatch = cookies.match(new RegExp(`${LANGUAGE_COOKIE_NAME}=([^;]+)`));
70
- const cookieLang = cookieMatch?.[1];
71
- if (cookieLang && isLocale(cookieLang)) {
72
- return cookieLang;
73
- }
74
- // 2. Check Accept-Language header
75
- const acceptLang = c.req.header("Accept-Language") ?? null;
76
- return parseAcceptLanguage(acceptLang);
77
- }
@@ -1,19 +1,9 @@
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
  */
18
8
  import { I18n } from "@lingui/core";
19
9
  import { locales, baseLocale, isLocale, type Locale } from "./locales.js";
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/i18n/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAK1E,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;AAGtD,YAAY,EAAE,IAAI,EAAE,CAAC;AAErB;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAY/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE;IAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAE3D"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/i18n/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAK1E,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;AAGtD,YAAY,EAAE,IAAI,EAAE,CAAC;AASrB;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAU/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE;IAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAE3D"}