@naeil/ui 0.9.0 → 0.11.0

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 (61) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +5 -5
  3. package/dist/{chunk-XRO3NJAB.js → chunk-KWEWR46R.js} +40 -154
  4. package/dist/{chunk-JDHGKM25.js → chunk-U3IZCFM4.js} +267 -2
  5. package/dist/components/index.js +12 -3
  6. package/dist/components/naeil-footer.d.ts +3 -3
  7. package/dist/components/naeil-footer.js +14 -11
  8. package/dist/components/naeil-header.d.ts +7 -9
  9. package/dist/components/naeil-header.js +2 -2
  10. package/dist/lib/ui-release.d.ts +1 -1
  11. package/dist/lib/ui-release.js +1 -1
  12. package/dist/naeil-locale/checker.d.ts +16 -0
  13. package/dist/naeil-locale/checker.js +91 -0
  14. package/dist/naeil-locale/chrome.d.ts +150 -0
  15. package/dist/naeil-locale/chrome.js +2385 -0
  16. package/dist/naeil-locale/chunk-4U64K4J3.js +56 -0
  17. package/dist/naeil-locale/chunk-N3ETBM74.js +24 -0
  18. package/dist/naeil-locale/chunk-U65OQHZY.js +167 -0
  19. package/dist/naeil-locale/chunk-YQ5OJWBF.js +53 -0
  20. package/dist/naeil-locale/client.d.ts +70 -0
  21. package/dist/naeil-locale/client.js +388 -0
  22. package/dist/naeil-locale/en-ZC66VDHP.js +86 -0
  23. package/dist/naeil-locale/index.d.ts +40 -0
  24. package/dist/naeil-locale/index.js +111 -0
  25. package/dist/naeil-locale/ja-DKIEQUG7.js +86 -0
  26. package/dist/naeil-locale/ko-CY6663RZ.js +86 -0
  27. package/dist/naeil-locale/messages-BuQvB-u2.d.ts +167 -0
  28. package/dist/naeil-locale/messages.d.ts +1 -0
  29. package/dist/naeil-locale/messages.js +14 -0
  30. package/dist/naeil-locale/server.d.ts +75 -0
  31. package/dist/naeil-locale/server.js +172 -0
  32. package/dist/source/components/naeil-footer-core.d.ts +16 -0
  33. package/dist/source/components/naeil-footer-core.js +93 -0
  34. package/dist/source/components/naeil-footer.d.ts +6 -11
  35. package/dist/source/components/naeil-footer.js +4 -75
  36. package/dist/source/components/naeil-header-account-core.d.ts +26 -0
  37. package/dist/source/components/naeil-header-account-core.js +98 -0
  38. package/dist/source/components/naeil-header-account.d.ts +6 -22
  39. package/dist/source/components/naeil-header-account.js +5 -81
  40. package/dist/source/components/naeil-header-content.d.ts +102 -109
  41. package/dist/source/components/naeil-header-content.js +6 -142
  42. package/dist/source/components/naeil-header-core.d.ts +59 -0
  43. package/dist/source/components/naeil-header-core.js +231 -0
  44. package/dist/source/components/naeil-header-data.d.ts +11 -0
  45. package/dist/source/components/naeil-header-data.js +14 -0
  46. package/dist/source/components/naeil-header.d.ts +10 -51
  47. package/dist/source/components/naeil-header.js +9 -200
  48. package/dist/source/components/naeil-messages-context.d.ts +94 -0
  49. package/dist/source/components/naeil-messages-context.js +16 -0
  50. package/dist/source/components/naeil-standalone-messages.d.ts +11 -0
  51. package/dist/source/components/naeil-standalone-messages.js +13 -0
  52. package/dist/source/i18n/routing.d.ts +22 -20
  53. package/dist/source/lib/ui-release.d.ts +1 -1
  54. package/dist/source/lib/ui-release.js +1 -1
  55. package/dist/source/naeil-locale/messages/en.json +78 -0
  56. package/dist/source/naeil-locale/messages/ja.json +78 -0
  57. package/dist/source/naeil-locale/messages/ko.json +78 -0
  58. package/docs/components/naeil-locale.md +52 -0
  59. package/docs/package-release.md +31 -6
  60. package/package.json +35 -7
  61. /package/dist/{naeil-header-content-BvISJ4RV.d.ts → naeil-header-data-BvISJ4RV.d.ts} +0 -0
@@ -0,0 +1,86 @@
1
+ import "./chunk-N3ETBM74.js";
2
+
3
+ // src/naeil-locale/messages/ja.json
4
+ var naeil = {
5
+ header: {
6
+ nav: {
7
+ home: "\u30DB\u30FC\u30E0",
8
+ projects: "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8",
9
+ blog: "\u30D6\u30ED\u30B0",
10
+ navigation: "\u30E1\u30A4\u30F3\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3",
11
+ menu: "\u30E1\u30CB\u30E5\u30FC",
12
+ closeMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B"
13
+ },
14
+ theme: {
15
+ switchToLight: "\u30E9\u30A4\u30C8\u30C6\u30FC\u30DE\u306B\u5207\u308A\u66FF\u3048\u308B",
16
+ switchToDark: "\u30C0\u30FC\u30AF\u30C6\u30FC\u30DE\u306B\u5207\u308A\u66FF\u3048\u308B"
17
+ },
18
+ locale: {
19
+ switchLabel: "\u8A00\u8A9E"
20
+ },
21
+ projects: {
22
+ cc: {
23
+ name: "Content Collector",
24
+ description: "RSS\u3001YouTube\u3001Reddit\u306E\u81EA\u52D5\u53CE\u96C6 + AI\u8981\u7D04"
25
+ },
26
+ pkm: {
27
+ name: "PKM",
28
+ description: "\u500B\u4EBA\u30CA\u30EC\u30C3\u30B8\u7BA1\u7406 \u2014 \u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u89E3\u6790\u3001\u57CB\u3081\u8FBC\u307F\u3001\u30BB\u30DE\u30F3\u30C6\u30A3\u30C3\u30AF\u691C\u7D22"
29
+ },
30
+ naeilUi: {
31
+ name: "naeil-ui",
32
+ description: "\u30DF\u30CB\u30DE\u30EB\u30C7\u30B6\u30A4\u30F3\u30B7\u30B9\u30C6\u30E0 \u2014 OKLCH\u30C8\u30FC\u30AF\u30F3\u3001Tailwind v4\u3001shadcn"
33
+ },
34
+ sa: {
35
+ name: "Sustainability Analyzer",
36
+ description: "ESG\u30EC\u30DD\u30FC\u30C8AI\u5206\u6790 \u2014 PDF\u89E3\u6790\u3001\u5B9A\u6027\u8A55\u4FA1\u3001\u6BD4\u8F03\u8868\u306E\u81EA\u52D5\u751F\u6210"
37
+ },
38
+ babyAgent: {
39
+ name: "Baby Agent",
40
+ description: "\u80B2\u5150AI\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8 \u2014 LINE Q&A\u3001\u8A18\u9332\u3001\u30EA\u30DE\u30A4\u30F3\u30C0\u30FC"
41
+ },
42
+ status: {
43
+ active: "\u30A2\u30AF\u30C6\u30A3\u30D6",
44
+ coming: "\u6E96\u5099\u4E2D"
45
+ }
46
+ }
47
+ },
48
+ account: {
49
+ menu: "\u30A2\u30AB\u30A6\u30F3\u30C8\u30E1\u30CB\u30E5\u30FC",
50
+ account: "\u30A2\u30AB\u30A6\u30F3\u30C8",
51
+ login: "\u30ED\u30B0\u30A4\u30F3",
52
+ logout: "\u30ED\u30B0\u30A2\u30A6\u30C8",
53
+ busy: "\u30ED\u30B0\u30A2\u30A6\u30C8\u4E2D\u2026"
54
+ },
55
+ footer: {
56
+ navigation: "\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3",
57
+ projects: "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8",
58
+ blog: "\u30D6\u30ED\u30B0",
59
+ social: "\u30BD\u30FC\u30B7\u30E3\u30EB",
60
+ description: "Tomorrow starts here."
61
+ },
62
+ locale: {
63
+ names: {
64
+ en: "English",
65
+ ko: "\uD55C\uAD6D\uC5B4",
66
+ ja: "\u65E5\u672C\u8A9E"
67
+ },
68
+ pending: "\u8A00\u8A9E\u3092\u5909\u66F4\u3057\u3066\u3044\u307E\u3059\u2026",
69
+ failed: "\u8A00\u8A9E\u3092\u5909\u66F4\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u4F5C\u696D\u5185\u5BB9\u306F\u4FDD\u6301\u3055\u308C\u3066\u3044\u307E\u3059\u3002",
70
+ retry: "\u518D\u8A66\u884C",
71
+ errors: {
72
+ badRequest: "\u3053\u306E\u30A2\u30C9\u30EC\u30B9\u306F\u7121\u52B9\u3067\u3059\u3002",
73
+ notFound: "\u30DA\u30FC\u30B8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002",
74
+ unauthenticated: "\u7D9A\u3051\u308B\u306B\u306F\u30ED\u30B0\u30A4\u30F3\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
75
+ forbidden: "\u3053\u306E\u30DA\u30FC\u30B8\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093\u3002",
76
+ unavailable: "\u30B5\u30FC\u30D3\u30B9\u3092\u4E00\u6642\u7684\u306B\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002"
77
+ }
78
+ }
79
+ };
80
+ var ja_default = {
81
+ naeil
82
+ };
83
+ export {
84
+ ja_default as default,
85
+ naeil
86
+ };
@@ -0,0 +1,86 @@
1
+ import "./chunk-N3ETBM74.js";
2
+
3
+ // src/naeil-locale/messages/ko.json
4
+ var naeil = {
5
+ header: {
6
+ nav: {
7
+ home: "\uD648",
8
+ projects: "\uD504\uB85C\uC81D\uD2B8",
9
+ blog: "\uBE14\uB85C\uADF8",
10
+ navigation: "\uC8FC\uC694 \uBA54\uB274",
11
+ menu: "\uBA54\uB274",
12
+ closeMenu: "\uBA54\uB274 \uB2EB\uAE30"
13
+ },
14
+ theme: {
15
+ switchToLight: "\uBC1D\uC740 \uD14C\uB9C8\uB85C \uC804\uD658",
16
+ switchToDark: "\uC5B4\uB450\uC6B4 \uD14C\uB9C8\uB85C \uC804\uD658"
17
+ },
18
+ locale: {
19
+ switchLabel: "\uC5B8\uC5B4"
20
+ },
21
+ projects: {
22
+ cc: {
23
+ name: "Content Collector",
24
+ description: "RSS, YouTube, Reddit \uC790\uB3D9 \uC218\uC9D1 + AI \uC694\uC57D"
25
+ },
26
+ pkm: {
27
+ name: "PKM",
28
+ description: "\uAC1C\uC778 \uC9C0\uC2DD \uAD00\uB9AC \u2014 \uBB38\uC11C \uD30C\uC2F1, \uC784\uBCA0\uB529, \uC2DC\uB9E8\uD2F1 \uAC80\uC0C9"
29
+ },
30
+ naeilUi: {
31
+ name: "naeil-ui",
32
+ description: "\uBBF8\uB2C8\uBA40 \uB514\uC790\uC778 \uC2DC\uC2A4\uD15C \u2014 OKLCH \uD1A0\uD070, Tailwind v4, shadcn"
33
+ },
34
+ sa: {
35
+ name: "Sustainability Analyzer",
36
+ description: "ESG \uB9AC\uD3EC\uD2B8 AI \uBD84\uC11D \u2014 PDF \uD30C\uC2F1, \uC815\uC131\uD3C9\uAC00, \uBE44\uAD50\uD45C \uC790\uB3D9 \uC0DD\uC131"
37
+ },
38
+ babyAgent: {
39
+ name: "Baby Agent",
40
+ description: "\uC721\uC544 AI \uC5D0\uC774\uC804\uD2B8 \u2014 LINE \uAE30\uBC18 Q&A, \uAE30\uB85D, \uB9AC\uB9C8\uC778\uB354"
41
+ },
42
+ status: {
43
+ active: "\uD65C\uC131",
44
+ coming: "\uC900\uBE44 \uC911"
45
+ }
46
+ }
47
+ },
48
+ account: {
49
+ menu: "\uACC4\uC815 \uBA54\uB274",
50
+ account: "\uACC4\uC815",
51
+ login: "\uB85C\uADF8\uC778",
52
+ logout: "\uB85C\uADF8\uC544\uC6C3",
53
+ busy: "\uB85C\uADF8\uC544\uC6C3 \uC911\u2026"
54
+ },
55
+ footer: {
56
+ navigation: "\uB124\uBE44\uAC8C\uC774\uC158",
57
+ projects: "\uD504\uB85C\uC81D\uD2B8",
58
+ blog: "\uBE14\uB85C\uADF8",
59
+ social: "\uC18C\uC15C",
60
+ description: "Tomorrow starts here."
61
+ },
62
+ locale: {
63
+ names: {
64
+ en: "English",
65
+ ko: "\uD55C\uAD6D\uC5B4",
66
+ ja: "\u65E5\u672C\u8A9E"
67
+ },
68
+ pending: "\uC5B8\uC5B4\uB97C \uBCC0\uACBD\uD558\uB294 \uC911\u2026",
69
+ failed: "\uC5B8\uC5B4\uB97C \uBCC0\uACBD\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC791\uC5C5 \uB0B4\uC6A9\uC740 \uC720\uC9C0\uB429\uB2C8\uB2E4.",
70
+ retry: "\uB2E4\uC2DC \uC2DC\uB3C4",
71
+ errors: {
72
+ badRequest: "\uC62C\uBC14\uB974\uC9C0 \uC54A\uC740 \uC8FC\uC18C\uC785\uB2C8\uB2E4.",
73
+ notFound: "\uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
74
+ unauthenticated: "\uACC4\uC18D\uD558\uB824\uBA74 \uB85C\uADF8\uC778\uD558\uC138\uC694.",
75
+ forbidden: "\uC774 \uD398\uC774\uC9C0\uC5D0 \uC811\uADFC\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
76
+ unavailable: "\uC77C\uC2DC\uC801\uC73C\uB85C \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694."
77
+ }
78
+ }
79
+ };
80
+ var ko_default = {
81
+ naeil
82
+ };
83
+ export {
84
+ ko_default as default,
85
+ naeil
86
+ };
@@ -0,0 +1,167 @@
1
+ /** Opt-in owned-service routing. The legacy public i18n/routing entry is unchanged. */
2
+ declare const naeilLocales: readonly ["en", "ko", "ja"];
3
+ type NaeilLocale = (typeof naeilLocales)[number];
4
+ declare const defaultLocale: NaeilLocale;
5
+ declare const naeilRouting: {
6
+ locales: readonly ["en", "ko", "ja"];
7
+ defaultLocale: "en";
8
+ localePrefix: "as-needed";
9
+ localeDetection: false;
10
+ localeCookie: false;
11
+ alternateLinks: false;
12
+ };
13
+ declare function isNaeilLocale(value: unknown): value is NaeilLocale;
14
+ declare function assertLocale(value: unknown): NaeilLocale;
15
+ type NaeilServiceId = "main" | "jev" | "estimate" | "abstorm";
16
+ interface NaeilRoute {
17
+ path: string;
18
+ protected?: boolean;
19
+ }
20
+ interface NaeilLocaleService {
21
+ id: NaeilServiceId;
22
+ origin: string;
23
+ routes: readonly (string | NaeilRoute)[];
24
+ protocolPrefixes?: readonly string[];
25
+ /** Explicitly audited UI routes within an otherwise protected namespace. */
26
+ uiProtocolExceptions?: readonly string[];
27
+ }
28
+ declare function defineLocaleService(service: NaeilLocaleService): NaeilLocaleService;
29
+ declare const naeilServices: {
30
+ readonly abstorm: NaeilLocaleService;
31
+ readonly main: NaeilLocaleService;
32
+ readonly site: NaeilLocaleService;
33
+ readonly jev: NaeilLocaleService;
34
+ readonly estimate: NaeilLocaleService;
35
+ };
36
+ type LocaleServiceInput = NaeilLocaleService | NaeilServiceId;
37
+ declare function getLocaleService(service: LocaleServiceInput): NaeilLocaleService;
38
+ interface ResolvedLocaleRoute {
39
+ kind: "ui";
40
+ locale: NaeilLocale;
41
+ logicalPath: string;
42
+ route: NaeilRoute;
43
+ /** Canonical same-origin path, preserving non-language query and fragment. */
44
+ canonicalPath: string;
45
+ originalPath: string;
46
+ alias: boolean;
47
+ }
48
+ type LocaleUrlResolution = ResolvedLocaleRoute | {
49
+ kind: "protocol";
50
+ pathname: string;
51
+ } | {
52
+ kind: "invalid";
53
+ status: 400 | 404;
54
+ reason: string;
55
+ locale?: NaeilLocale;
56
+ };
57
+ /** Strict UI classification is not an auth/return validator. Call existing security validators separately. */
58
+ declare function resolveLocaleUrl(inputService: LocaleServiceInput, input: string): LocaleUrlResolution;
59
+ /** Input must be an unlocalized registered UI route. Does not validate login return destinations. */
60
+ declare function localePath(inputService: LocaleServiceInput, unlocalizedRoute: string, locale: NaeilLocale): string;
61
+ declare function localeHref(service: LocaleServiceInput, unlocalizedRoute: string, locale: NaeilLocale): string;
62
+ declare function sameLogicalRoute(service: LocaleServiceInput, left: string, right: string): boolean;
63
+
64
+ declare var naeil: {
65
+ header: {
66
+ nav: {
67
+ home: string;
68
+ projects: string;
69
+ blog: string;
70
+ navigation: string;
71
+ menu: string;
72
+ closeMenu: string;
73
+ };
74
+ theme: {
75
+ switchToLight: string;
76
+ switchToDark: string;
77
+ };
78
+ locale: {
79
+ switchLabel: string;
80
+ };
81
+ projects: {
82
+ cc: {
83
+ name: string;
84
+ description: string;
85
+ };
86
+ pkm: {
87
+ name: string;
88
+ description: string;
89
+ };
90
+ naeilUi: {
91
+ name: string;
92
+ description: string;
93
+ };
94
+ sa: {
95
+ name: string;
96
+ description: string;
97
+ };
98
+ babyAgent: {
99
+ name: string;
100
+ description: string;
101
+ };
102
+ status: {
103
+ active: string;
104
+ coming: string;
105
+ };
106
+ };
107
+ };
108
+ account: {
109
+ menu: string;
110
+ account: string;
111
+ login: string;
112
+ logout: string;
113
+ busy: string;
114
+ };
115
+ footer: {
116
+ navigation: string;
117
+ projects: string;
118
+ blog: string;
119
+ social: string;
120
+ description: string;
121
+ };
122
+ locale: {
123
+ names: {
124
+ en: string;
125
+ ko: string;
126
+ ja: string;
127
+ };
128
+ pending: string;
129
+ failed: string;
130
+ retry: string;
131
+ errors: {
132
+ badRequest: string;
133
+ notFound: string;
134
+ unauthenticated: string;
135
+ forbidden: string;
136
+ unavailable: string;
137
+ };
138
+ };
139
+ };
140
+ declare var en: {
141
+ naeil: typeof naeil;
142
+ };
143
+
144
+ declare const __messages_en_json_naeil: typeof naeil;
145
+ declare namespace __messages_en_json {
146
+ export { en as default, __messages_en_json_naeil as naeil };
147
+ }
148
+
149
+ interface LocaleMessages {
150
+ [key: string]: string | LocaleMessages;
151
+ }
152
+ type MessageModule = LocaleMessages | {
153
+ default: LocaleMessages;
154
+ };
155
+ type LocaleMessageLoaders = Record<NaeilLocale, () => Promise<MessageModule>>;
156
+ type SharedMessages = typeof __messages_en_json;
157
+ declare function loadSharedMessages(locale: NaeilLocale): Promise<SharedMessages>;
158
+ /** Every application dictionary has exactly its declared top-level namespace. */
159
+ declare function mergeLocaleMessages(shared: LocaleMessages, application: LocaleMessages, namespace: string): LocaleMessages;
160
+ declare function createLocaleMessageLoader(options: {
161
+ namespace: string;
162
+ messages: LocaleMessageLoaders;
163
+ }): (locale: NaeilLocale) => Promise<LocaleMessages>;
164
+ /** Runtime fallback is observable and is not a substitute for the build checker. */
165
+ declare function recoverMissingMessages(selected: LocaleMessages, english: LocaleMessages, onMissing: (key: string) => void, prefix?: string): LocaleMessages;
166
+
167
+ export { type LocaleMessages as L, type MessageModule as M, type NaeilLocale as N, type ResolvedLocaleRoute as R, type SharedMessages as S, type LocaleServiceInput as a, type LocaleMessageLoaders as b, type LocaleUrlResolution as c, type NaeilLocaleService as d, type NaeilRoute as e, type NaeilServiceId as f, assertLocale as g, defaultLocale as h, defineLocaleService as i, getLocaleService as j, isNaeilLocale as k, localeHref as l, localePath as m, naeilLocales as n, naeilRouting as o, naeilServices as p, createLocaleMessageLoader as q, resolveLocaleUrl as r, sameLogicalRoute as s, loadSharedMessages as t, mergeLocaleMessages as u, recoverMissingMessages as v };
@@ -0,0 +1 @@
1
+ export { b as LocaleMessageLoaders, L as LocaleMessages, M as MessageModule, S as SharedMessages, q as createLocaleMessageLoader, t as loadSharedMessages, u as mergeLocaleMessages, v as recoverMissingMessages } from './messages-BuQvB-u2.js';
@@ -0,0 +1,14 @@
1
+ import {
2
+ createLocaleMessageLoader,
3
+ loadSharedMessages,
4
+ mergeLocaleMessages,
5
+ recoverMissingMessages
6
+ } from "./chunk-4U64K4J3.js";
7
+ import "./chunk-U65OQHZY.js";
8
+ import "./chunk-N3ETBM74.js";
9
+ export {
10
+ createLocaleMessageLoader,
11
+ loadSharedMessages,
12
+ mergeLocaleMessages,
13
+ recoverMissingMessages
14
+ };
@@ -0,0 +1,75 @@
1
+ import * as next_intl_server from 'next-intl/server';
2
+ import { NextResponse, NextRequest } from 'next/server';
3
+ import { a as LocaleServiceInput, R as ResolvedLocaleRoute, N as NaeilLocale, b as LocaleMessageLoaders } from './messages-BuQvB-u2.js';
4
+ export { q as createLocaleMessageLoader, o as naeilRouting } from './messages-BuQvB-u2.js';
5
+
6
+ declare const localeRequestHeader: string;
7
+ declare const accessRequestHeader: string;
8
+ declare const pathRequestHeader: string;
9
+ type LocaleRequestKind = "document" | "rsc" | "action" | "other";
10
+ declare function localeRequestKind(request: Pick<NextRequest, "method" | "headers">): LocaleRequestKind;
11
+ /** Only read after createNaeilLocaleProxy has replaced external marker headers. */
12
+ declare function getRequestLocale(headers: Pick<Headers, "get">, fallback?: NaeilLocale): NaeilLocale;
13
+ /** A rendering hint, never authorization. Pages must still check data access. */
14
+ declare function getRequestLocaleAccess(headers: Pick<Headers, "get">): "allowed" | "unauthenticated" | "forbidden" | "unavailable" | undefined;
15
+ declare function createNaeilRequestConfig(options: {
16
+ namespace: string;
17
+ messages: LocaleMessageLoaders;
18
+ onMessageError?: (error: Error) => void;
19
+ }): (params: next_intl_server.GetRequestConfigParams) => next_intl_server.RequestConfig | Promise<next_intl_server.RequestConfig>;
20
+ interface LocaleProxyAuthorization {
21
+ access: "allowed" | "unauthenticated" | "forbidden" | "unavailable";
22
+ /** Document denial/redirect only. RSC denials render the app access boundary. */
23
+ response?: NextResponse;
24
+ /** Existing refreshed auth response; its Set-Cookie values are retained. */
25
+ cookiesFrom?: NextResponse;
26
+ /** Updated request cookies/headers from the app's existing auth refresh. */
27
+ requestHeaders?: Headers;
28
+ }
29
+ interface NaeilLocaleProxyOptions {
30
+ service: LocaleServiceInput;
31
+ /** Existing app-validated origin, e.g. a local proxy behind a trusted ingress.
32
+ * Never return an unvalidated forwarded Host. This is not an auth allowlist. */
33
+ requestOrigin?: (request: NextRequest) => string;
34
+ /** Runs first for exact existing protocol/security boundaries. */
35
+ protocol?: (request: NextRequest) => NextResponse | null | undefined | Promise<NextResponse | null | undefined>;
36
+ authorize?: (context: {
37
+ request: NextRequest;
38
+ route: ResolvedLocaleRoute;
39
+ kind: LocaleRequestKind;
40
+ locale: NaeilLocale;
41
+ logicalPath: string;
42
+ }) => LocaleProxyAuthorization | Promise<LocaleProxyAuthorization>;
43
+ }
44
+ /** Auth decisions precede alias canonicalization; no locale rewrite reaches protocol handlers. */
45
+ declare function createNaeilLocaleProxy(options: NaeilLocaleProxyOptions): (original: NextRequest) => Promise<NextResponse>;
46
+ declare function localeMetadata(options: {
47
+ service: LocaleServiceInput;
48
+ route: string;
49
+ locale: NaeilLocale;
50
+ title: string;
51
+ serviceName: string;
52
+ public?: boolean;
53
+ translatedLocales?: readonly NaeilLocale[];
54
+ description?: string;
55
+ }): {
56
+ title: string;
57
+ description: string | undefined;
58
+ robots: {
59
+ index: boolean;
60
+ follow: boolean;
61
+ };
62
+ alternates?: undefined;
63
+ } | {
64
+ title: string;
65
+ description: string | undefined;
66
+ alternates: {
67
+ canonical: string;
68
+ languages: {
69
+ [k: string]: string;
70
+ };
71
+ };
72
+ robots?: undefined;
73
+ };
74
+
75
+ export { type LocaleProxyAuthorization, type LocaleRequestKind, type NaeilLocaleProxyOptions, accessRequestHeader, createNaeilLocaleProxy, createNaeilRequestConfig, getRequestLocale, getRequestLocaleAccess, localeMetadata, localeRequestHeader, localeRequestKind, pathRequestHeader };
@@ -0,0 +1,172 @@
1
+ import {
2
+ createLocaleMessageLoader,
3
+ loadSharedMessages,
4
+ recoverMissingMessages
5
+ } from "./chunk-4U64K4J3.js";
6
+ import {
7
+ assertLocale,
8
+ getLocaleService,
9
+ localeHref,
10
+ localePath,
11
+ naeilLocales,
12
+ naeilRouting,
13
+ resolveLocaleUrl
14
+ } from "./chunk-U65OQHZY.js";
15
+ import "./chunk-N3ETBM74.js";
16
+
17
+ // src/naeil-locale/server.ts
18
+ import "server-only";
19
+ import { NextRequest, NextResponse } from "next/server";
20
+ import createIntlMiddleware from "next-intl/middleware";
21
+ import { getRequestConfig } from "next-intl/server";
22
+ var localeRequestHeader = "x-naeil-locale";
23
+ var accessRequestHeader = "x-naeil-locale-access";
24
+ var pathRequestHeader = "x-naeil-locale-path";
25
+ var privateHeaders = [localeRequestHeader, accessRequestHeader, pathRequestHeader, "x-next-intl-locale"];
26
+ function localeRequestKind(request) {
27
+ if (request.headers.has("next-action")) return "action";
28
+ if (request.headers.get("rsc") === "1" || request.headers.has("next-router-state-tree") || request.headers.has("next-router-prefetch")) return "rsc";
29
+ const mode = request.headers.get("sec-fetch-mode");
30
+ if ((request.method === "GET" || request.method === "HEAD") && request.headers.get("sec-fetch-dest") === "empty" && (mode === "cors" || mode === "same-origin")) return "rsc";
31
+ return request.method === "GET" || request.method === "HEAD" ? "document" : "other";
32
+ }
33
+ function getRequestLocale(headers, fallback = "en") {
34
+ const locale = headers.get(localeRequestHeader);
35
+ return locale === null ? assertLocale(fallback) : assertLocale(locale);
36
+ }
37
+ function getRequestLocaleAccess(headers) {
38
+ const value = headers.get(accessRequestHeader);
39
+ if (value === "allowed" || value === "unauthenticated" || value === "forbidden" || value === "unavailable") return value;
40
+ }
41
+ function createNaeilRequestConfig(options) {
42
+ const load = createLocaleMessageLoader(options);
43
+ return getRequestConfig(async ({ requestLocale }) => {
44
+ var _a;
45
+ const locale = assertLocale((_a = await requestLocale) != null ? _a : "en");
46
+ const selected = await load(locale);
47
+ const messages = locale === "en" ? selected : recoverMissingMessages(selected, await load("en"), (key) => {
48
+ const error = new Error(`Missing ${locale} translation: ${key}`);
49
+ if (options.onMessageError) options.onMessageError(error);
50
+ else console.error(error.message);
51
+ });
52
+ return { locale, messages, timeZone: "UTC" };
53
+ });
54
+ }
55
+ function copyCookies(from, to) {
56
+ from == null ? void 0 : from.cookies.getAll().forEach((cookie) => to.cookies.set(cookie));
57
+ return to;
58
+ }
59
+ function stripMarkers(headers) {
60
+ const sanitized = new Headers(headers);
61
+ for (const key of privateHeaders) sanitized.delete(key);
62
+ return sanitized;
63
+ }
64
+ function sanitizeProtocolPassThrough(response, requestHeaders) {
65
+ var _a;
66
+ if (response.headers.get("x-middleware-next") !== "1" && !response.headers.has("x-middleware-rewrite")) return response;
67
+ const forwarded = new Headers(requestHeaders);
68
+ for (const key of ((_a = response.headers.get("x-middleware-override-headers")) != null ? _a : "").split(",")) {
69
+ if (!key) continue;
70
+ const value = response.headers.get(`x-middleware-request-${key}`);
71
+ if (value !== null) forwarded.set(key, value);
72
+ }
73
+ for (const key of privateHeaders) {
74
+ forwarded.delete(key);
75
+ response.headers.delete(`x-middleware-request-${key}`);
76
+ }
77
+ const names = [];
78
+ for (const [key, value] of forwarded) {
79
+ names.push(key);
80
+ response.headers.set(`x-middleware-request-${key}`, value);
81
+ }
82
+ response.headers.set("x-middleware-override-headers", names.join(","));
83
+ return response;
84
+ }
85
+ function markPrivate(response) {
86
+ response.headers.set("Cache-Control", "private, no-store");
87
+ return response;
88
+ }
89
+ function escapeHtml(value) {
90
+ return value.replace(/[&<>"']/g, (char) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[char]);
91
+ }
92
+ async function invalidResponse(status, service, kind, locale = "en") {
93
+ if (kind !== "document") return markPrivate(new NextResponse(null, { status }));
94
+ const copy = (await loadSharedMessages(locale)).naeil.locale;
95
+ const message = copy.errors[status === 400 ? "badRequest" : status === 401 ? "unauthenticated" : status === 403 ? "forbidden" : status === 503 ? "unavailable" : "notFound"];
96
+ const id = getLocaleService(service).id;
97
+ const identity = { abstorm: { name: "abstorm", icon: null }, main: { name: ".naeil", icon: "/icon.svg" }, jev: { name: "Jev", icon: null }, estimate: { name: "AB Estimate", icon: "/favicon.svg" } }[id];
98
+ const links = naeilLocales.map((language) => `<li><a lang="${language}" href="${escapeHtml(localePath(service, "/", language))}">${escapeHtml(copy.names[language])}</a></li>`).join("");
99
+ return markPrivate(new NextResponse(`<!doctype html><html lang="${locale}"><head><meta name="robots" content="noindex"><meta name="viewport" content="width=device-width,initial-scale=1">${identity.icon ? `<link rel="icon" href="${identity.icon}">` : ""}<title>${escapeHtml(message)} \u2014 ${identity.name}</title></head><body><h1>${status}</h1><p>${escapeHtml(message)}</p><ul>${links}</ul></body></html>`, { status, headers: { "Content-Type": "text/html; charset=utf-8" } }));
100
+ }
101
+ function createNaeilLocaleProxy(options) {
102
+ const service = getLocaleService(options.service);
103
+ const intl = createIntlMiddleware(naeilRouting);
104
+ return async function naeilLocaleProxy(original) {
105
+ var _a, _b, _c, _d, _e, _f;
106
+ const sanitized = stripMarkers(original.headers);
107
+ const request = new NextRequest(original, { headers: sanitized });
108
+ const protocol = await ((_a = options.protocol) == null ? void 0 : _a.call(options, request));
109
+ if (protocol) return sanitizeProtocolPassThrough(protocol, sanitized);
110
+ const kind = localeRequestKind(request);
111
+ const raw = new URL(request.url);
112
+ const origin = (_c = (_b = options.requestOrigin) == null ? void 0 : _b.call(options, request)) != null ? _c : raw.origin;
113
+ const parsedOrigin = new URL(origin);
114
+ if (parsedOrigin.origin !== origin || !["https:", "http:"].includes(parsedOrigin.protocol)) throw new Error("Expected a validated HTTP request origin");
115
+ const result = resolveLocaleUrl(service, raw.pathname + raw.search);
116
+ if (result.kind === "protocol") return NextResponse.next({ request: { headers: sanitized } });
117
+ if (result.kind === "invalid") return invalidResponse(result.status, service, kind, result.locale);
118
+ const authorization = options.authorize ? await options.authorize({ request, route: result, kind, locale: result.locale, logicalPath: result.logicalPath }) : { access: result.route.protected ? "unavailable" : "allowed" };
119
+ const authHeaders = stripMarkers((_d = authorization.requestHeaders) != null ? _d : sanitized);
120
+ if (authorization.access !== "allowed" && kind === "document") {
121
+ return copyCookies(authorization.cookiesFrom, markPrivate((_e = authorization.response) != null ? _e : await invalidResponse(authorization.access === "unauthenticated" ? 401 : authorization.access === "forbidden" ? 403 : 503, service, kind, result.locale)));
122
+ }
123
+ if (authorization.access !== "allowed" && kind !== "rsc") return copyCookies(authorization.cookiesFrom, markPrivate(new NextResponse(null, { status: authorization.access === "unauthenticated" ? 401 : authorization.access === "forbidden" ? 403 : 503 })));
124
+ if (result.alias && kind === "document") return copyCookies(authorization.cookiesFrom, NextResponse.redirect(new URL(result.canonicalPath, origin), 307));
125
+ if (result.alias && kind !== "document") return copyCookies(authorization.cookiesFrom, await invalidResponse(400, service, kind, result.locale));
126
+ authHeaders.set(localeRequestHeader, result.locale);
127
+ authHeaders.set("x-next-intl-locale", result.locale);
128
+ authHeaders.set(pathRequestHeader, result.logicalPath);
129
+ authHeaders.set(accessRequestHeader, authorization.access);
130
+ const response = intl(new NextRequest(request, { headers: authHeaders }));
131
+ const rewrite = response.headers.get("x-middleware-rewrite");
132
+ if (rewrite && options.requestOrigin) {
133
+ const target = new URL(rewrite);
134
+ target.host = parsedOrigin.host;
135
+ target.protocol = parsedOrigin.protocol;
136
+ response.headers.set("x-middleware-rewrite", target.href);
137
+ }
138
+ const forwarded = new Set(((_f = response.headers.get("x-middleware-override-headers")) != null ? _f : "").split(",").filter(Boolean));
139
+ for (const [key, value] of authHeaders) {
140
+ forwarded.add(key);
141
+ response.headers.set(`x-middleware-request-${key}`, value);
142
+ }
143
+ response.headers.set("x-middleware-override-headers", [...forwarded].join(","));
144
+ response.headers.delete("link");
145
+ if (result.route.protected || authorization.access !== "allowed") markPrivate(response);
146
+ return copyCookies(authorization.cookiesFrom, response);
147
+ };
148
+ }
149
+ function localeMetadata(options) {
150
+ var _a;
151
+ const locale = assertLocale(options.locale);
152
+ const title = options.title ? `${options.title} \u2014 ${options.serviceName}` : options.serviceName;
153
+ if (!options.public) return { title, description: options.description, robots: { index: false, follow: false } };
154
+ const translated = (_a = options.translatedLocales) != null ? _a : naeilLocales;
155
+ if (!translated.includes(locale)) throw new Error("Cannot advertise untranslated page");
156
+ const languages = Object.fromEntries(translated.map((language) => [language, localeHref(options.service, options.route, language)]));
157
+ if (translated.includes("en")) languages["x-default"] = localeHref(options.service, options.route, "en");
158
+ return { title, description: options.description, alternates: { canonical: localeHref(options.service, options.route, locale), languages } };
159
+ }
160
+ export {
161
+ accessRequestHeader,
162
+ createLocaleMessageLoader,
163
+ createNaeilLocaleProxy,
164
+ createNaeilRequestConfig,
165
+ getRequestLocale,
166
+ getRequestLocaleAccess,
167
+ localeMetadata,
168
+ localeRequestHeader,
169
+ localeRequestKind,
170
+ naeilRouting,
171
+ pathRequestHeader
172
+ };
@@ -0,0 +1,16 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { SiteFooterProps } from './ui/site-footer.js';
3
+ import { NaeilHeaderLocale } from './naeil-header-data.js';
4
+ import 'react';
5
+ import './ui/navigation.js';
6
+
7
+ type NaeilFooterLocale = NaeilHeaderLocale;
8
+ interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description" | "groups"> {
9
+ locale: NaeilFooterLocale;
10
+ /** Only localize/route canonical paths; default destinations use the official origin. */
11
+ resolveHref?: (path: string) => string;
12
+ }
13
+ /** Canonical content in full/compact density. Product legal/status copy belongs in meta. */
14
+ declare function NaeilFooter({ locale, resolveHref, variant, Link, onNavigate, ...props }: NaeilFooterProps): react_jsx_runtime.JSX.Element;
15
+
16
+ export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps };